Added a few simple optimizations that resolve most of #2527.
This commit is contained in:
@@ -119,7 +119,8 @@ static OptFunc DOptBNegAX1 = { OptBNegAX1, "OptBNegAX1", 100, 0,
|
||||
static OptFunc DOptBNegAX2 = { OptBNegAX2, "OptBNegAX2", 100, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptBNegAX3 = { OptBNegAX3, "OptBNegAX3", 100, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptBNegAX4 = { OptBNegAX4, "OptBNegAX4", 100, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptBinOps = { OptBinOps, "OptBinOps", 0, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptBinOps1 = { OptBinOps1, "OptBinOps1", 0, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptBinOps2 = { OptBinOps2, "OptBinOps2", 0, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptBoolCmp = { OptBoolCmp, "OptBoolCmp", 100, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptBoolTrans = { OptBoolTrans, "OptBoolTrans", 100, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptBoolUnary1 = { OptBoolUnary1, "OptBoolUnary1", 40, 0, 0, 0, 0, 0 };
|
||||
@@ -154,6 +155,8 @@ static OptFunc DOptJumpTarget3 = { OptJumpTarget3, "OptJumpTarget3", 100, 0,
|
||||
static OptFunc DOptLoad1 = { OptLoad1, "OptLoad1", 100, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptLoad2 = { OptLoad2, "OptLoad2", 200, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptLoad3 = { OptLoad3, "OptLoad3", 0, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptLoadStore1 = { OptLoadStore1, "OptLoadStore1", 0, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptLoadStore2 = { OptLoadStore2, "OptLoadStore2", 0, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptLoadStoreLoad= { OptLoadStoreLoad,"OptLoadStoreLoad", 0, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptLongAssign = { OptLongAssign, "OptLongAssign", 100, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptLongCopy = { OptLongCopy, "OptLongCopy", 100, 0, 0, 0, 0, 0 };
|
||||
@@ -238,7 +241,8 @@ static OptFunc* OptFuncs[] = {
|
||||
&DOptBNegAX2,
|
||||
&DOptBNegAX3,
|
||||
&DOptBNegAX4,
|
||||
&DOptBinOps,
|
||||
&DOptBinOps1,
|
||||
&DOptBinOps2,
|
||||
&DOptBoolCmp,
|
||||
&DOptBoolTrans,
|
||||
&DOptBoolUnary1,
|
||||
@@ -273,6 +277,8 @@ static OptFunc* OptFuncs[] = {
|
||||
&DOptLoad1,
|
||||
&DOptLoad2,
|
||||
&DOptLoad3,
|
||||
&DOptLoadStore1,
|
||||
&DOptLoadStore2,
|
||||
&DOptLoadStoreLoad,
|
||||
&DOptLongAssign,
|
||||
&DOptLongCopy,
|
||||
@@ -649,6 +655,7 @@ static unsigned RunOptGroup1 (CodeSeg* S)
|
||||
Changes += RunOptFunc (S, &DOptSub1, 1);
|
||||
Changes += RunOptFunc (S, &DOptSub3, 1);
|
||||
Changes += RunOptFunc (S, &DOptLongAssign, 1);
|
||||
Changes += RunOptFunc (S, &DOptLoadStore2, 1);
|
||||
Changes += RunOptFunc (S, &DOptStore4, 1);
|
||||
Changes += RunOptFunc (S, &DOptStore5, 1);
|
||||
Changes += RunOptFunc (S, &DOptShift1, 1);
|
||||
@@ -741,9 +748,10 @@ static unsigned RunOptGroup3 (CodeSeg* S)
|
||||
C += RunOptFunc (S, &DOptJumpTarget3, 1); /* After OptCondBranches2 */
|
||||
C += RunOptFunc (S, &DOptUnusedLoads, 1);
|
||||
C += RunOptFunc (S, &DOptUnusedStores, 1);
|
||||
C += RunOptFunc (S, &DOptDupLoads, 1);
|
||||
C += RunOptFunc (S, &DOptStoreLoad, 1);
|
||||
C += RunOptFunc (S, &DOptLoadStoreLoad, 1);
|
||||
C += RunOptFunc (S, &DOptDupLoads, 1);
|
||||
C += RunOptFunc (S, &DOptLoadStore1, 1);
|
||||
C += RunOptFunc (S, &DOptTransfers1, 1);
|
||||
C += RunOptFunc (S, &DOptTransfers3, 1);
|
||||
C += RunOptFunc (S, &DOptTransfers4, 1);
|
||||
@@ -755,7 +763,8 @@ static unsigned RunOptGroup3 (CodeSeg* S)
|
||||
C += RunOptFunc (S, &DOptPrecalc, 1);
|
||||
C += RunOptFunc (S, &DOptShiftBack, 1);
|
||||
C += RunOptFunc (S, &DOptSignExtended, 1);
|
||||
C += RunOptFunc (S, &DOptBinOps, 1);
|
||||
C += RunOptFunc (S, &DOptBinOps1, 1);
|
||||
C += RunOptFunc (S, &DOptBinOps2, 1);
|
||||
|
||||
Changes += C;
|
||||
|
||||
|
||||
@@ -590,6 +590,49 @@ unsigned OptStoreLoad (CodeSeg* S)
|
||||
|
||||
|
||||
|
||||
unsigned OptLoadStore1 (CodeSeg* S)
|
||||
/* Remove an 8 bit load followed by a store into the same location. */
|
||||
{
|
||||
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 it is a load instruction followed by a store into the
|
||||
** same address.
|
||||
*/
|
||||
if ((E->Info & OF_LOAD) != 0 &&
|
||||
(N = CS_GetNextEntry (S, I)) != 0 &&
|
||||
!CE_HasLabel (N) &&
|
||||
E->AM == N->AM &&
|
||||
((E->OPC == OP65_LDA && N->OPC == OP65_STA) ||
|
||||
(E->OPC == OP65_LDX && N->OPC == OP65_STX) ||
|
||||
(E->OPC == OP65_LDY && N->OPC == OP65_STY)) &&
|
||||
strcmp (E->Arg, N->Arg) == 0) {
|
||||
|
||||
/* Memory cell has already the correct value, remove the store */
|
||||
CS_DelEntry (S, I+1);
|
||||
|
||||
/* Remember, we had changes */
|
||||
++Changes;
|
||||
}
|
||||
|
||||
/* Next entry */
|
||||
++I;
|
||||
}
|
||||
|
||||
/* Return the number of changes made */
|
||||
return Changes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned OptLoadStoreLoad (CodeSeg* S)
|
||||
/* Search for the sequence
|
||||
**
|
||||
@@ -626,7 +669,7 @@ unsigned OptLoadStoreLoad (CodeSeg* S)
|
||||
strcmp (L[0]->Arg, L[2]->Arg) == 0) {
|
||||
|
||||
/* Remove the second load */
|
||||
CS_DelEntries (S, I+2, 1);
|
||||
CS_DelEntry (S, I+2);
|
||||
|
||||
/* Remember, we had changes */
|
||||
++Changes;
|
||||
|
||||
@@ -66,6 +66,9 @@ unsigned OptDupLoads (CodeSeg* S);
|
||||
unsigned OptStoreLoad (CodeSeg* S);
|
||||
/* Remove a store followed by a load from the same location. */
|
||||
|
||||
unsigned OptLoadStore1 (CodeSeg* S);
|
||||
/* Remove an 8 bit load followed by a store into the same location. */
|
||||
|
||||
unsigned OptLoadStoreLoad (CodeSeg* S);
|
||||
/* Remove a load, store followed by a reload of the same location. */
|
||||
|
||||
|
||||
@@ -582,11 +582,57 @@ unsigned OptGotoSPAdj (CodeSeg* S)
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Optimize stack load ops */
|
||||
/* Optimize stack load/store ops */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
unsigned OptLoadStore2 (CodeSeg* S)
|
||||
/* Remove 16 bit stack loads followed by a store into the same location. */
|
||||
{
|
||||
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 this is a 16 bit load followed by a store into the same
|
||||
** address.
|
||||
*/
|
||||
if (CE_IsCallTo (E, "ldaxysp") && /* Stack load ... */
|
||||
RegValIsKnown (E->RI->In.RegY) && /* ... with known offs */
|
||||
(N = CS_GetNextEntry (S, I)) != 0 && /* Next insn ... */
|
||||
!CE_HasLabel (N) && /* ... without label ... */
|
||||
N->OPC == OP65_LDY && /* ... is LDY */
|
||||
CE_IsKnownImm (N, E->RI->In.RegY-1) && /* Same offset as load */
|
||||
(N = CS_GetNextEntry (S, I+1)) != 0 && /* Next insn ... */
|
||||
!CE_HasLabel (N) && /* ... without label ... */
|
||||
CE_IsCallTo (N, "staxysp")) { /* ... is store */
|
||||
|
||||
/* Found - remove it. Leave the load in place. If it's unused, it
|
||||
** will get removed by later steps.
|
||||
*/
|
||||
CS_DelEntries (S, I+1, 2);
|
||||
|
||||
/* Remember, we had changes */
|
||||
++Changes;
|
||||
}
|
||||
|
||||
/* Next entry */
|
||||
++I;
|
||||
}
|
||||
|
||||
/* Return the number of changes made */
|
||||
return Changes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned OptLoad1 (CodeSeg* S)
|
||||
/* Search for a call to ldaxysp where X is not used later and replace it by
|
||||
** a load of just the A register.
|
||||
@@ -736,7 +782,7 @@ unsigned OptLoad2 (CodeSeg* S)
|
||||
|
||||
|
||||
|
||||
unsigned OptBinOps (CodeSeg* S)
|
||||
unsigned OptBinOps1 (CodeSeg* S)
|
||||
/* Search for an AND/EOR/ORA where the value of A or the operand is known and
|
||||
** replace it by something simpler.
|
||||
*/
|
||||
@@ -902,3 +948,59 @@ unsigned OptBinOps (CodeSeg* S)
|
||||
/* Return the number of changes made */
|
||||
return Changes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned OptBinOps2 (CodeSeg* S)
|
||||
/* Search for an AND/EOR/ORA for identical memory locations and replace it
|
||||
** by something simpler.
|
||||
*/
|
||||
{
|
||||
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 this is an 8 bit load followed by a bit operation with the
|
||||
** same memory cell.
|
||||
*/
|
||||
if (E->OPC == OP65_LDA &&
|
||||
(N = CS_GetNextEntry (S, I)) != 0 && /* Next insn ... */
|
||||
!CE_HasLabel (N) && /* ... without label ... */
|
||||
(N->OPC == OP65_AND || /* ... is AND/EOR/ORA ... */
|
||||
N->OPC == OP65_EOR ||
|
||||
N->OPC == OP65_ORA) &&
|
||||
E->AM == N->AM && /* ... with same addr mode ... */
|
||||
strcmp (E->Arg, N->Arg) == 0) { /* ... and same argument */
|
||||
|
||||
/* For an EOR, the result is zero. For the other instructions, the
|
||||
** result doesn't change so they can be removed.
|
||||
*/
|
||||
if (N->OPC == OP65_EOR) {
|
||||
/* Simply insert a load of the now known value. The flags will
|
||||
** be correct because of the load and the preceeding
|
||||
** instructions will be removed by later steps.
|
||||
*/
|
||||
CodeEntry* X = NewCodeEntry (OP65_LDA, AM65_IMM, "$00", 0, N->LI);
|
||||
CS_InsertEntry (S, X, I+2);
|
||||
} else {
|
||||
CS_DelEntry (S, I+1);
|
||||
}
|
||||
|
||||
/* Remember, we had changes */
|
||||
++Changes;
|
||||
}
|
||||
|
||||
/* Next entry */
|
||||
++I;
|
||||
}
|
||||
|
||||
/* Return the number of changes made */
|
||||
return Changes;
|
||||
}
|
||||
|
||||
@@ -99,6 +99,9 @@ unsigned OptStackPtrOps (CodeSeg* S);
|
||||
unsigned OptGotoSPAdj (CodeSeg* S);
|
||||
/* Optimize SP adjustment for forward 'goto' */
|
||||
|
||||
unsigned OptLoadStore2 (CodeSeg* S);
|
||||
/* Remove 16 bit stack loads followed by a store into the same location. */
|
||||
|
||||
unsigned OptLoad1 (CodeSeg* S);
|
||||
/* Search for a call to ldaxysp where X is not used later and replace it by
|
||||
** a load of just the A register.
|
||||
@@ -107,11 +110,16 @@ unsigned OptLoad1 (CodeSeg* S);
|
||||
unsigned OptLoad2 (CodeSeg* S);
|
||||
/* Replace calls to ldaxysp by inline code */
|
||||
|
||||
unsigned OptBinOps (CodeSeg* S);
|
||||
unsigned OptBinOps1 (CodeSeg* S);
|
||||
/* Search for an AND/EOR/ORA where the value of A or the operand is known and
|
||||
** replace it by something simpler.
|
||||
*/
|
||||
|
||||
unsigned OptBinOps2 (CodeSeg* S);
|
||||
/* Search for an AND/EOR/ORA for identical memory locations and replace it
|
||||
** by something simpler.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* End of coptmisc.h */
|
||||
|
||||
Reference in New Issue
Block a user