]> git.sur5r.net Git - cc65/commitdiff
Added two replacements for negax. Shift right for signed values can be treated
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 23 Jun 2012 16:58:05 +0000 (16:58 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 23 Jun 2012 16:58:05 +0000 (16:58 +0000)
like unsigned if X is known to be zero.

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

src/cc65/codeopt.c
src/cc65/coptneg.c
src/cc65/coptneg.h

index 98bfc686cafca8c42569aabbbc0ab21eeb74a6b0..c83e965cb668f675d20aeb0406f53f26e00a7b6f 100644 (file)
@@ -330,8 +330,8 @@ static unsigned OptShift3 (CodeSeg* S)
 
 
 static unsigned OptShift4 (CodeSeg* S)
-/* A call to the shraxN routine may get replaced by one or more lsr insns
- * if the value of X is zero.
+/* Calls to the asraxN or shraxN routines may get replaced by one or more lsr
+ * insns if the value of X is zero.
  */
 {
     unsigned Changes = 0;
@@ -348,10 +348,11 @@ static unsigned OptShift4 (CodeSeg* S)
                CodeEntry* E = CS_GetEntry (S, I);
 
        /* Check for the sequence */
-       if (E->OPC == OP65_JSR                       &&
-                   strncmp (E->Arg, "shrax", 5) == 0        &&
-           strlen (E->Arg) == 6                     &&
-           IsDigit (E->Arg[5])                      &&
+       if (E->OPC == OP65_JSR                          &&
+                   (strncmp (E->Arg, "shrax", 5) == 0  ||
+             strncmp (E->Arg, "asrax", 5) == 0)         &&
+           strlen (E->Arg) == 6                        &&
+           IsDigit (E->Arg[5])                         &&
                    E->RI->In.RegX == 0) {
 
            /* Insert shift insns */
@@ -1151,6 +1152,12 @@ static OptFunc DOptAdd3          = { OptAdd3,         "OptAdd3",          65, 0,
 static OptFunc DOptAdd4                = { OptAdd4,         "OptAdd4",          90, 0, 0, 0, 0, 0 };
 static OptFunc DOptAdd5                = { OptAdd5,         "OptAdd5",         100, 0, 0, 0, 0, 0 };
 static OptFunc DOptAdd6                = { OptAdd6,         "OptAdd6",          40, 0, 0, 0, 0, 0 };
+static OptFunc DOptBNegA1       = { OptBNegA1,       "OptBNegA1",       100, 0, 0, 0, 0, 0 };
+static OptFunc DOptBNegA2       = { OptBNegA2,       "OptBNegA2",       100, 0, 0, 0, 0, 0 };
+static OptFunc DOptBNegAX1      = { OptBNegAX1,      "OptBNegAX1",      100, 0, 0, 0, 0, 0 };
+static OptFunc DOptBNegAX2      = { OptBNegAX2,      "OptBNegAX2",      100, 0, 0, 0, 0, 0 };
+static OptFunc DOptBNegAX3      = { OptBNegAX3,      "OptBNegAX3",      100, 0, 0, 0, 0, 0 };
+static OptFunc DOptBNegAX4      = { OptBNegAX4,      "OptBNegAX4",      100, 0, 0, 0, 0, 0 };
 static OptFunc DOptBoolTrans    = { OptBoolTrans,    "OptBoolTrans",    100, 0, 0, 0, 0, 0 };
 static OptFunc DOptBranchDist          = { OptBranchDist,   "OptBranchDist",     0, 0, 0, 0, 0, 0 };
 static OptFunc DOptCmp1                = { OptCmp1,         "OptCmp1",          42, 0, 0, 0, 0, 0 };
@@ -1176,15 +1183,11 @@ static OptFunc DOptJumpTarget2  = { OptJumpTarget2,  "OptJumpTarget2",  100, 0,
 static OptFunc DOptJumpTarget3  = { OptJumpTarget3,  "OptJumpTarget3",  100, 0, 0, 0, 0, 0 };
 static OptFunc DOptLoad1        = { OptLoad1,        "OptLoad1",        100, 0, 0, 0, 0, 0 };
 static OptFunc DOptLoad2        = { OptLoad2,        "OptLoad2",        200, 0, 0, 0, 0, 0 };
+static OptFunc DOptNegAX1       = { OptNegAX1,       "OptNegAX1",       165, 0, 0, 0, 0, 0 };
+static OptFunc DOptNegAX2       = { OptNegAX2,       "OptNegAX2",       200, 0, 0, 0, 0, 0 };
 static OptFunc DOptRTS                 = { OptRTS,          "OptRTS",          100, 0, 0, 0, 0, 0 };
 static OptFunc DOptRTSJumps1    = { OptRTSJumps1,    "OptRTSJumps1",           100, 0, 0, 0, 0, 0 };
 static OptFunc DOptRTSJumps2    = { OptRTSJumps2,    "OptRTSJumps2",           100, 0, 0, 0, 0, 0 };
-static OptFunc DOptBNegA1       = { OptBNegA1,       "OptBNegA1",       100, 0, 0, 0, 0, 0 };
-static OptFunc DOptBNegA2       = { OptBNegA2,       "OptBNegA2",       100, 0, 0, 0, 0, 0 };
-static OptFunc DOptBNegAX1      = { OptBNegAX1,      "OptBNegAX1",      100, 0, 0, 0, 0, 0 };
-static OptFunc DOptBNegAX2      = { OptBNegAX2,      "OptBNegAX2",      100, 0, 0, 0, 0, 0 };
-static OptFunc DOptBNegAX3      = { OptBNegAX3,      "OptBNegAX3",      100, 0, 0, 0, 0, 0 };
-static OptFunc DOptBNegAX4      = { OptBNegAX4,      "OptBNegAX4",      100, 0, 0, 0, 0, 0 };
 static OptFunc DOptPrecalc      = { OptPrecalc,      "OptPrecalc",             100, 0, 0, 0, 0, 0 };
 static OptFunc DOptPtrLoad1            = { OptPtrLoad1,     "OptPtrLoad1",     100, 0, 0, 0, 0, 0 };
 static OptFunc DOptPtrLoad2            = { OptPtrLoad2,     "OptPtrLoad2",     100, 0, 0, 0, 0, 0 };
@@ -1246,6 +1249,12 @@ static OptFunc* OptFuncs[] = {
     &DOptAdd4,
     &DOptAdd5,
     &DOptAdd6,
+    &DOptBNegA1,
+    &DOptBNegA2,
+    &DOptBNegAX1,
+    &DOptBNegAX2,
+    &DOptBNegAX3,
+    &DOptBNegAX4,
     &DOptBoolTrans,
     &DOptBranchDist,
     &DOptCmp1,
@@ -1271,12 +1280,8 @@ static OptFunc* OptFuncs[] = {
     &DOptJumpTarget3,
     &DOptLoad1,
     &DOptLoad2,
-    &DOptBNegA1,
-    &DOptBNegA2,
-    &DOptBNegAX1,
-    &DOptBNegAX2,
-    &DOptBNegAX3,
-    &DOptBNegAX4,
+    &DOptNegAX1,
+    &DOptNegAX2,
     &DOptPrecalc,
     &DOptPtrLoad1,
     &DOptPtrLoad11,
@@ -1642,6 +1647,8 @@ static unsigned RunOptGroup3 (CodeSeg* S)
 
                C += RunOptFunc (S, &DOptBNegA1, 1);
                C += RunOptFunc (S, &DOptBNegA2, 1);
+        C += RunOptFunc (S, &DOptNegAX1, 1);
+        C += RunOptFunc (S, &DOptNegAX2, 1);
                C += RunOptFunc (S, &DOptStackOps, 1);
                C += RunOptFunc (S, &DOptSub1, 1);
                C += RunOptFunc (S, &DOptSub2, 1);
index 9c41a8fe5be7f703f46665793cf7dfe5fa9a059f..8fd89b97d9fc45e38b284c8bce205451682d031a 100644 (file)
@@ -417,3 +417,161 @@ unsigned OptBNegAX4 (CodeSeg* S)
 
 
 
+/*****************************************************************************/
+/*                            negax optimizations                            */
+/*****************************************************************************/
+
+
+
+unsigned OptNegAX1 (CodeSeg* S)
+/* Search for a call to negax and replace it by
+ *
+ *      eor     #$FF
+ *      clc
+ *      adc     #$01
+ *
+ * if X isn't used later.
+ */
+{
+    unsigned Changes = 0;
+    unsigned I;
+
+    /* Generate register info for this step */
+    CS_GenRegInfo (S);
+
+    /* Walk over the entries */
+    I = 0;
+    while (I < CS_GetEntryCount (S)) {
+
+       /* Get next entry */
+               CodeEntry* E = CS_GetEntry (S, I);
+
+       /* Check if this is a call to negax, and if X isn't used later */
+               if (CE_IsCallTo (E, "negax") && !RegXUsed (S, I+1)) {
+
+            CodeEntry* X;
+
+            /* Add replacement code behind */
+           X = NewCodeEntry (OP65_EOR, AM65_IMM, "$FF", 0, E->LI);
+           CS_InsertEntry (S, X, I+1);
+
+            X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, E->LI);
+            CS_InsertEntry (S, X, I+2);
+
+            X = NewCodeEntry (OP65_ADC, AM65_IMM, "$01", 0, E->LI);
+            CS_InsertEntry (S, X, I+3);
+
+            /* Delete the call to negax */
+           CS_DelEntry (S, I);
+
+            /* Skip the generated code */
+            I += 2;
+
+           /* We had changes */
+           ++Changes;
+       }
+
+       /* Next entry */
+       ++I;
+
+    }
+
+    /* Free register info */
+    CS_FreeRegInfo (S);
+
+    /* Return the number of changes made */
+    return Changes;
+}
+
+
+
+unsigned OptNegAX2 (CodeSeg* S)
+/* Search for a call to negax and replace it by
+ *
+ *      ldx     #$FF
+ *      eor     #$FF
+ *      clc
+ *      adc     #$01
+ *      bne     L1
+ *      inx
+ * L1:
+ *
+ * if X is known and zero on entry.
+ */
+{
+    unsigned Changes = 0;
+    unsigned I;
+
+    /* Generate register info for this step */
+    CS_GenRegInfo (S);
+
+    /* Walk over the entries */
+    I = 0;
+    while (I < CS_GetEntryCount (S)) {
+
+        CodeEntry* P;
+
+       /* Get next entry */
+               CodeEntry* E = CS_GetEntry (S, I);
+
+       /* Check if this is a call to negax, and if X is known and zero */
+       if (E->RI->In.RegX == 0                 &&
+            CE_IsCallTo (E, "negax")            &&
+            (P = CS_GetNextEntry (S, I)) != 0) {
+
+            CodeEntry* X;
+            CodeLabel* L;
+
+            /* Add replacement code behind */
+
+            /* ldx #$FF */
+           X = NewCodeEntry (OP65_LDX, AM65_IMM, "$FF", 0, E->LI);
+           CS_InsertEntry (S, X, I+1);
+
+            /* eor #$FF */
+           X = NewCodeEntry (OP65_EOR, AM65_IMM, "$FF", 0, E->LI);
+           CS_InsertEntry (S, X, I+2);
+
+            /* clc */
+            X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, E->LI);
+            CS_InsertEntry (S, X, I+3);
+
+            /* adc #$01 */
+            X = NewCodeEntry (OP65_ADC, AM65_IMM, "$01", 0, E->LI);
+            CS_InsertEntry (S, X, I+4);
+
+            /* Get the label attached to the insn following the call */
+            L = CS_GenLabel (S, P);
+
+            /* bne L */
+            X = NewCodeEntry (OP65_BNE, AM65_BRA, L->Name, L, E->LI);
+            CS_InsertEntry (S, X, I+5);
+
+            /* inx */
+            X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, E->LI);
+            CS_InsertEntry (S, X, I+6);
+
+            /* Delete the call to negax */
+           CS_DelEntry (S, I);
+
+            /* Skip the generated code */
+            I += 5;
+
+           /* We had changes */
+           ++Changes;
+       }
+
+       /* Next entry */
+       ++I;
+
+    }
+
+    /* Free register info */
+    CS_FreeRegInfo (S);
+
+    /* Return the number of changes made */
+    return Changes;
+}
+
+
+
index 0ff897d0c57fac55f8adaf75867767f79613a993..82bd2f39d98f664ff68c3422a6c4123cbd61aea0 100644 (file)
@@ -132,6 +132,38 @@ unsigned OptBNegAX4 (CodeSeg* S);
 
 
 
+/*****************************************************************************/
+/*                            negax optimizations                            */
+/*****************************************************************************/
+
+
+
+unsigned OptNegAX1 (CodeSeg* S);
+/* Search for a call to negax and replace it by
+ *
+ *      eor     #$FF
+ *      clc
+ *      adc     #$01
+ *
+ * if X isn't used later.
+ */
+
+unsigned OptNegAX2 (CodeSeg* S);
+/* Search for a call to negax and replace it by
+ *
+ *      ldx     #$FF
+ *      eor     #$FF
+ *      clc
+ *      adc     #$01
+ *      bne     L1
+ *      inx
+ * L1:
+ *
+ * if X is known and zero on entry.
+ */
+
+
+
 /* End of coptneg.h */
 
 #endif