]> git.sur5r.net Git - cc65/commitdiff
Remove more push/pop sequences.
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 15 Aug 2009 10:27:41 +0000 (10:27 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 15 Aug 2009 10:27:41 +0000 (10:27 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@4010 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/coptind.c

index 67fa1f7e57477376ef01460914c88e64a8aef435..e72f6c28d9e796ddbb9c47a4c92dda1897ca6023 100644 (file)
 
 
 
+static int MemAccess (CodeSeg* S, unsigned From, unsigned To, const char* Arg)
+/* Checks a range of code entries if there are any memory accesses to Arg.
+ * Note: This function is not 100% safe, because there is more than one way
+ * to express a memory location ("foo" and "foo+0" comes to mind) and there
+ * may be other accesses through pointers. For the code generated by cc65 and
+ * for the purpose of the caller (OptPushPop) it is assumed to be safe enough
+ * however.
+ */
+{
+    /* Walk over all code entries */
+    while (From <= To) {
+
+       /* Get the next entry */
+       CodeEntry* E = CS_GetEntry (S, From);
+
+        /* For simplicity, we just check if there is an argument and if this
+         * argument equals Arg.
+         */
+        if (E->Arg && strcmp (E->Arg, Arg) == 0) {
+            /* Found an access */
+            return 1;
+        }
+
+        /* Next entry */
+        ++From;
+    }
+
+    /* Nothing found */
+    return 0;
+}
+
+
+
 static int GetBranchDist (CodeSeg* S, unsigned From, CodeEntry* To)
 /* Get the branch distance between the two entries and return it. The distance
  * will be negative for backward jumps and positive for forward jumps.
@@ -1225,6 +1258,8 @@ unsigned OptPushPop (CodeSeg* S)
     unsigned I = 0;
     while (I < CS_GetEntryCount (S)) {
 
+        CodeEntry* X;
+
        /* Get next entry */
                CodeEntry* E = CS_GetEntry (S, I);
 
@@ -1245,19 +1280,47 @@ unsigned OptPushPop (CodeSeg* S)
                 } else if (E->OPC == OP65_PLA) {
                     /* Found a matching pop */
                     Pop = I;
-                    State = FoundPop;
+                    /* Check that the block between Push and Pop is a basic
+                     * block (one entry, one exit). Otherwise ignore it.
+                     */
+                    if (CS_IsBasicBlock (S, Push, Pop)) {
+                        State = FoundPop;
+                    } else {
+                        /* Go into searching mode again */
+                        State = Searching;
+                    }
                 }
                 break;
 
             case FoundPop:
-                /* Next insn, just check if it is no conditional branch and
-                 * that A is not used later. Check also that the range we have
-                 * found now is a basic block, which means that the PHA is the
-                 * only entrance and the PLA the only exit.
+                /* We're at the instruction after the PLA.
+                 * Check for the following conditions:
+                 *   - If this instruction is a store of A, and A is not used
+                 *     later, we may replace the PHA by the store and remove
+                 *     pla if several other conditions are met.
+                 *   - If this instruction is not a conditional branch, and A
+                 *     is unused later, we may remove PHA and PLA.
                  */
-                if ((E->Info & OF_CBRA) == 0    &&
-                    !RegAUsed (S, I)            &&
-                    CS_IsBasicBlock (S, Push, Pop)) {
+                if (E->OPC == OP65_STA                  &&
+                    !RegAUsed (S, I+1)                  &&
+                    !MemAccess (S, Push+1, Pop-1, E->Arg)) {
+
+                    /* Insert a STA before the PHA */
+                    X = NewCodeEntry (E->OPC, E->AM, E->Arg, E->JumpTo, E->LI);
+                    CS_InsertEntry (S, X, Push);
+
+                    /* Remove the PHA instead */
+                    CS_DelEntry (S, Push+1);
+
+                    /* Remove the PLA/STA sequence */
+                    CS_DelEntries (S, Pop, 2);
+
+                    /* Remember we had changes */
+                    ++Changes;
+
+                } else if ((E->Info & OF_CBRA) == 0     &&
+                           !RegAUsed (S, I)) {
+
                     /* We can remove the PHA and PLA instructions */
                     CS_DelEntry (S, Pop);
                     CS_DelEntry (S, Push);
@@ -1265,6 +1328,7 @@ unsigned OptPushPop (CodeSeg* S)
                     I -= 2;
                     /* Remember we had changes */
                     ++Changes;
+
                 }
                 /* Go into search mode again */
                 State = Searching;