]> git.sur5r.net Git - cc65/commitdiff
New optimization
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 14 Sep 2003 09:54:24 +0000 (09:54 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 14 Sep 2003 09:54:24 +0000 (09:54 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@2436 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/codeopt.c
src/cc65/coptind.c
src/cc65/coptind.h

index 31bcfb3906a07a0f11ba322df273f13dbb114de6..cfa114f9774de37caf03c5a3facbb7533eecddb7 100644 (file)
@@ -1542,7 +1542,8 @@ static OptFunc DOptStoreLoad      = { OptStoreLoad,    "OptStoreLoad",      0, 0,
 static OptFunc DOptSub1                = { OptSub1,         "OptSub1",         100, 0, 0, 0, 0, 0 };
 static OptFunc DOptSub2                = { OptSub2,         "OptSub2",         100, 0, 0, 0, 0, 0 };
 static OptFunc DOptTest1               = { OptTest1,        "OptTest1",        100, 0, 0, 0, 0, 0 };
-static OptFunc DOptTransfers           = { OptTransfers,    "OptTransfers",      0, 0, 0, 0, 0, 0 };
+static OptFunc DOptTransfers1          = { OptTransfers1,   "OptTransfers1",     0, 0, 0, 0, 0, 0 };
+static OptFunc DOptTransfers2          = { OptTransfers2,   "OptTransfers2",    60, 0, 0, 0, 0, 0 };
 static OptFunc DOptUnusedLoads         = { OptUnusedLoads,  "OptUnusedLoads",    0, 0, 0, 0, 0, 0 };
 static OptFunc DOptUnusedStores        = { OptUnusedStores, "OptUnusedStores",   0, 0, 0, 0, 0, 0 };
 
@@ -1610,7 +1611,8 @@ static OptFunc* OptFuncs[] = {
     &DOptSub1,
     &DOptSub2,
     &DOptTest1,
-    &DOptTransfers,
+    &DOptTransfers1,
+    &DOptTransfers2,
     &DOptUnusedLoads,
     &DOptUnusedStores,
 };
@@ -1781,15 +1783,15 @@ static void WriteOptStats (const char* Name)
 
     /* Write a header */
     fprintf (F,
-            "; Optimizer           Total  Last   Total  Last\n"
-                    ";   Step              Runs   Runs    Chg   Chg\n");
+            "; Optimizer               Total      Last       Total      Last\n"
+                    ";   Step                  Runs       Runs        Chg       Chg\n");        
 
 
     /* Write the data */
     for (I = 0; I < OPTFUNC_COUNT; ++I) {
        const OptFunc* O = OptFuncs[I];
        fprintf (F,
-                        "%-20s %6lu %6lu %6lu %6lu\n",
+                        "%-20s %10lu %10lu %10lu %10lu\n",
                 O->Name,
                 O->TotalRuns,
                 O->LastRuns,
@@ -1934,7 +1936,7 @@ static unsigned RunOptGroup3 (CodeSeg* S)
                C += RunOptFunc (S, &DOptUnusedStores, 1);
                C += RunOptFunc (S, &DOptDupLoads, 1);
                C += RunOptFunc (S, &DOptStoreLoad, 1);
-               C += RunOptFunc (S, &DOptTransfers, 1);
+               C += RunOptFunc (S, &DOptTransfers1, 1);
         C += RunOptFunc (S, &DOptPushPop, 1);
 
        Changes += C;
@@ -1981,6 +1983,7 @@ static unsigned RunOptGroup5 (CodeSeg* S)
     Changes += RunOptFunc (S, &DOptPush1, 1);
     Changes += RunOptFunc (S, &DOptPush2, 1);
     Changes += RunOptFunc (S, &DOptUnusedLoads, 1);
+    Changes += RunOptFunc (S, &DOptTransfers2, 1);
 
     /* Return the number of changes */
     return Changes;
index 23007611d30ddba2bc46b46a9ba8f418c4475497..3bfb879df96153fd9e7ec8b7ea7e75c903593a7f 100644 (file)
@@ -1065,7 +1065,7 @@ unsigned OptStoreLoad (CodeSeg* S)
 
 
 
-unsigned OptTransfers (CodeSeg* S)
+unsigned OptTransfers1 (CodeSeg* S)
 /* Remove transfers from one register to another and back */
 {
     unsigned Changes = 0;
@@ -1081,9 +1081,7 @@ unsigned OptTransfers (CodeSeg* S)
        /* Get next entry */
                CodeEntry* E = CS_GetEntry (S, I);
 
-       /* Check if it is a store instruction followed by a load from the
-        * same address which is itself not followed by a conditional branch.
-        */
+       /* Check if we have two transfer instructions */
                if ((E->Info & OF_XFR) != 0                 &&
            (N = CS_GetNextEntry (S, I)) != 0       &&
            !CE_HasLabel (N)                        &&
@@ -1135,6 +1133,82 @@ NextEntry:
 
 
 
+unsigned OptTransfers2 (CodeSeg* S)
+/* Replace loads followed by a register transfer by a load with the second
+ * register if possible.
+ */
+{
+    unsigned Changes = 0;
+
+    /* Walk over the entries */
+    unsigned I = 0;
+    while (I < CS_GetEntryCount (S)) {
+
+       CodeEntry* N;
+
+       /* Get next entry */
+               CodeEntry* E = CS_GetEntry (S, I);
+
+       /* Check if we have a load followed by a transfer where the loaded
+         * register is not used later.
+         */
+               if ((E->Info & OF_LOAD) != 0                &&
+                   (N = CS_GetNextEntry (S, I)) != 0       &&
+           !CE_HasLabel (N)                        &&
+                   (N->Info & OF_XFR) != 0                 &&
+            GetRegInfo (S, I+2, E->Chg) != E->Chg) {
+
+            CodeEntry* X = 0;
+
+            if (E->OPC == OP65_LDA && N->OPC == OP65_TAX) {
+                /* LDA/TAX - check for the right addressing modes */
+                if (E->AM == AM65_IMM ||
+                    E->AM == AM65_ZP  ||
+                    E->AM == AM65_ABS ||
+                    E->AM == AM65_ABSY) {
+                    /* Replace */
+                    X = NewCodeEntry (OP65_LDX, E->AM, E->Arg, 0, N->LI);
+                }
+            } else if (E->OPC == OP65_LDA && N->OPC == OP65_TAY) {
+                /* LDA/TAY - check for the right addressing modes */
+                if (E->AM == AM65_IMM ||
+                    E->AM == AM65_ZP  ||
+                    E->AM == AM65_ZPX ||
+                    E->AM == AM65_ABS ||
+                    E->AM == AM65_ABSX) {
+                    /* Replace */
+                    X = NewCodeEntry (OP65_LDY, E->AM, E->Arg, 0, N->LI);
+                }
+            } else if (E->OPC == OP65_LDY && N->OPC == OP65_TYA) {
+                /* LDY/TYA. LDA supports all addressing modes LDY does */
+                X = NewCodeEntry (OP65_LDA, E->AM, E->Arg, 0, N->LI);
+            } else if (E->OPC == OP65_LDX && N->OPC == OP65_TXA) {
+                /* LDX/TXA. LDA doesn't support zp,y, so we must map it to
+                 * abs,y instead.
+                 */
+                am_t AM = (E->AM == AM65_ZPY)? AM65_ABSY : E->AM;
+                X = NewCodeEntry (OP65_LDA, AM, E->Arg, 0, N->LI);
+            }
+
+            /* If we have a load entry, add it and remove the old stuff */
+            if (X) {
+                CS_InsertEntry (S, X, I+2);
+                CS_DelEntries (S, I, 2);
+                ++Changes;
+                --I;    /* Correct for one entry less */
+            }
+       }
+
+       /* Next entry */
+       ++I;
+    }
+
+    /* Return the number of changes made */
+    return Changes;
+}
+
+
+
 unsigned OptPushPop (CodeSeg* S)
 /* Remove a PHA/PLA sequence were A is not used later */
 {
@@ -1264,7 +1338,6 @@ unsigned OptPrecalc (CodeSeg* S)
                     } else if (E->AM == AM65_ZP) {
                         int R = ZPRegVal (E->Use, In);
                         if (RegValIsKnown (R)) {
-                            printf ("A: %02X  tmp1: %02X\n", In->RegA, R);
                             /* Accu EOR zp with known contents */
                             Arg = MakeHexArg (In->RegA ^ R);
                         }
index abad65359202b6e86da89c2b3cc9812cc2e272df..ae72b1fbbf98b4191d14c0ec048423c99d426cca 100644 (file)
@@ -102,9 +102,14 @@ unsigned OptDupLoads (CodeSeg* S);
 unsigned OptStoreLoad (CodeSeg* S);
 /* Remove a store followed by a load from the same location. */
 
-unsigned OptTransfers (CodeSeg* S);
+unsigned OptTransfers1 (CodeSeg* S);
 /* Remove transfers from one register to another and back */
 
+unsigned OptTransfers2 (CodeSeg* S);
+/* Replace loads followed by a register transfer by a load with the second
+ * register if possible.
+ */
+
 unsigned OptPushPop (CodeSeg* S);
 /* Remove a PHA/PLA sequence were A is not used later */