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
+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. */
{
* 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;
/* Free an existing register info struct */
{
if (E->RI) {
- FreeRegInfo (E->RI);
+ FreeRegInfo (E->RI);
E->RI = 0;
}
}
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 */
#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 */
/* Get the insn referencing this label */
CodeEntry* E = CollAt (&L->JumpFrom, I);
/* Remove the reference */
- E->JumpTo = 0;
+ CE_ClearJumpTo (E);
}
CollDeleteAll (&L->JumpFrom);
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;
}
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) {