]> git.sur5r.net Git - cc65/commitdiff
Fixed a problem in the optimizer function that rewrites ops that use the
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Wed, 20 Jan 2010 19:47:44 +0000 (19:47 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Wed, 20 Jan 2010 19:47:44 +0000 (19:47 +0000)
stack. Useless instructions (duplicate loads or transfers) within the sequence
are left intact and may cause problems because the interfere with the
replacement code. A run of OptRemoveUnusedLoads and friends should fix the
problem, bit this step may be disabled, so the routine has to check for this
condition and avoid it (by not doing the replacement).

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

src/cc65/coptstop.c

index 50fd73b4e6b6f7d158024d262875dc5b42d1166a..620a73504e52d7aba8fe303dcb61605846d32af7 100644 (file)
@@ -58,6 +58,7 @@ typedef enum {
   LI_DIRECT             = 0x01,         /* Direct op may be used */
   LI_RELOAD_Y           = 0x02,         /* Reload index register Y */
   LI_REMOVE             = 0x04,         /* Load may be removed */
+  LI_DUP_LOAD           = 0x08,         /* Duplicate load */
 } LI_FLAGS;
 
 /* Structure that tells us how to load the lhs values */
@@ -258,9 +259,17 @@ static void TrackLoads (LoadInfo* LI, CodeEntry* E, int I)
             RI = &LI->X;
         } else if (E->Chg & REG_Y) {
             RI = &LI->Y;
-        } 
+        }
         CHECK (RI != 0);
 
+        /* If we had a load or xfer op before, this is a duplicate load which
+         * can cause problems if it encountered between the pushax and the op,
+         * so remember it.
+         */
+        if (RI->LoadIndex >= 0 || RI->XferIndex >= 0) {
+            RI->Flags |= LI_DUP_LOAD;
+        }
+
         /* Remember the load */
         RI->LoadIndex = I;
         RI->XferIndex = -1;
@@ -299,6 +308,14 @@ static void TrackLoads (LoadInfo* LI, CodeEntry* E, int I)
             default:            Internal ("Unknown XFR insn in TrackLoads");
         }
 
+        /* If we had a load or xfer op before, this is a duplicate load which
+         * can cause problems if it encountered between the pushax and the op,
+         * so remember it.
+         */
+        if (Tgt->LoadIndex >= 0 || Tgt->XferIndex >= 0) {
+            Tgt->Flags |= LI_DUP_LOAD;
+        }
+
         /* Transfer the data */
         Tgt->LoadIndex  = Src->LoadIndex;
         Tgt->XferIndex  = I;
@@ -308,6 +325,17 @@ static void TrackLoads (LoadInfo* LI, CodeEntry* E, int I)
 
     } else if (CE_IsCallTo (E, "ldaxysp") && RegValIsKnown (E->RI->In.RegY)) {
 
+        /* If we had a load or xfer op before, this is a duplicate load which
+         * can cause problems if it encountered between the pushax and the op,
+         * so remember it for both registers involved.
+         */
+        if (LI->A.LoadIndex >= 0 || LI->A.XferIndex >= 0) {
+            LI->A.Flags |= LI_DUP_LOAD;
+        }
+        if (LI->X.LoadIndex >= 0 || LI->X.XferIndex >= 0) {
+            LI->X.Flags |= LI_DUP_LOAD;
+        }
+
         /* Both registers set, Y changed */
         LI->A.LoadIndex = I;
         LI->A.XferIndex = -1;
@@ -1659,6 +1687,10 @@ static int PreCondOk (StackOpData* D)
             }
         }
     }
+    if ((D->Rhs.A.Flags | D->Rhs.X.Flags) & LI_DUP_LOAD) {
+        /* Cannot optimize */
+        return 0;
+    }
 
     /* Determine the zero page locations to use */
     if ((D->UsedRegs & REG_PTR1) == REG_NONE) {