]> git.sur5r.net Git - cc65/commitdiff
Cleaned up the code used for handling jump labels and the label name.
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 7 Jun 2004 21:16:49 +0000 (21:16 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 7 Jun 2004 21:16:49 +0000 (21:16 +0000)
Fixed a problem that caused the optimizer not to detect that flags set by
a load are used, if the use is "hidden" behind an unconditional branch. This
caused the optimizer to remove the load.

git-svn-id: svn://svn.cc65.org/cc65/trunk@3111 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/codeent.c
src/cc65/codeent.h
src/cc65/codeseg.c

index e87311c307b6c780ace2f1da3cb58eba0207de33..233080712a6d795e0554d671c95b740e9a20d60c 100644 (file)
@@ -323,6 +323,22 @@ void CE_AttachLabel (CodeEntry* E, CodeLabel* L)
 
 
 
+void CE_ClearJumpTo (CodeEntry* E)
+/* Clear the JumpTo entry and the argument (which contained the name of the
+ * label). Note: The function will not clear the backpointer from the label,
+ * so use it with care.
+ */
+{
+    /* Clear the JumpTo entry */
+    E->JumpTo = 0;
+
+    /* Clear the argument and assign the empty one */
+    FreeArg (E->Arg);
+    E->Arg = EmptyArg;
+}
+
+
+
 void CE_MoveLabel (CodeLabel* L, CodeEntry* E)
 /* Move the code label L from it's former owner to the code entry E. */
 {
@@ -391,6 +407,33 @@ int CE_UseLoadFlags (const CodeEntry* E)
  * a register (N and Z).
  */
 {
+    /* Follow unconditional branches, but beware of endless loops. After this,
+     * E will point to the first entry that is not a branch.
+     */
+    if (E->Info & OF_UBRA) {
+        Collection C = AUTO_COLLECTION_INITIALIZER;
+
+        /* Follow the chain */
+        while (E->Info & OF_UBRA) {
+
+            /* Remember the entry so we can detect loops */
+            CollAppend (&C, (void*) E);
+
+            /* Check the target */
+            if (E->JumpTo == 0 || CollIndex (&C, E->JumpTo->Owner) >= 0) {
+                /* Unconditional jump to external symbol, or endless loop. */
+                DoneCollection (&C);
+                return 0;       /* Flags not used */
+            }
+
+            /* Follow the chain */
+            E = E->JumpTo->Owner;
+        }
+
+        /* Delete the collection */
+        DoneCollection (&C);
+    }
+
     /* A branch will use the flags */
     if (E->Info & OF_FBRA) {
         return 1;
@@ -429,7 +472,7 @@ void CE_FreeRegInfo (CodeEntry* E)
 /* Free an existing register info struct */
 {
     if (E->RI) {
-       FreeRegInfo (E->RI);
+               FreeRegInfo (E->RI);
        E->RI = 0;
     }
 }
index 2c42faf35ec7e8aa3757b0385f9d5a78f8bcf5c2..99c003b741ee04bc327b301cf02e78824d1b33a3 100644 (file)
@@ -115,6 +115,12 @@ int CodeEntriesAreEqual (const CodeEntry* E1, const CodeEntry* E2);
 void CE_AttachLabel (CodeEntry* E, CodeLabel* L);
 /* Attach the label to the entry */
 
+void CE_ClearJumpTo (CodeEntry* E);
+/* Clear the JumpTo entry and the argument (which contained the name of the
+ * label). Note: The function will not clear the backpointer from the label,
+ * so use it with care.
+ */
+
 #if defined(HAVE_INLINE)
 INLINE int CE_HasLabel (const CodeEntry* E)
 /* Check if the given code entry has labels attached */
@@ -157,7 +163,7 @@ INLINE int CE_HasMark (const CodeEntry* E)
 #else
 #  define CE_HasMark(E)        (((E)->Flags & CEF_USERMARK) != 0)
 #endif
-   
+
 #if defined(HAVE_INLINE)
 INLINE void CE_SetMark (CodeEntry* E)
 /* Set the CEF_USERMARK flag for the given entry */
index 8eb594f798903c307c38999accf1d535d39b713f..1126e08ee1564de18f3928cb1e7b15fc1f4e559c 100644 (file)
@@ -829,7 +829,7 @@ void CS_DelLabel (CodeSeg* S, CodeLabel* L)
                /* Get the insn referencing this label */
                CodeEntry* E = CollAt (&L->JumpFrom, I);
                /* Remove the reference */
-               E->JumpTo = 0;
+               CE_ClearJumpTo (E);
     }
     CollDeleteAll (&L->JumpFrom);
 
@@ -875,7 +875,10 @@ void CS_MergeLabels (CodeSeg* S)
                for (J = 0; J < CL_GetRefCount (X); ++J) {
                    /* Get the entry referencing this label */
                    CodeEntry* E = CL_GetRef (X, J);
-                   /* And remove the reference */
+                   /* And remove the reference. Do NOT call CE_ClearJumpTo
+                     * here, because this will also clear the label name,
+                     * which is not what we want.
+                     */
                    E->JumpTo = 0;
                }
 
@@ -999,7 +1002,7 @@ void CS_RemoveLabelRef (CodeSeg* S, struct CodeEntry* E)
     CollDeleteItem (&L->JumpFrom, E);
 
     /* The entry jumps no longer to L */
-    E->JumpTo = 0;
+    CE_ClearJumpTo (E);
 
     /* If there are no more references, delete the label */
     if (CollCount (&L->JumpFrom) == 0) {