]> git.sur5r.net Git - cc65/commitdiff
Stack adjustment code optimizations.
authorlaubzega <mileksmyk@gmail.com>
Sat, 13 Oct 2018 07:05:33 +0000 (00:05 -0700)
committerOliver Schmidt <ol.sc@web.de>
Tue, 16 Oct 2018 07:55:02 +0000 (09:55 +0200)
src/cc65/codeopt.c
src/cc65/opcodes.h
src/cc65/symentry.h
src/cc65/symtab.c
src/cc65/symtab.h

index e44bf2bf5590976edc1afe29ed3c09e4ed3f4ccc..6e547f16dc772da576b1e5a82855feafd0ae1914 100644 (file)
@@ -69,7 +69,7 @@
 #include "error.h"
 #include "global.h"
 #include "output.h"
-
+#include "symtab.h"
 
 
 /*****************************************************************************/
@@ -613,7 +613,86 @@ static unsigned OptStackPtrOps (CodeSeg* S)
     return Changes;
 }
 
+static unsigned OptGotoSPAdj (CodeSeg* S)
+/* Remove unnecessary SP adjustment while gotoing
+*/
+{
+    unsigned Changes = 0;
+    unsigned I;
+
+    /* Walk over the entries */
+    I = 0;
+    while (I < CS_GetEntryCount (S)) {
+
+        CodeEntry* L[10], *X;
+        unsigned short adjustment;
+        const char* Arg;
+
+        /* Get next entry */
+        L[0] = CS_GetEntry (S, I);
+
+        /* Check for the sequence */
+        if (L[0]->OPC == OP65_PHA            &&
+            CS_GetEntries (S, L+1, I+1, 9)   &&
+            L[1]->OPC == OP65_LDA            &&
+            L[1]->AM == AM65_ABS             &&
+            L[2]->OPC == OP65_CLC            &&
+            L[3]->OPC == OP65_ADC            &&
+            strcmp (L[3]->Arg, "sp") == 0    &&
+            L[6]->OPC == OP65_ADC            &&
+            strcmp (L[6]->Arg, "sp+1") == 0    &&
+            L[9]->OPC == OP65_JMP
+            ) {
+            printf("Goto SP adjustment found. Jump to: %s, data Label: %s\n", L[9]->Arg, L[1]->Arg);
+            adjustment = FindSPAdjustment(L[1]->Arg);
+
+            if (adjustment == 0) {
+                CS_DelEntries (S, I, 9);
+            }
+            else if (adjustment > 255) {
+                Arg = MakeHexArg (adjustment & 0xff);
+                X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, L[1]->LI);
+                CS_InsertEntry(S, X, I + 1);
+                Arg = MakeHexArg (adjustment >> 8);
+                X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, L[5]->LI);
+                CS_InsertEntry(S, X, I + 6);
+
+                CS_DelEntry(S, I + 2);
+                CS_DelEntry(S, I + 6);
+            }
+            else if (adjustment > 8) {
+                Arg = MakeHexArg (adjustment & 0xff);
+                X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[1]->LI);
+                CS_InsertEntry (S, X, I);
+                X = NewCodeEntry (OP65_JSR, AM65_ABS, "addysp", 0, L[1]->LI);
+                CS_InsertEntry (S, X, I + 1);
+
+                CS_DelEntries(S, I + 2, 9);
+            }
+            else {
+                char Buf[20];
+                xsprintf (Buf, sizeof (Buf), "incsp%u", adjustment);
+                X = NewCodeEntry (OP65_JSR, AM65_ABS, Buf, 0, L[1]->LI);
+                CS_InsertEntry (S, X, I);
+
+                CS_DelEntries(S, I + 1, 9);
+            }
+            /* Regenerate register info */
+            CS_GenRegInfo (S);
+
+            /* Remember we had changes */
+            Changes++;
+        } else {
+
+            /* Next entry */
+            ++I;
+        }
 
+    }
+
+    /* Return the number of changes made */
+    return Changes;
+}
 
 /*****************************************************************************/
 /*                              struct OptFunc                               */
