From 4f3a96a535a94b91813ce7651dcd08de9dc95cd3 Mon Sep 17 00:00:00 2001 From: acqn Date: Fri, 18 Sep 2020 20:22:58 +0800 Subject: [PATCH] Added new opt OptPushPop2. Also renamed OptPushPop to OptPushPop1. --- src/cc65/codeopt.c | 8 ++-- src/cc65/coptind.c | 93 +++++++++++++++++++++++++++++++++++++++++++++- src/cc65/coptind.h | 7 +++- 3 files changed, 101 insertions(+), 7 deletions(-) diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index 4a7722830..f83a8d9f8 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -167,7 +167,8 @@ static OptFunc DOptPtrStore2 = { OptPtrStore2, "OptPtrStore2", 65, 0, static OptFunc DOptPtrStore3 = { OptPtrStore3, "OptPtrStore3", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptPush1 = { OptPush1, "OptPush1", 65, 0, 0, 0, 0, 0 }; static OptFunc DOptPush2 = { OptPush2, "OptPush2", 50, 0, 0, 0, 0, 0 }; -static OptFunc DOptPushPop = { OptPushPop, "OptPushPop", 0, 0, 0, 0, 0, 0 }; +static OptFunc DOptPushPop1 = { OptPushPop1, "OptPushPop1", 0, 0, 0, 0, 0, 0 }; +static OptFunc DOptPushPop2 = { OptPushPop2, "OptPushPop2", 0, 0, 0, 0, 0, 0 }; static OptFunc DOptRTS = { OptRTS, "OptRTS", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptRTSJumps1 = { OptRTSJumps1, "OptRTSJumps1", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptRTSJumps2 = { OptRTSJumps2, "OptRTSJumps2", 100, 0, 0, 0, 0, 0 }; @@ -269,7 +270,7 @@ static OptFunc* OptFuncs[] = { &DOptPtrStore3, &DOptPush1, &DOptPush2, - &DOptPushPop, + &DOptPushPop1, &DOptRTS, &DOptRTSJumps1, &DOptRTSJumps2, @@ -709,7 +710,8 @@ static unsigned RunOptGroup3 (CodeSeg* S) C += RunOptFunc (S, &DOptTransfers4, 1); C += RunOptFunc (S, &DOptStore1, 1); C += RunOptFunc (S, &DOptStore5, 1); - C += RunOptFunc (S, &DOptPushPop, 1); + C += RunOptFunc (S, &DOptPushPop1, 1); + C += RunOptFunc (S, &DOptPushPop2, 1); C += RunOptFunc (S, &DOptPrecalc, 1); Changes += C; diff --git a/src/cc65/coptind.c b/src/cc65/coptind.c index eada61871..4bb236692 100644 --- a/src/cc65/coptind.c +++ b/src/cc65/coptind.c @@ -1069,8 +1069,8 @@ unsigned OptTransfers4 (CodeSeg* S) -unsigned OptPushPop (CodeSeg* S) -/* Remove a PHA/PLA sequence were A is not used later */ +unsigned OptPushPop1 (CodeSeg* S) +/* Remove a PHA/PLA sequence were A not used later */ { unsigned Changes = 0; unsigned Push = 0; /* Index of push insn */ @@ -1199,6 +1199,95 @@ unsigned OptPushPop (CodeSeg* S) +unsigned OptPushPop2 (CodeSeg* S) +/* Remove a PHP/PLP sequence were no processor flags changed inside */ +{ + unsigned Changes = 0; + unsigned Push = 0; /* Index of push insn */ + unsigned Pop = 0; /* Index of pop insn */ + enum { + Searching, + FoundPush, + FoundPop + } State = Searching; + + /* Walk over the entries. Look for a push instruction that is followed by + ** a pop later, where the pop is not followed by an conditional branch, + ** and where the value of the A register is not used later on. + ** Look out for the following problems: + ** + ** - There may be another PHP/PLP inside the sequence: Restart it. + ** - All jumps inside the sequence must not go outside the sequence, + ** otherwise it would be too complicated to remove the PHP/PLP. + */ + unsigned I = 0; + while (I < CS_GetEntryCount (S)) { + + /* Get next entry */ + CodeEntry* E = CS_GetEntry (S, I); + + switch (State) { + + case Searching: + if (E->OPC == OP65_PHP) { + /* Found start of sequence */ + Push = I; + State = FoundPush; + } + break; + + case FoundPush: + if (E->OPC == OP65_PHP) { + /* Inner push/pop, restart */ + Push = I; + } else if (E->OPC == OP65_PLP) { + /* Found a matching pop */ + Pop = I; + /* Check that the block between Push and Pop is a basic + ** block (one entry, one exit). Otherwise ignore it. + */ + if (CS_IsBasicBlock (S, Push, Pop)) { + State = FoundPop; + } else { + /* Go into searching mode again */ + State = Searching; + } + } else if ((E->Info & OF_BRA) == 0 && + (E->Info & OF_STORE) == 0 && + E->OPC != OP65_NOP && + E->OPC != OP65_TSX) { + /* Don't bother skipping dead code */ + State = Searching; + } + break; + + case FoundPop: + /* We can remove the PHP and PLP instructions */ + CS_DelEntry (S, Pop); + CS_DelEntry (S, Push); + + /* Correct I so we continue with THIS insn */ + I -= 3; + + /* Remember we had changes */ + ++Changes; + + /* Go into search mode again */ + State = Searching; + break; + + } + + /* Next entry */ + ++I; + } + + /* Return the number of changes made */ + return Changes; +} + + + unsigned OptPrecalc (CodeSeg* S) /* Replace immediate operations with the accu where the current contents are ** known by a load of the final value. diff --git a/src/cc65/coptind.h b/src/cc65/coptind.h index 64acb10d8..ab9179e96 100644 --- a/src/cc65/coptind.h +++ b/src/cc65/coptind.h @@ -82,8 +82,11 @@ unsigned OptTransfers4 (CodeSeg* S); ** by a load of the second register if possible. */ -unsigned OptPushPop (CodeSeg* S); -/* Remove a PHA/PLA sequence were A is not used later */ +unsigned OptPushPop1 (CodeSeg* S); +/* Remove a PHA/PLA sequence were A not used later */ + +unsigned OptPushPop2 (CodeSeg* S); +/* Remove a PHP/PLP sequence were no processor flags changed inside */ unsigned OptPrecalc (CodeSeg* S); /* Replace immediate operations with the accu where the current contents are