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 DOptBNegAX2 = { OptBNegAX2, "OptBNegAX2", 100, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptBNegAX3 = { OptBNegAX3, "OptBNegAX3", 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 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 DOptBoolCmp = { OptBoolCmp, "OptBoolCmp", 100, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptBoolTrans = { OptBoolTrans, "OptBoolTrans", 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 };
|
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 DOptLoad1 = { OptLoad1, "OptLoad1", 100, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptLoad2 = { OptLoad2, "OptLoad2", 200, 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 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 DOptLoadStoreLoad= { OptLoadStoreLoad,"OptLoadStoreLoad", 0, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptLongAssign = { OptLongAssign, "OptLongAssign", 100, 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 };
|
static OptFunc DOptLongCopy = { OptLongCopy, "OptLongCopy", 100, 0, 0, 0, 0, 0 };
|
||||||
@@ -238,7 +241,8 @@ static OptFunc* OptFuncs[] = {
|
|||||||
&DOptBNegAX2,
|
&DOptBNegAX2,
|
||||||
&DOptBNegAX3,
|
&DOptBNegAX3,
|
||||||
&DOptBNegAX4,
|
&DOptBNegAX4,
|
||||||
&DOptBinOps,
|
&DOptBinOps1,
|
||||||
|
&DOptBinOps2,
|
||||||
&DOptBoolCmp,
|
&DOptBoolCmp,
|
||||||
&DOptBoolTrans,
|
&DOptBoolTrans,
|
||||||
&DOptBoolUnary1,
|
&DOptBoolUnary1,
|
||||||
@@ -273,6 +277,8 @@ static OptFunc* OptFuncs[] = {
|
|||||||
&DOptLoad1,
|
&DOptLoad1,
|
||||||
&DOptLoad2,
|
&DOptLoad2,
|
||||||
&DOptLoad3,
|
&DOptLoad3,
|
||||||
|
&DOptLoadStore1,
|
||||||
|
&DOptLoadStore2,
|
||||||
&DOptLoadStoreLoad,
|
&DOptLoadStoreLoad,
|
||||||
&DOptLongAssign,
|
&DOptLongAssign,
|
||||||
&DOptLongCopy,
|
&DOptLongCopy,
|
||||||
@@ -649,6 +655,7 @@ static unsigned RunOptGroup1 (CodeSeg* S)
|
|||||||
Changes += RunOptFunc (S, &DOptSub1, 1);
|
Changes += RunOptFunc (S, &DOptSub1, 1);
|
||||||
Changes += RunOptFunc (S, &DOptSub3, 1);
|
Changes += RunOptFunc (S, &DOptSub3, 1);
|
||||||
Changes += RunOptFunc (S, &DOptLongAssign, 1);
|
Changes += RunOptFunc (S, &DOptLongAssign, 1);
|
||||||
|
Changes += RunOptFunc (S, &DOptLoadStore2, 1);
|
||||||
Changes += RunOptFunc (S, &DOptStore4, 1);
|
Changes += RunOptFunc (S, &DOptStore4, 1);
|
||||||
Changes += RunOptFunc (S, &DOptStore5, 1);
|
Changes += RunOptFunc (S, &DOptStore5, 1);
|
||||||
Changes += RunOptFunc (S, &DOptShift1, 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, &DOptJumpTarget3, 1); /* After OptCondBranches2 */
|
||||||
C += RunOptFunc (S, &DOptUnusedLoads, 1);
|
C += RunOptFunc (S, &DOptUnusedLoads, 1);
|
||||||
C += RunOptFunc (S, &DOptUnusedStores, 1);
|
C += RunOptFunc (S, &DOptUnusedStores, 1);
|
||||||
C += RunOptFunc (S, &DOptDupLoads, 1);
|
|
||||||
C += RunOptFunc (S, &DOptStoreLoad, 1);
|
C += RunOptFunc (S, &DOptStoreLoad, 1);
|
||||||
C += RunOptFunc (S, &DOptLoadStoreLoad, 1);
|
C += RunOptFunc (S, &DOptLoadStoreLoad, 1);
|
||||||
|
C += RunOptFunc (S, &DOptDupLoads, 1);
|
||||||
|
C += RunOptFunc (S, &DOptLoadStore1, 1);
|
||||||
C += RunOptFunc (S, &DOptTransfers1, 1);
|
C += RunOptFunc (S, &DOptTransfers1, 1);
|
||||||
C += RunOptFunc (S, &DOptTransfers3, 1);
|
C += RunOptFunc (S, &DOptTransfers3, 1);
|
||||||
C += RunOptFunc (S, &DOptTransfers4, 1);
|
C += RunOptFunc (S, &DOptTransfers4, 1);
|
||||||
@@ -755,7 +763,8 @@ static unsigned RunOptGroup3 (CodeSeg* S)
|
|||||||
C += RunOptFunc (S, &DOptPrecalc, 1);
|
C += RunOptFunc (S, &DOptPrecalc, 1);
|
||||||
C += RunOptFunc (S, &DOptShiftBack, 1);
|
C += RunOptFunc (S, &DOptShiftBack, 1);
|
||||||
C += RunOptFunc (S, &DOptSignExtended, 1);
|
C += RunOptFunc (S, &DOptSignExtended, 1);
|
||||||
C += RunOptFunc (S, &DOptBinOps, 1);
|
C += RunOptFunc (S, &DOptBinOps1, 1);
|
||||||
|
C += RunOptFunc (S, &DOptBinOps2, 1);
|
||||||
|
|
||||||
Changes += C;
|
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)
|
unsigned OptLoadStoreLoad (CodeSeg* S)
|
||||||
/* Search for the sequence
|
/* Search for the sequence
|
||||||
**
|
**
|
||||||
@@ -626,7 +669,7 @@ unsigned OptLoadStoreLoad (CodeSeg* S)
|
|||||||
strcmp (L[0]->Arg, L[2]->Arg) == 0) {
|
strcmp (L[0]->Arg, L[2]->Arg) == 0) {
|
||||||
|
|
||||||
/* Remove the second load */
|
/* Remove the second load */
|
||||||
CS_DelEntries (S, I+2, 1);
|
CS_DelEntry (S, I+2);
|
||||||
|
|
||||||
/* Remember, we had changes */
|
/* Remember, we had changes */
|
||||||
++Changes;
|
++Changes;
|
||||||
|
|||||||
@@ -66,6 +66,9 @@ unsigned OptDupLoads (CodeSeg* S);
|
|||||||
unsigned OptStoreLoad (CodeSeg* S);
|
unsigned OptStoreLoad (CodeSeg* S);
|
||||||
/* Remove a store followed by a load from the same location. */
|
/* 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);
|
unsigned OptLoadStoreLoad (CodeSeg* S);
|
||||||
/* Remove a load, store followed by a reload of the same location. */
|
/* 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)
|
unsigned OptLoad1 (CodeSeg* S)
|
||||||
/* Search for a call to ldaxysp where X is not used later and replace it by
|
/* Search for a call to ldaxysp where X is not used later and replace it by
|
||||||
** a load of just the A register.
|
** 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
|
/* Search for an AND/EOR/ORA where the value of A or the operand is known and
|
||||||
** replace it by something simpler.
|
** replace it by something simpler.
|
||||||
*/
|
*/
|
||||||
@@ -902,3 +948,59 @@ unsigned OptBinOps (CodeSeg* S)
|
|||||||
/* Return the number of changes made */
|
/* Return the number of changes made */
|
||||||
return Changes;
|
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);
|
unsigned OptGotoSPAdj (CodeSeg* S);
|
||||||
/* Optimize SP adjustment for forward 'goto' */
|
/* 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);
|
unsigned OptLoad1 (CodeSeg* S);
|
||||||
/* Search for a call to ldaxysp where X is not used later and replace it by
|
/* Search for a call to ldaxysp where X is not used later and replace it by
|
||||||
** a load of just the A register.
|
** a load of just the A register.
|
||||||
@@ -107,11 +110,16 @@ unsigned OptLoad1 (CodeSeg* S);
|
|||||||
unsigned OptLoad2 (CodeSeg* S);
|
unsigned OptLoad2 (CodeSeg* S);
|
||||||
/* Replace calls to ldaxysp by inline code */
|
/* 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
|
/* Search for an AND/EOR/ORA where the value of A or the operand is known and
|
||||||
** replace it by something simpler.
|
** 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 */
|
/* End of coptmisc.h */
|
||||||
|
|||||||
Reference in New Issue
Block a user