@@ -675,6 +754,7 @@ static OptFunc DOptDeadCode     = { OptDeadCode,     "OptDeadCode",     100, 0,
 static OptFunc DOptDeadJumps    = { OptDeadJumps,    "OptDeadJumps",    100, 0, 0, 0, 0, 0 };
 static OptFunc DOptDecouple     = { OptDecouple,     "OptDecouple",     100, 0, 0, 0, 0, 0 };
 static OptFunc DOptDupLoads     = { OptDupLoads,     "OptDupLoads",       0, 0, 0, 0, 0, 0 };
+static OptFunc DOptGotoSPAdj    = { OptGotoSPAdj,    "OptGotoSPAdj",      0, 0, 0, 0, 0, 0 };
 static OptFunc DOptIndLoads1    = { OptIndLoads1,    "OptIndLoads1",      0, 0, 0, 0, 0, 0 };
 static OptFunc DOptIndLoads2    = { OptIndLoads2,    "OptIndLoads2",      0, 0, 0, 0, 0, 0 };
 static OptFunc DOptJumpCascades = { OptJumpCascades, "OptJumpCascades", 100, 0, 0, 0, 0, 0 };
@@ -774,6 +854,7 @@ static OptFunc* OptFuncs[] = {
     &DOptDeadJumps,
     &DOptDecouple,
     &DOptDupLoads,
+    &DOptGotoSPAdj,
     &DOptIndLoads1,
     &DOptIndLoads2,
     &DOptJumpCascades,
@@ -1122,6 +1203,7 @@ static unsigned RunOptGroup1 (CodeSeg* S)
 {
     unsigned Changes = 0;
 
+    Changes += RunOptFunc (S, &DOptGotoSPAdj, 1);
     Changes += RunOptFunc (S, &DOptStackPtrOps, 5);
     Changes += RunOptFunc (S, &DOptPtrStore1, 1);
     Changes += RunOptFunc (S, &DOptPtrStore2, 1);
@@ -1229,6 +1311,7 @@ static unsigned RunOptGroup3 (CodeSeg* S)
         C += RunOptFunc (S, &DOptCmp6, 1);
         C += RunOptFunc (S, &DOptCmp7, 1);
         C += RunOptFunc (S, &DOptCmp9, 1);
+
         C += RunOptFunc (S, &DOptTest1, 1);
         C += RunOptFunc (S, &DOptLoad1, 1);
         C += RunOptFunc (S, &DOptJumpTarget3, 1);       /* After OptCondBranches2 */
index 349de32a4dbba3e03d3546cac97f63bcac412288..0d191f6c7bd6b7337bd321d911a8fc5a994721fd 100644 (file)
@@ -134,7 +134,7 @@ typedef enum {
 typedef enum {
     AM65_IMP,                   /* implicit */
     AM65_ACC,                   /* accumulator */
-    AM65_IMM,                   /* immidiate */
+    AM65_IMM,                   /* immediate */
     AM65_ZP,                    /* zeropage */
     AM65_ZPX,                   /* zeropage,X */
     AM65_ZPY,                   /* zeropage,Y */
index e978274dccd77dbc32a586830c02f0e4da9fc1f5..630ca944c97c28fb15f92e64994e9b7b9ecaba7f 100644 (file)
@@ -99,6 +99,7 @@ struct LiteralPool;
 #define SC_HAVEATTR     0x10000U        /* Symbol has attributes */
 
 #define SC_GOTO         0x20000U
+#define SC_SPADJUSTMENT 0x40000U
 
 
 
@@ -139,6 +140,10 @@ struct SymEntry {
             Collection          *DefsOrRefs;
         } L;
 
+        struct {
+            unsigned short      SPAdjustment;
+        } G;
+
         /* Register bank offset and offset of the saved copy on stack for
         ** register variables.
         */
index 8eefe1178da32b93abd292c4852dba380079d164..8db6a741c8c1ad547c89e5a96e1225d78557fc4f 100644 (file)
@@ -92,7 +92,7 @@ static SymTable*        SymTab          = 0;
 static SymTable*        TagTab0         = 0;
 static SymTable*        TagTab          = 0;
 static SymTable*        LabelTab        = 0;
-
+static SymTable*        SPAdjustTab     = 0;
 
 
 /*****************************************************************************/
@@ -225,6 +225,8 @@ void EnterGlobalLevel (void)
 
     /* Create and assign the tag table */
     TagTab0 = TagTab = NewSymTable (SYMTAB_SIZE_GLOBAL);
+
+    SPAdjustTab = NewSymTable (SYMTAB_SIZE_GLOBAL);
 }
 
 
@@ -405,7 +407,7 @@ void LeaveStructLevel (void)
 
 
 
-static SymEntry* FindSymInTable (const SymTable* T, const char* Name, unsigned Hash)
+SymEntry* FindSymInTable (const SymTable* T, const char* Name, unsigned Hash)
 /* Search for an entry in one table */
 {
     /* Get the start of the hash chain */
@@ -660,7 +662,7 @@ SymEntry* AddConstSym (const char* Name, const Type* T, unsigned Flags, long Val
 }
 
 
-DefOrRef* AddDefOrRef(SymEntry* E, unsigned Flags)
+DefOrRef* AddDefOrRef (SymEntry* E, unsigned Flags)
 /* Add definition or reference to the SymEntry and preserve its attributes */
 {
     DefOrRef *DOR;
@@ -677,6 +679,20 @@ DefOrRef* AddDefOrRef(SymEntry* E, unsigned Flags)
     return DOR;
 }
 
+unsigned short FindSPAdjustment (const char* Name)
+{
+    SymEntry* Entry = FindSymInTable (SPAdjustTab, Name, HashStr (Name));
+
+    if (Entry) {
+            printf("L: %s sa: %d\n", Name, Entry->V.G.SPAdjustment);
+            return Entry->V.G.SPAdjustment;
+    }
+
+    Fatal("ICE: No label entry found");
+
+    return 0;
+}
+
 SymEntry* AddLabelSym (const char* Name, unsigned Flags)
 /* Add a goto label to the label table */
 {
@@ -728,9 +744,14 @@ SymEntry* AddLabelSym (const char* Name, unsigned Flags)
                 /* We're processing a label, let's update all gotos encountered
                 ** so far
                 */
+                SymEntry *E;
                 g_userodata();
                 g_defdatalabel (DOR->LateSP_Label);
                 g_defdata (CF_CONST | CF_INT, StackPtr - DOR->StackPtr, 0);
+                E = NewSymEntry (LocalLabelName(DOR->LateSP_Label), SC_SPADJUSTMENT);
+                E->V.G.SPAdjustment = StackPtr - DOR->StackPtr;
+                AddSymEntry (SPAdjustTab, E);
+
 
                 /* Are we jumping into a block with initalization of an object that
                 ** has automatic storage duration? Let's emit a warning.
index 39782d6abe6f70ac50ffc90b6798200a32f5e2bd..0856740cc48789a490a2bf2f79545b7ffc3c63eb 100644 (file)
@@ -136,6 +136,8 @@ SymEntry* FindTagSym (const char* Name);
 SymEntry* FindStructField (const Type* TypeArray, const char* Name);
 /* Find a struct field in the fields list */
 
+unsigned short FindSPAdjustment (const char* Name);
+/* Search for an entry in the table of SP adjustments */
 
 
 /*****************************************************************************/