diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index baa44f99e..3a2c2a35d 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -197,6 +197,7 @@ static OptFunc DOptStore3 = { OptStore3, "OptStore3", 120, 0, static OptFunc DOptStore4 = { OptStore4, "OptStore4", 50, 0, 0, 0, 0, 0 }; static OptFunc DOptStore5 = { OptStore5, "OptStore5", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptStoreLoad = { OptStoreLoad, "OptStoreLoad", 0, 0, 0, 0, 0, 0 }; +static OptFunc DOptLoadStoreLoad= { OptLoadStoreLoad,"OptLoadStoreLoad", 0, 0, 0, 0, 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 DOptSub3 = { OptSub3, "OptSub3", 100, 0, 0, 0, 0, 0 }; @@ -307,6 +308,7 @@ static OptFunc* OptFuncs[] = { &DOptStore4, &DOptStore5, &DOptStoreLoad, + &DOptLoadStoreLoad, &DOptSub1, &DOptSub2, &DOptSub3, @@ -723,6 +725,7 @@ static unsigned RunOptGroup3 (CodeSeg* S) C += RunOptFunc (S, &DOptUnusedStores, 1); C += RunOptFunc (S, &DOptDupLoads, 1); C += RunOptFunc (S, &DOptStoreLoad, 1); + C += RunOptFunc (S, &DOptLoadStoreLoad, 1); C += RunOptFunc (S, &DOptTransfers1, 1); C += RunOptFunc (S, &DOptTransfers3, 1); C += RunOptFunc (S, &DOptTransfers4, 1); diff --git a/src/cc65/coptind.c b/src/cc65/coptind.c index a080cfb20..9e9985c10 100644 --- a/src/cc65/coptind.c +++ b/src/cc65/coptind.c @@ -581,6 +581,60 @@ unsigned OptStoreLoad (CodeSeg* S) +unsigned OptLoadStoreLoad (CodeSeg* S) +/* Search for the sequence +** +** ld. xx +** st. yy +** ld. xx +** +** and remove the useless load. +*/ +{ + unsigned Changes = 0; + + /* Walk over the entries */ + unsigned I = 0; + while (I < CS_GetEntryCount (S)) { + + CodeEntry* L[3]; + + /* Get next entry */ + L[0] = CS_GetEntry (S, I); + + /* Check for the sequence */ + if ((L[0]->OPC == OP65_LDA || + L[0]->OPC == OP65_LDX || + L[0]->OPC == OP65_LDY) && + (L[0]->AM == AM65_ABS || L[0]->AM == AM65_ZP) && + !CS_RangeHasLabel (S, I+1, 3) && + CS_GetEntries (S, L+1, I+1, 2) && + (L[1]->OPC == OP65_STA || + L[1]->OPC == OP65_STX || + L[1]->OPC == OP65_STY) && + L[2]->OPC == L[0]->OPC && + L[2]->AM == L[0]->AM && + strcmp (L[0]->Arg, L[2]->Arg) == 0) { + + /* Remove the second load */ + CS_DelEntries (S, I+2, 1); + + /* Remember, we had changes */ + ++Changes; + + } + + /* Next entry */ + ++I; + + } + + /* Return the number of changes made */ + return Changes; +} + + + unsigned OptTransfers1 (CodeSeg* S) /* Remove transfers from one register to another and back */ { diff --git a/src/cc65/coptind.h b/src/cc65/coptind.h index c7ecf4194..6d39ee1f8 100644 --- a/src/cc65/coptind.h +++ b/src/cc65/coptind.h @@ -64,6 +64,9 @@ unsigned OptDupLoads (CodeSeg* S); unsigned OptStoreLoad (CodeSeg* S); /* Remove a store followed by a load from the same location. */ +unsigned OptLoadStoreLoad (CodeSeg* S); +/* Remove a load, store followed by a reload of the same location. */ + unsigned OptTransfers1 (CodeSeg* S); /* Remove transfers from one register to another and back */