mirror of
https://github.com/cc65/cc65.git
synced 2025-01-13 09:31:53 +00:00
New optimization
git-svn-id: svn://svn.cc65.org/cc65/trunk@2436 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
6028eaac0c
commit
3499efea8f
@ -1542,7 +1542,8 @@ static OptFunc DOptStoreLoad = { OptStoreLoad, "OptStoreLoad", 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 DOptTest1 = { OptTest1, "OptTest1", 100, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptTransfers = { OptTransfers, "OptTransfers", 0, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptTransfers1 = { OptTransfers1, "OptTransfers1", 0, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptTransfers2 = { OptTransfers2, "OptTransfers2", 60, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptUnusedLoads = { OptUnusedLoads, "OptUnusedLoads", 0, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptUnusedStores = { OptUnusedStores, "OptUnusedStores", 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
@ -1610,7 +1611,8 @@ static OptFunc* OptFuncs[] = {
|
||||
&DOptSub1,
|
||||
&DOptSub2,
|
||||
&DOptTest1,
|
||||
&DOptTransfers,
|
||||
&DOptTransfers1,
|
||||
&DOptTransfers2,
|
||||
&DOptUnusedLoads,
|
||||
&DOptUnusedStores,
|
||||
};
|
||||
@ -1781,15 +1783,15 @@ static void WriteOptStats (const char* Name)
|
||||
|
||||
/* Write a header */
|
||||
fprintf (F,
|
||||
"; Optimizer Total Last Total Last\n"
|
||||
"; Step Runs Runs Chg Chg\n");
|
||||
"; Optimizer Total Last Total Last\n"
|
||||
"; Step Runs Runs Chg Chg\n");
|
||||
|
||||
|
||||
/* Write the data */
|
||||
for (I = 0; I < OPTFUNC_COUNT; ++I) {
|
||||
const OptFunc* O = OptFuncs[I];
|
||||
fprintf (F,
|
||||
"%-20s %6lu %6lu %6lu %6lu\n",
|
||||
"%-20s %10lu %10lu %10lu %10lu\n",
|
||||
O->Name,
|
||||
O->TotalRuns,
|
||||
O->LastRuns,
|
||||
@ -1934,7 +1936,7 @@ static unsigned RunOptGroup3 (CodeSeg* S)
|
||||
C += RunOptFunc (S, &DOptUnusedStores, 1);
|
||||
C += RunOptFunc (S, &DOptDupLoads, 1);
|
||||
C += RunOptFunc (S, &DOptStoreLoad, 1);
|
||||
C += RunOptFunc (S, &DOptTransfers, 1);
|
||||
C += RunOptFunc (S, &DOptTransfers1, 1);
|
||||
C += RunOptFunc (S, &DOptPushPop, 1);
|
||||
|
||||
Changes += C;
|
||||
@ -1981,6 +1983,7 @@ static unsigned RunOptGroup5 (CodeSeg* S)
|
||||
Changes += RunOptFunc (S, &DOptPush1, 1);
|
||||
Changes += RunOptFunc (S, &DOptPush2, 1);
|
||||
Changes += RunOptFunc (S, &DOptUnusedLoads, 1);
|
||||
Changes += RunOptFunc (S, &DOptTransfers2, 1);
|
||||
|
||||
/* Return the number of changes */
|
||||
return Changes;
|
||||
|
@ -1065,7 +1065,7 @@ unsigned OptStoreLoad (CodeSeg* S)
|
||||
|
||||
|
||||
|
||||
unsigned OptTransfers (CodeSeg* S)
|
||||
unsigned OptTransfers1 (CodeSeg* S)
|
||||
/* Remove transfers from one register to another and back */
|
||||
{
|
||||
unsigned Changes = 0;
|
||||
@ -1081,9 +1081,7 @@ unsigned OptTransfers (CodeSeg* S)
|
||||
/* Get next entry */
|
||||
CodeEntry* E = CS_GetEntry (S, I);
|
||||
|
||||
/* Check if it is a store instruction followed by a load from the
|
||||
* same address which is itself not followed by a conditional branch.
|
||||
*/
|
||||
/* Check if we have two transfer instructions */
|
||||
if ((E->Info & OF_XFR) != 0 &&
|
||||
(N = CS_GetNextEntry (S, I)) != 0 &&
|
||||
!CE_HasLabel (N) &&
|
||||
@ -1135,6 +1133,82 @@ NextEntry:
|
||||
|
||||
|
||||
|
||||
unsigned OptTransfers2 (CodeSeg* S)
|
||||
/* Replace loads followed by a register transfer by a load with the second
|
||||
* register if possible.
|
||||
*/
|
||||
{
|
||||
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 we have a load followed by a transfer where the loaded
|
||||
* register is not used later.
|
||||
*/
|
||||
if ((E->Info & OF_LOAD) != 0 &&
|
||||
(N = CS_GetNextEntry (S, I)) != 0 &&
|
||||
!CE_HasLabel (N) &&
|
||||
(N->Info & OF_XFR) != 0 &&
|
||||
GetRegInfo (S, I+2, E->Chg) != E->Chg) {
|
||||
|
||||
CodeEntry* X = 0;
|
||||
|
||||
if (E->OPC == OP65_LDA && N->OPC == OP65_TAX) {
|
||||
/* LDA/TAX - check for the right addressing modes */
|
||||
if (E->AM == AM65_IMM ||
|
||||
E->AM == AM65_ZP ||
|
||||
E->AM == AM65_ABS ||
|
||||
E->AM == AM65_ABSY) {
|
||||
/* Replace */
|
||||
X = NewCodeEntry (OP65_LDX, E->AM, E->Arg, 0, N->LI);
|
||||
}
|
||||
} else if (E->OPC == OP65_LDA && N->OPC == OP65_TAY) {
|
||||
/* LDA/TAY - check for the right addressing modes */
|
||||
if (E->AM == AM65_IMM ||
|
||||
E->AM == AM65_ZP ||
|
||||
E->AM == AM65_ZPX ||
|
||||
E->AM == AM65_ABS ||
|
||||
E->AM == AM65_ABSX) {
|
||||
/* Replace */
|
||||
X = NewCodeEntry (OP65_LDY, E->AM, E->Arg, 0, N->LI);
|
||||
}
|
||||
} else if (E->OPC == OP65_LDY && N->OPC == OP65_TYA) {
|
||||
/* LDY/TYA. LDA supports all addressing modes LDY does */
|
||||
X = NewCodeEntry (OP65_LDA, E->AM, E->Arg, 0, N->LI);
|
||||
} else if (E->OPC == OP65_LDX && N->OPC == OP65_TXA) {
|
||||
/* LDX/TXA. LDA doesn't support zp,y, so we must map it to
|
||||
* abs,y instead.
|
||||
*/
|
||||
am_t AM = (E->AM == AM65_ZPY)? AM65_ABSY : E->AM;
|
||||
X = NewCodeEntry (OP65_LDA, AM, E->Arg, 0, N->LI);
|
||||
}
|
||||
|
||||
/* If we have a load entry, add it and remove the old stuff */
|
||||
if (X) {
|
||||
CS_InsertEntry (S, X, I+2);
|
||||
CS_DelEntries (S, I, 2);
|
||||
++Changes;
|
||||
--I; /* Correct for one entry less */
|
||||
}
|
||||
}
|
||||
|
||||
/* Next entry */
|
||||
++I;
|
||||
}
|
||||
|
||||
/* Return the number of changes made */
|
||||
return Changes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned OptPushPop (CodeSeg* S)
|
||||
/* Remove a PHA/PLA sequence were A is not used later */
|
||||
{
|
||||
@ -1264,7 +1338,6 @@ unsigned OptPrecalc (CodeSeg* S)
|
||||
} else if (E->AM == AM65_ZP) {
|
||||
int R = ZPRegVal (E->Use, In);
|
||||
if (RegValIsKnown (R)) {
|
||||
printf ("A: %02X tmp1: %02X\n", In->RegA, R);
|
||||
/* Accu EOR zp with known contents */
|
||||
Arg = MakeHexArg (In->RegA ^ R);
|
||||
}
|
||||
|
@ -102,9 +102,14 @@ unsigned OptDupLoads (CodeSeg* S);
|
||||
unsigned OptStoreLoad (CodeSeg* S);
|
||||
/* Remove a store followed by a load from the same location. */
|
||||
|
||||
unsigned OptTransfers (CodeSeg* S);
|
||||
unsigned OptTransfers1 (CodeSeg* S);
|
||||
/* Remove transfers from one register to another and back */
|
||||
|
||||
unsigned OptTransfers2 (CodeSeg* S);
|
||||
/* Replace loads followed by a register transfer by a load with the second
|
||||
* register if possible.
|
||||
*/
|
||||
|
||||
unsigned OptPushPop (CodeSeg* S);
|
||||
/* Remove a PHA/PLA sequence were A is not used later */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user