]> git.sur5r.net Git - cc65/commitdiff
Do size improvements always if they have no impact on speed.
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Fri, 14 Aug 2009 18:23:29 +0000 (18:23 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Fri, 14 Aug 2009 18:23:29 +0000 (18:23 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@4002 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/codeopt.c
src/cc65/coptsize.c

index 4542e44a24df78a3d5f194106eb4848614c23032..18673ebbf3bab78e4d49832448876baac041505d 100644 (file)
@@ -1489,22 +1489,21 @@ static unsigned RunOptGroup6 (CodeSeg* S)
     unsigned Changes = 0;
     unsigned C;
 
-    if (S->CodeSizeFactor <= 100) {
-        /* Optimize for size, that is replace operations by shorter ones, even
-         * if this does hinder further optimizations (no problem since we're
-         * done soon).
+    /* Optimize for size, that is replace operations by shorter ones, even
+     * if this does hinder further optimizations (no problem since we're
+     * done soon).
+     */
+    C = RunOptFunc (S, &DOptSize1, 1);
+    if (C) {
+        Changes += C;
+        /* Run some optimization passes again, since the size optimizations
+         * may have opened new oportunities.
          */
-        C = RunOptFunc (S, &DOptSize1, 1);
-        if (C) {
-            Changes += C;
-            /* Run some optimization passes again, since the size optimizations
-             * may have opened new oportunities.
-             */
-            Changes += RunOptFunc (S, &DOptUnusedLoads, 1);
-            Changes += RunOptFunc (S, &DOptJumpTarget, 5);
-            Changes += RunOptFunc (S, &DOptStore5, 1);
-        }
+        Changes += RunOptFunc (S, &DOptUnusedLoads, 1);
+        Changes += RunOptFunc (S, &DOptJumpTarget, 5);
+        Changes += RunOptFunc (S, &DOptStore5, 1);
     }
+
     C = RunOptFunc (S, &DOptSize2, 1);
     if (C) {
         Changes += C;
index 6e14c42f1c06ce59e4cdead3f35da1d324c050c9..ad384da6475e4ddc4fa343234675fcd23ddd1fa9 100644 (file)
 
 
 
+/* Flags for CallDesc */
+#define F_NONE          0x0000U /* No extra flags */
+#define F_SLOWER        0x0001U /* Function call is slower */
+
 typedef struct CallDesc CallDesc;
 struct CallDesc {
-    const char*     LongFunc;       /* Long function name */
-    short           A, X, Y;        /* Register contents */
-    const char*     ShortFunc;      /* Short function name */
+    const char* LongFunc;       /* Long function name */
+    short       A, X, Y;        /* Register contents */
+    unsigned    Flags;          /* Flags from above */
+    const char* ShortFunc;      /* Short function name */
 };
 
 /* Note: The table is sorted. If there is more than one entry with the same
@@ -65,55 +70,60 @@ struct CallDesc {
  * at least none of the following ones are better).
  */
 static const CallDesc CallTable [] = {
-    /* Name          A register      X register     Y register     replacement */
-    { "addeqysp",  UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0, "addeq0sp"  },
-    { "laddeqysp", UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0, "laddeq0sp" },
-    { "ldaxidx",   UNKNOWN_REGVAL, UNKNOWN_REGVAL,              1, "ldaxi"     },
-    { "ldaxysp",   UNKNOWN_REGVAL, UNKNOWN_REGVAL,              1, "ldax0sp"   },
-    { "ldeaxidx",  UNKNOWN_REGVAL, UNKNOWN_REGVAL,              3, "ldeaxi"    },
-    { "ldeaxysp",  UNKNOWN_REGVAL, UNKNOWN_REGVAL,              3, "ldeax0sp"  },
-    { "pusha",                  0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, "pushc0"    },
-    { "pusha",                  1, UNKNOWN_REGVAL, UNKNOWN_REGVAL, "pushc1"    },
-    { "pusha",                  2, UNKNOWN_REGVAL, UNKNOWN_REGVAL, "pushc2"    },
-    { "pushax",                 0,              0, UNKNOWN_REGVAL, "push0"     },
-    { "pushax",                 1,              0, UNKNOWN_REGVAL, "push1"     },
-    { "pushax",                 2,              0, UNKNOWN_REGVAL, "push2"     },
-    { "pushax",                 3,              0, UNKNOWN_REGVAL, "push3"     },
-    { "pushax",                 4,              0, UNKNOWN_REGVAL, "push4"     },
-    { "pushax",                 5,              0, UNKNOWN_REGVAL, "push5"     },
-    { "pushax",                 6,              0, UNKNOWN_REGVAL, "push6"     },
-    { "pushax",                 7,              0, UNKNOWN_REGVAL, "push7"     },
-    { "pushax",    UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "pusha0"    },
-    { "pushax",    UNKNOWN_REGVAL,           0xFF, UNKNOWN_REGVAL, "pushaFF"   },
-    { "pushaysp",  UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0, "pusha0sp"  },
-    { "pushwidx",  UNKNOWN_REGVAL, UNKNOWN_REGVAL,              1, "pushw"     },
-    { "pushwysp",  UNKNOWN_REGVAL, UNKNOWN_REGVAL,              3, "pushw0sp"  },
-    { "staxysp",   UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0, "stax0sp"   },
-    { "tosaddax",  UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "tosadda0"  },
-    { "tosandax",  UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "tosanda0"  },
-    { "tosdivax",  UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "tosdiva0"  },
-    { "toseqax",   UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "toseqa0"   },
-    { "tosgeax",   UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "tosgea0"   },
-    { "tosgtax",   UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "tosgta0"   },
-    { "tosleax",   UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "toslea0"   },
-    { "tosorax",   UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "tosora0"   },
-    { "lsubeqysp", UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0, "lsubeq0sp" },
-    { "steaxysp",  UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0, "steax0sp"  },
-    { "subeqysp",  UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0, "subeq0sp"  },
-    { "tosltax",   UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "toslta0"   },
-    { "tosmodax",  UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "tosmoda0"  },
-    { "tosmulax",  UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "tosmula0"  },
-    { "tosneax",   UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "tosnea0"   },
-    { "tosrsubax", UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "tosrsuba0" },
-    { "tossubax",  UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "tossuba0"  },
-    { "tosudivax", UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "tosudiva0" },
-    { "tosugeax",  UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "tosugea0"  },
-    { "tosugtax",  UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "tosugta0"  },
-    { "tosuleax",  UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "tosulea0"  },
-    { "tosultax",  UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "tosulta0"  },
-    { "tosumodax", UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "tosumoda0" },
-    { "tosumulax", UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "tosumula0" },
-    { "tosxorax",  UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, "tosxora0"  },
+    /* Name          A register      X register     Y register     flags     replacement */
+    { "addeqysp",  UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0, F_NONE,   "addeq0sp"  },
+    { "laddeqysp", UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0, F_NONE,   "laddeq0sp" },
+    { "ldaxidx",   UNKNOWN_REGVAL, UNKNOWN_REGVAL,              1, F_NONE,   "ldaxi"     },
+    { "ldaxysp",   UNKNOWN_REGVAL, UNKNOWN_REGVAL,              1, F_NONE,   "ldax0sp"   },
+    { "ldeaxidx",  UNKNOWN_REGVAL, UNKNOWN_REGVAL,              3, F_NONE,   "ldeaxi"    },
+    { "ldeaxysp",  UNKNOWN_REGVAL, UNKNOWN_REGVAL,              3, F_NONE,   "ldeax0sp"  },
+    { "lsubeqysp", UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0, F_NONE,   "lsubeq0sp" },
+    { "pusha",                  0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, F_SLOWER, "pushc0"    },
+    { "pusha",                  1, UNKNOWN_REGVAL, UNKNOWN_REGVAL, F_SLOWER, "pushc1"    },
+    { "pusha",                  2, UNKNOWN_REGVAL, UNKNOWN_REGVAL, F_SLOWER, "pushc2"    },
+    { "pushax",                 0,              0, UNKNOWN_REGVAL, F_NONE,   "push0"     },
+    { "pushax",                 1,              0, UNKNOWN_REGVAL, F_SLOWER, "push1"     },
+    { "pushax",                 2,              0, UNKNOWN_REGVAL, F_SLOWER, "push2"     },
+    { "pushax",                 3,              0, UNKNOWN_REGVAL, F_SLOWER, "push3"     },
+    { "pushax",                 4,              0, UNKNOWN_REGVAL, F_SLOWER, "push4"     },
+    { "pushax",                 5,              0, UNKNOWN_REGVAL, F_SLOWER, "push5"     },
+    { "pushax",                 6,              0, UNKNOWN_REGVAL, F_SLOWER, "push6"     },
+    { "pushax",                 7,              0, UNKNOWN_REGVAL, F_SLOWER, "push7"     },
+    { "pushax",    UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "pusha0"    },
+    { "pushax",    UNKNOWN_REGVAL,           0xFF, UNKNOWN_REGVAL, F_SLOWER, "pushaFF"   },
+    { "pushaysp",  UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0, F_NONE,   "pusha0sp"  },
+    { "pushwidx",  UNKNOWN_REGVAL, UNKNOWN_REGVAL,              1, F_NONE,   "pushw"     },
+    { "pushwysp",  UNKNOWN_REGVAL, UNKNOWN_REGVAL,              3, F_NONE,   "pushw0sp"  },
+    { "staxysp",   UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0, F_NONE,   "stax0sp"   },
+    { "steaxysp",  UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0, F_NONE,   "steax0sp"  },
+    { "subeqysp",  UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0, F_NONE,   "subeq0sp"  },
+    { "tosaddax",  UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "tosadda0"  },
+    { "tosandax",  UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "tosanda0"  },
+    { "tosdivax",  UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "tosdiva0"  },
+    { "toseqax",                0,              0, UNKNOWN_REGVAL, F_NONE,   "toseq00"   },
+    { "toseqax",   UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "toseqa0"   },
+    { "tosgeax",                0,              0, UNKNOWN_REGVAL, F_NONE,   "tosge00"   },
+    { "tosgeax",   UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "tosgea0"   },
+    { "tosgtax",                0,              0, UNKNOWN_REGVAL, F_NONE,   "tosgt00"   },
+    { "tosgtax",   UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "tosgta0"   },
+    { "tosleax",                0,              0, UNKNOWN_REGVAL, F_NONE,   "tosle00"   },
+    { "tosleax",   UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "toslea0"   },
+    { "tosltax",                0,              0, UNKNOWN_REGVAL, F_NONE,   "toslt00"   },
+    { "tosltax",   UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "toslta0"   },
+    { "tosmodax",  UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "tosmoda0"  },
+    { "tosmulax",  UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "tosmula0"  },
+    { "tosneax",   UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "tosnea0"   },
+    { "tosorax",   UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "tosora0"   },
+    { "tosrsubax", UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "tosrsuba0" },
+    { "tossubax",  UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "tossuba0"  },
+    { "tosudivax", UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "tosudiva0" },
+    { "tosugeax",  UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "tosugea0"  },
+    { "tosugtax",  UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "tosugta0"  },
+    { "tosuleax",  UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "tosulea0"  },
+    { "tosultax",  UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "tosulta0"  },
+    { "tosumodax", UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "tosumoda0" },
+    { "tosumulax", UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "tosumula0" },
+    { "tosxorax",  UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, F_NONE,   "tosxora0"  },
 
 #if 0
     "tosadd0ax",         /* tosaddeax, sreg = 0 */
@@ -201,6 +211,9 @@ unsigned OptSize1 (CodeSeg* S)
     unsigned Changes = 0;
     unsigned I;
 
+    /* Are we optimizing for size */
+    int OptForSize = (S->CodeSizeFactor < 100);
+
     /* Generate register info for the following step */
     CS_GenRegInfo (S);
 
@@ -216,15 +229,23 @@ unsigned OptSize1 (CodeSeg* S)
        /* Check if it's a subroutine call */
        if (E->OPC == OP65_JSR && (D = FindCall (E->Arg)) != 0) {
 
-           /* Check for any of the known functions. */
+            printf ("Found \"%s\" for \"%s\"\n", D->LongFunc, D->ShortFunc);
+
+            /* FindCall finds the first entry that matches our function name.
+             * The names are listed in "best match" order, so search for the
+             * first one, that fulfills our conditions.
+             */
             while (1) {
 
-                /* Check the registers */
+                /* Check the registers and allow slower code only if
+                 * optimizing for size.
+                 */
                 if ((D->A < 0 || D->A == E->RI->In.RegA) &&
                     (D->X < 0 || D->X == E->RI->In.RegX) &&
-                    (D->Y < 0 || D->Y == E->RI->In.RegY)) {
+                    (D->Y < 0 || D->Y == E->RI->In.RegY) &&
+                    (OptForSize || (D->Flags & F_SLOWER) == 0)) {
 
-                    /* Ok, match for all registers */
+                    /* Ok, match for all conditions */
                     CodeEntry* X;
                     X = NewCodeEntry (E->OPC, E->AM, D->ShortFunc, 0, E->LI);
                     CS_InsertEntry (S, X, I+1);
@@ -246,8 +267,8 @@ unsigned OptSize1 (CodeSeg* S)
             }
         }
 
-       /* Next entry */
-       ++I;
+       /* Next entry */
+       ++I;
 
     }