Added optimizations for commutative arithmetic ops

git-svn-id: svn://svn.cc65.org/cc65/trunk@469 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2000-11-22 21:39:56 +00:00
parent 901a8088e6
commit cefb4c067d

View file

@ -177,6 +177,8 @@ static const struct {
{ "\tstz\t", 0, REG_NONE, REG_NONE },
{ "\ttax", 1, REG_A, REG_X },
{ "\ttay", 1, REG_A, REG_Y },
{ "\ttrb\t", 0, REG_A, REG_NONE },
{ "\ttsb\t", 0, REG_A, REG_NONE },
{ "\ttsx", 1, REG_NONE, REG_X },
{ "\ttxa", 1, REG_X, REG_A },
{ "\ttya", 1, REG_Y, REG_A },
@ -3304,7 +3306,7 @@ static void OptTests (void)
{
Line* L2 [2];
const char* BitOps [] = {
static const char* BitOps [] = {
"\tand\t",
"\tora\t",
"\teor\t",
@ -3401,6 +3403,127 @@ static void OptTests (void)
static void OptBitOps (void)
/* Optimize bit oeprations */
{
Line* L2 [2];
/* Walk over the code */
Line* L = FirstCode;
while (L) {
/* Search for
*
* lda xxx
* and #$yy ; adc/eor/ora
* sta xxx
*
* and replace it by
*
* lda #$yy
* and xxx
* sta xxx
*
* While this saves nothing here, it transforms the code to contain an
* explicit register load that may be removed by the basic block
* optimization later. As a special optimization for the 65C02, the
* "ora" and "and" ops may be replaced by "trb" and "tsb" resp. if the
* value in A is not used later.
*/
if (LineMatch (L, "\tlda\t") &&
L->Line[5] != '#' &&
GetNextCodeLines (L, L2, 2) &&
LineMatch (L2[1], "\tsta\t") &&
strcmp (L->Line+5, L2[1]->Line+5) == 0) {
if (LineMatch (L2[0], "\tand\t#$")) {
unsigned Val = GetHexNum (L2[0]->Line+7);
if (Val == 0x00) {
/* AND with 0x00, remove the mem access */
FreeLine (L);
FreeLine (L2[1]);
/* Replace the AND by a load */
L = ReplaceLine (L2[0], "\tlda\t#$%02X", Val);
} else if (Val == 0xFF) {
/* AND with 0xFF, just load the value from memory */
FreeLines (L2[0], L2[1]);
} else if (CPU == CPU_65C02 &&
!IsXAddrMode (L) &&
!IsYAddrMode (L) &&
!RegAUsed (L2[1])) {
/* Replace by trb */
ReplaceLine (L, "\tlda\t#$%02X", (~Val) & 0xFF);
ReplaceLine (L2[0], "\ttrb\t%s", L2[1]->Line+5);
FreeLine (L2[1]);
L = L2[0];
} else {
/* Just reorder */
L = ReplaceLine (L, "\tlda\t#$%02X", Val);
ReplaceLine (L2[0], "\tand\t%s", L2[1]->Line+5);
L = L2[1];
}
} else if (LineMatch (L2[0], "\tora\t#$")) {
unsigned Val = GetHexNum (L2[0]->Line+7);
if (Val == 0x00) {
/* ORA with 0x00, just load the value from memory */
FreeLines (L2[0], L2[1]);
} else if (Val == 0xFF) {
/* ORA with 0xFF, replace by a store of $FF */
FreeLine (L);
ReplaceLine (L2[0], "\tlda\t#$FF");
} else if (CPU == CPU_65C02 &&
!IsXAddrMode (L) &&
!IsYAddrMode (L) &&
!RegAUsed (L2[1])) {
/* Replace by trb */
ReplaceLine (L, "\tlda\t#$%02X", Val);
ReplaceLine (L2[0], "\ttsb\t%s", L2[1]->Line+5);
FreeLine (L2[1]);
L = L2[0];
} else {
/* Just reorder */
L = ReplaceLine (L, "\tlda\t#$%02X", Val);
ReplaceLine (L2[0], "\tora\t%s", L2[1]->Line+5);
L = L2[1];
}
} else if (LineMatch (L2[0], "\teor\t#$") ||
LineMatch (L2[0], "\tadc\t#$")) {
/* Just reorder */
L = ReplaceLine (L, "\tlda\t%s", L2[0]->Line+5);
ReplaceLine (L2[0], "\t%.3s\t%s", L2[0]->Line+1, L2[1]->Line+5);
}
}
/* Next line */
L = NextCodeLine (L);
}
}
static void OptNeg (void)
/* Optimize the "bnegax/jeq" and "bnegax/jne" sequences */
{
@ -4268,21 +4391,37 @@ static void OptRTS (void)
static void OptOnePass (unsigned long Flag, void (*F) (void))
/* Call one optimizer pass if enabled */
{
if ((OptDisable & Flag) == 0) {
F ();
} else if (Verbose || Debug) {
printf ("Optimizer pass %04lX skipped\n", Flag);
}
}
void OptDoOpt (void)
/* Run the optimizer over the collected stuff */
{
typedef void (*OptFunc)(void);
/* Table with optimizer steps - are called in this order */
static const OptFunc OptFuncs [] = {
OptCompares1, /* Optimize compares - first step */
OptDeadJumps, /* Remove dead jumps */
OptLoads, /* Remove unnecessary loads */
OptRegLoads, /* Remove unnecessary register loads */
OptPtrOps, /* Optimize stores through pointers */
OptRegVars, /* Optimize use of register variables */
OptDoubleJumps, /* Remove jump cascades - must be used before OptNeg */
OptNeg, /* Remove unnecessary boolean negates */
OptJumpRTS, /* Replace jumps to an RTS by an RTS */
OptBoolTransforms, /* Optimize boolean transforms */
OptCompares2, /* Optimize compares */
OptTests, /* Remove unnecessary tests */
OptBitOps, /* Optimize bit operations */
OptTriples, /* Optimize several triples */
OptBlocks, /* Optimize basic blocks */
OptRegLoads, /* Remove unnecessary register loads (another pass) */
OptBlocks, /* Optimize basic blocks */
OptJumps, /* Optimize jumps */
OptRTS, /* Optimize jsr/rts sequences */
};
unsigned long Flags;
unsigned I;
/* Find and remember the first line of code */
FindCodeStart ();
@ -4293,57 +4432,14 @@ void OptDoOpt (void)
CreateLabelList ();
/* Ok, now start the real optimizations */
/* Optimize compares - first step */
OptOnePass (0x0001, OptCompares1);
/* Remove dead jumps */
OptOnePass (0x0002, OptDeadJumps);
/* Remove unnecessary loads */
OptOnePass (0x0004, OptLoads);
/* Remove unnecessary register loads */
OptOnePass (0x0008, OptRegLoads);
/* Optimize stores through pointers */
OptOnePass (0x0010, OptPtrOps);
/* Optimize use of register variables */
OptOnePass (0x0020, OptRegVars);
/* Remove jump cascades - must be used before OptNeg */
OptOnePass (0x0040, OptDoubleJumps);
/* Remove unnecessary boolean negates */
OptOnePass (0x0080, OptNeg);
/* Replace jumps to an RTS by an RTS */
OptOnePass (0x0100, OptJumpRTS);
/* Optimize boolean transforms */
OptOnePass (0x0200, OptBoolTransforms);
/* Optimize compares */
OptOnePass (0x0400, OptCompares2);
/* Remove unnecessary tests */
OptOnePass (0x0800, OptTests);
/* Optimize several triples */
OptOnePass (0x1000, OptTriples);
/* Optimize basic blocks */
OptOnePass (0x2000, OptBlocks);
/* Remove unnecessary register loads (another pass) */
OptOnePass (0x0008, OptRegLoads);
/* Optimize jumps */
OptOnePass (0x4000, OptJumps);
/* Optimize jsr/rts sequences */
OptOnePass (0x8000, OptRTS);
Flags = 1UL;
for (I = 0; I < sizeof(OptFuncs)/sizeof(OptFuncs[0]); ++I) {
if ((OptDisable & Flags) == 0) {
OptFuncs[I] ();
} else if (Verbose || Debug) {
printf ("Optimizer pass %u skipped\n", I);
}
}
}