1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-08 15:29:37 +00:00

Stack adjustment code optimizations.

This commit is contained in:
laubzega 2018-10-13 00:05:33 -07:00 committed by Oliver Schmidt
parent 249248ccc8
commit d3665b263e
5 changed files with 116 additions and 5 deletions

View 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 */

View 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 */

View 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.
*/

View 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.

View 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 */
/*****************************************************************************/