mirror of
https://github.com/cc65/cc65.git
synced 2025-01-19 02:33:19 +00:00
Added new opt OptPushPop2.
Also renamed OptPushPop to OptPushPop1.
This commit is contained in:
parent
0f66f7569e
commit
4f3a96a535
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user