diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index 31bcfb390..cfa114f97 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -1542,7 +1542,8 @@ static OptFunc DOptStoreLoad = { OptStoreLoad, "OptStoreLoad", 0, 0, static OptFunc DOptSub1 = { OptSub1, "OptSub1", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptSub2 = { OptSub2, "OptSub2", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptTest1 = { OptTest1, "OptTest1", 100, 0, 0, 0, 0, 0 }; -static OptFunc DOptTransfers = { OptTransfers, "OptTransfers", 0, 0, 0, 0, 0, 0 }; +static OptFunc DOptTransfers1 = { OptTransfers1, "OptTransfers1", 0, 0, 0, 0, 0, 0 }; +static OptFunc DOptTransfers2 = { OptTransfers2, "OptTransfers2", 60, 0, 0, 0, 0, 0 }; static OptFunc DOptUnusedLoads = { OptUnusedLoads, "OptUnusedLoads", 0, 0, 0, 0, 0, 0 }; static OptFunc DOptUnusedStores = { OptUnusedStores, "OptUnusedStores", 0, 0, 0, 0, 0, 0 }; @@ -1610,7 +1611,8 @@ static OptFunc* OptFuncs[] = { &DOptSub1, &DOptSub2, &DOptTest1, - &DOptTransfers, + &DOptTransfers1, + &DOptTransfers2, &DOptUnusedLoads, &DOptUnusedStores, }; @@ -1781,15 +1783,15 @@ static void WriteOptStats (const char* Name) /* Write a header */ fprintf (F, - "; Optimizer Total Last Total Last\n" - "; Step Runs Runs Chg Chg\n"); + "; Optimizer Total Last Total Last\n" + "; Step Runs Runs Chg Chg\n"); /* Write the data */ for (I = 0; I < OPTFUNC_COUNT; ++I) { const OptFunc* O = OptFuncs[I]; fprintf (F, - "%-20s %6lu %6lu %6lu %6lu\n", + "%-20s %10lu %10lu %10lu %10lu\n", O->Name, O->TotalRuns, O->LastRuns, @@ -1934,7 +1936,7 @@ static unsigned RunOptGroup3 (CodeSeg* S) C += RunOptFunc (S, &DOptUnusedStores, 1); C += RunOptFunc (S, &DOptDupLoads, 1); C += RunOptFunc (S, &DOptStoreLoad, 1); - C += RunOptFunc (S, &DOptTransfers, 1); + C += RunOptFunc (S, &DOptTransfers1, 1); C += RunOptFunc (S, &DOptPushPop, 1); Changes += C; @@ -1981,6 +1983,7 @@ static unsigned RunOptGroup5 (CodeSeg* S) Changes += RunOptFunc (S, &DOptPush1, 1); Changes += RunOptFunc (S, &DOptPush2, 1); Changes += RunOptFunc (S, &DOptUnusedLoads, 1); + Changes += RunOptFunc (S, &DOptTransfers2, 1); /* Return the number of changes */ return Changes; diff --git a/src/cc65/coptind.c b/src/cc65/coptind.c index 23007611d..3bfb879df 100644 --- a/src/cc65/coptind.c +++ b/src/cc65/coptind.c @@ -1065,7 +1065,7 @@ unsigned OptStoreLoad (CodeSeg* S) -unsigned OptTransfers (CodeSeg* S) +unsigned OptTransfers1 (CodeSeg* S) /* Remove transfers from one register to another and back */ { unsigned Changes = 0; @@ -1081,9 +1081,7 @@ unsigned OptTransfers (CodeSeg* S) /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); - /* Check if it is a store instruction followed by a load from the - * same address which is itself not followed by a conditional branch. - */ + /* Check if we have two transfer instructions */ if ((E->Info & OF_XFR) != 0 && (N = CS_GetNextEntry (S, I)) != 0 && !CE_HasLabel (N) && @@ -1135,6 +1133,82 @@ NextEntry: +unsigned OptTransfers2 (CodeSeg* S) +/* Replace loads followed by a register transfer by a load with the second + * register if possible. + */ +{ + unsigned Changes = 0; + + /* Walk over the entries */ + unsigned I = 0; + while (I < CS_GetEntryCount (S)) { + + CodeEntry* N; + + /* Get next entry */ + CodeEntry* E = CS_GetEntry (S, I); + + /* Check if we have a load followed by a transfer where the loaded + * register is not used later. + */ + if ((E->Info & OF_LOAD) != 0 && + (N = CS_GetNextEntry (S, I)) != 0 && + !CE_HasLabel (N) && + (N->Info & OF_XFR) != 0 && + GetRegInfo (S, I+2, E->Chg) != E->Chg) { + + CodeEntry* X = 0; + + if (E->OPC == OP65_LDA && N->OPC == OP65_TAX) { + /* LDA/TAX - check for the right addressing modes */ + if (E->AM == AM65_IMM || + E->AM == AM65_ZP || + E->AM == AM65_ABS || + E->AM == AM65_ABSY) { + /* Replace */ + X = NewCodeEntry (OP65_LDX, E->AM, E->Arg, 0, N->LI); + } + } else if (E->OPC == OP65_LDA && N->OPC == OP65_TAY) { + /* LDA/TAY - check for the right addressing modes */ + if (E->AM == AM65_IMM || + E->AM == AM65_ZP || + E->AM == AM65_ZPX || + E->AM == AM65_ABS || + E->AM == AM65_ABSX) { + /* Replace */ + X = NewCodeEntry (OP65_LDY, E->AM, E->Arg, 0, N->LI); + } + } else if (E->OPC == OP65_LDY && N->OPC == OP65_TYA) { + /* LDY/TYA. LDA supports all addressing modes LDY does */ + X = NewCodeEntry (OP65_LDA, E->AM, E->Arg, 0, N->LI); + } else if (E->OPC == OP65_LDX && N->OPC == OP65_TXA) { + /* LDX/TXA. LDA doesn't support zp,y, so we must map it to + * abs,y instead. + */ + am_t AM = (E->AM == AM65_ZPY)? AM65_ABSY : E->AM; + X = NewCodeEntry (OP65_LDA, AM, E->Arg, 0, N->LI); + } + + /* If we have a load entry, add it and remove the old stuff */ + if (X) { + CS_InsertEntry (S, X, I+2); + CS_DelEntries (S, I, 2); + ++Changes; + --I; /* Correct for one entry less */ + } + } + + /* Next entry */ + ++I; + } + + /* Return the number of changes made */ + return Changes; +} + + + unsigned OptPushPop (CodeSeg* S) /* Remove a PHA/PLA sequence were A is not used later */ { @@ -1264,7 +1338,6 @@ unsigned OptPrecalc (CodeSeg* S) } else if (E->AM == AM65_ZP) { int R = ZPRegVal (E->Use, In); if (RegValIsKnown (R)) { - printf ("A: %02X tmp1: %02X\n", In->RegA, R); /* Accu EOR zp with known contents */ Arg = MakeHexArg (In->RegA ^ R); } diff --git a/src/cc65/coptind.h b/src/cc65/coptind.h index abad65359..ae72b1fbb 100644 --- a/src/cc65/coptind.h +++ b/src/cc65/coptind.h @@ -102,9 +102,14 @@ unsigned OptDupLoads (CodeSeg* S); unsigned OptStoreLoad (CodeSeg* S); /* Remove a store followed by a load from the same location. */ -unsigned OptTransfers (CodeSeg* S); +unsigned OptTransfers1 (CodeSeg* S); /* Remove transfers from one register to another and back */ +unsigned OptTransfers2 (CodeSeg* S); +/* Replace loads followed by a register transfer by a load with the second + * register if possible. + */ + unsigned OptPushPop (CodeSeg* S); /* Remove a PHA/PLA sequence were A is not used later */