From: laubzega Date: Sat, 13 Oct 2018 07:05:33 +0000 (-0700) Subject: Stack adjustment code optimizations. X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=d3665b263ee9c7a028e39186b28017ba26fd13d9;p=cc65 Stack adjustment code optimizations. --- diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index e44bf2bf5..6e547f16d 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -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 */ diff --git a/src/cc65/opcodes.h b/src/cc65/opcodes.h index 349de32a4..0d191f6c7 100644 --- a/src/cc65/opcodes.h +++ b/src/cc65/opcodes.h @@ -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 */ diff --git a/src/cc65/symentry.h b/src/cc65/symentry.h index e978274dc..630ca944c 100644 --- a/src/cc65/symentry.h +++ b/src/cc65/symentry.h @@ -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. */ diff --git a/src/cc65/symtab.c b/src/cc65/symtab.c index 8eefe1178..8db6a741c 100644 --- a/src/cc65/symtab.c +++ b/src/cc65/symtab.c @@ -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. diff --git a/src/cc65/symtab.h b/src/cc65/symtab.h index 39782d6ab..0856740cc 100644 --- a/src/cc65/symtab.h +++ b/src/cc65/symtab.h @@ -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 */ /*****************************************************************************/