1
0
mirror of https://github.com/cc65/cc65.git synced 2024-07-01 08:29:37 +00:00

More optimization

git-svn-id: svn://svn.cc65.org/cc65/trunk@838 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2001-08-05 20:37:14 +00:00
parent 59a94124a1
commit 24403e151e
6 changed files with 173 additions and 218 deletions

View File

@ -131,6 +131,7 @@ static const FuncInfo FuncInfoTable[] = {
{ "shreax3", REG_AX, REG_AX },
{ "shreax4", REG_AX, REG_AX },
{ "staspidx", REG_A | REG_Y, REG_Y },
{ "stax0sp", REG_AX, REG_Y },
{ "tosicmp", REG_AX, REG_AXY },
{ "tosdiva0", REG_AX, REG_AXY },
{ "tosdivax", REG_AX, REG_AXY },

View File

@ -1032,7 +1032,7 @@ static unsigned OptCmp6 (CodeSeg* S)
CodeEntry* E = CS_GetEntry (S, I);
/* Check for the sequence */
if ((E->OPC == OP65_LDX || E->OPC == OP65_TAX) &&
if ((E->OPC == OP65_LDX) &&
CS_GetEntries (S, L, I+1, 2) &&
L[0]->OPC == OP65_TXA &&
!CE_HasLabel (L[0]) &&
@ -1072,12 +1072,18 @@ static unsigned OptTest1 (CodeSeg* S)
* ora xxx
* beq/bne ...
*
* if X is zero, the sequence may be changed
* if X is zero, the sequence may be changed to
*
* cmp #$00
* beq/bne ...
*
* which may be optimized further by another step.
*
* If A is zero, the sequence may be changed to
*
* txa
* beq/bne ...
*
*/
{
unsigned Changes = 0;
@ -1097,7 +1103,6 @@ static unsigned OptTest1 (CodeSeg* S)
/* Check if it's the sequence we're searching for */
if (L[0]->OPC == OP65_STX &&
L[0]->RI->In.RegX == 0 &&
CS_GetEntries (S, L+1, I+1, 2) &&
!CE_HasLabel (L[1]) &&
L[1]->OPC == OP65_ORA &&
@ -1105,16 +1110,34 @@ static unsigned OptTest1 (CodeSeg* S)
!CE_HasLabel (L[2]) &&
(L[2]->Info & OF_ZBRA) != 0) {
/* Insert the compare */
CodeEntry* N = NewCodeEntry (OP65_CMP, AM65_IMM, "$00", 0, L[0]->LI);
CS_InsertEntry (S, N, I+2);
/* Check if X is zero */
if (L[0]->RI->In.RegX == 0) {
/* Remove the two other insns */
CS_DelEntry (S, I+1);
CS_DelEntry (S, I);
/* Insert the compare */
CodeEntry* N = NewCodeEntry (OP65_CMP, AM65_IMM, "$00", 0, L[0]->LI);
CS_InsertEntry (S, N, I+2);
/* We had changes */
++Changes;
/* Remove the two other insns */
CS_DelEntry (S, I+1);
CS_DelEntry (S, I);
/* We had changes */
++Changes;
/* Check if A is zero */
} else if (L[1]->RI->In.RegA == 0) {
/* Insert the txa */
CodeEntry* N = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, L[1]->LI);
CS_InsertEntry (S, N, I+2);
/* Remove the two other insns */
CS_DelEntry (S, I+1);
CS_DelEntry (S, I);
/* We had changes */
++Changes;
}
}
/* Next entry */
@ -1131,10 +1154,6 @@ static unsigned OptTest1 (CodeSeg* S)
/*****************************************************************************/
/* nega optimizations */
/*****************************************************************************/
@ -1967,8 +1986,9 @@ static OptFunc OptFuncs [] = {
OptEntry (OptUnusedLoads, optMain),
OptEntry (OptDuplicateLoads, optMain),
OptEntry (OptStoreLoad, optMain),
OptEntry (OptTransfers, optMain),
/* Optimize branch distance */
OptEntry (OptBranchDist, optMain),
OptEntry (OptBranchDist, optPost),
};

View File

@ -44,18 +44,6 @@
/*****************************************************************************/
/* Macros */
/*****************************************************************************/
/* Macro to increment and decrement register contents if they're valid */
#define INC(reg,val) if ((reg) >= 0) (reg) = ((reg) + val) & 0xFF
#define DEC(reg,val) if ((reg) >= 0) (reg) = ((reg) - val) & 0xFF
/*****************************************************************************/
/* Replace jumps to RTS by RTS */
/*****************************************************************************/
@ -611,20 +599,26 @@ unsigned OptUnusedLoads (CodeSeg* S)
CodeEntry* E = CS_GetEntry (S, I);
/* Check if it's a register load or transfer insn */
if ((E->Info & (OF_LOAD | OF_XFR)) != 0 &&
(N = CS_GetNextEntry (S, I)) != 0 &&
if ((E->Info & (OF_LOAD | OF_XFR | OF_REG_INCDEC)) != 0 &&
(N = CS_GetNextEntry (S, I)) != 0 &&
(N->Info & OF_FBRA) == 0) {
/* Check which sort of load or transfer it is */
unsigned R;
switch (E->OPC) {
case OP65_DEA:
case OP65_INA:
case OP65_LDA:
case OP65_TXA:
case OP65_TYA:
case OP65_LDA: R = REG_A; break;
case OP65_TAX:
case OP65_LDX: R = REG_X; break;
case OP65_TAY:
case OP65_LDY: R = REG_Y; break;
case OP65_TYA: R = REG_A; break;
case OP65_DEX:
case OP65_INX:
case OP65_LDX:
case OP65_TAX: R = REG_X; break;
case OP65_DEY:
case OP65_INY:
case OP65_LDY:
case OP65_TAY: R = REG_Y; break;
default: goto NextEntry; /* OOPS */
}
@ -858,6 +852,76 @@ unsigned OptStoreLoad (CodeSeg* S)
unsigned OptTransfers (CodeSeg* S)
/* Remove transfers from one register to another and back */
{
unsigned Changes = 0;
/* Walk over the entries */
unsigned I = 0;
while (I < CS_GetEntryCount (S)) {
CodeEntry* N;
CodeEntry* X;
CodeEntry* P;
/* 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.
*/
if ((E->Info & OF_XFR) != 0 &&
(N = CS_GetNextEntry (S, I)) != 0 &&
!CE_HasLabel (N) &&
(N->Info & OF_XFR) != 0) {
/* Check if it's a transfer and back */
if ((E->OPC == OP65_TAX && N->OPC == OP65_TXA && !RegXUsed (S, I+2)) ||
(E->OPC == OP65_TAY && N->OPC == OP65_TYA && !RegYUsed (S, I+2)) ||
(E->OPC == OP65_TXA && N->OPC == OP65_TAX && !RegAUsed (S, I+2)) ||
(E->OPC == OP65_TYA && N->OPC == OP65_TAY && !RegAUsed (S, I+1))) {
/* If the next insn is a conditional branch, check if the insn
* preceeding the first xfr will set the flags right, otherwise we
* may not remove the sequence.
*/
if ((X = CS_GetNextEntry (S, I+1)) == 0) {
goto NextEntry;
}
if ((X->Info & OF_FBRA) != 0) {
if (I == 0) {
/* No preceeding entry */
goto NextEntry;
}
P = CS_GetEntry (S, I-1);
if ((P->Info & OF_SETF) == 0) {
/* Does not set the flags */
goto NextEntry;
}
}
/* Remove both transfers */
CS_DelEntry (S, I+1);
CS_DelEntry (S, I);
/* Remember, we had changes */
++Changes;
}
}
NextEntry:
/* Next entry */
++I;
}
/* Return the number of changes made */
return Changes;
}
/*****************************************************************************/
/* Optimize branch types */
/*****************************************************************************/

View File

@ -95,6 +95,9 @@ unsigned OptDuplicateLoads (CodeSeg* S);
unsigned OptStoreLoad (CodeSeg* S);
/* Remove a store followed by a load from the same location. */
unsigned OptTransfers (CodeSeg* S);
/* Remove transfers from one register to another and back */
unsigned OptBranchDist (CodeSeg* S);
/* Change branches for the distance needed. */

View File

@ -57,141 +57,27 @@
/* Opcode description table */
const OPCDesc OPCTable[OPCODE_COUNT] = {
/* Opcodes for the virtual stack machine */
{ OPC_CALL, /* opcode */
"call", /* mnemonic */
1, /* size */
REG_NONE, /* use */
REG_NONE, /* chg */
OF_CPU_VM | OF_CALL /* flags */
},
{ OPC_ENTER, /* opcode */
"enter", /* mnemonic */
1, /* size */
REG_Y, /* use */
REG_AXY, /* chg */
OF_CPU_VM /* flags */
},
{ OPC_JMP, /* opcode */
"jump", /* mnemonic */
1, /* size */
REG_NONE, /* use */
REG_NONE, /* chg */
OF_CPU_VM | OF_UBRA /* flags */
},
{ OPC_LDA, /* opcode */
"lda", /* mnemonic */
1, /* size */
REG_NONE, /* use */
REG_A, /* chg */
OF_CPU_VM | OF_LOAD /* flags */
},
{ OPC_LDAX, /* opcode */
"ldax", /* mnemonic */
1, /* size */
REG_NONE, /* use */
REG_AX, /* chg */
OF_CPU_VM | OF_LOAD /* flags */
},
{ OPC_LDEAX, /* opcode */
"ldeax", /* mnemonic */
1, /* size */
REG_NONE, /* use */
REG_EAX, /* chg */
OF_CPU_VM | OF_LOAD /* flags */
},
{ OPC_LEA, /* opcode */
"lea", /* mnemonic */
1, /* size */
REG_NONE, /* use */
REG_AX, /* chg */
OF_CPU_VM /* flags */
},
{ OPC_LEAVE, /* opcode */
"leave", /* mnemonic */
1, /* size */
REG_NONE, /* use */
REG_NONE, /* chg */
OF_CPU_VM /* flags */
},
{ OPC_PHA, /* opcode */
"pha", /* mnemonic */
1, /* size */
REG_A, /* use */
REG_NONE, /* chg */
OF_CPU_VM /* flags */
},
{ OPC_PHAX, /* opcode */
"phax", /* mnemonic */
1, /* size */
REG_AX, /* use */
REG_NONE, /* chg */
OF_CPU_VM /* flags */
},
{ OPC_PHEAX, /* opcode */
"pheax", /* mnemonic */
1, /* size */
REG_EAX, /* use */
REG_NONE, /* chg */
OF_CPU_VM /* flags */
},
{ OPC_RET, /* opcode */
"ret", /* mnemonic */
1, /* size */
REG_NONE, /* use */
REG_NONE, /* chg */
OF_CPU_VM | OF_RET /* flags */
},
{ OPC_SPACE, /* opcode */
"space", /* mnemonic */
1, /* size */
REG_NONE, /* use */
REG_NONE, /* chg */
OF_CPU_VM /* flags */
},
{ OPC_STA, /* opcode */
"sta", /* mnemonic */
1, /* size */
REG_A, /* use */
REG_NONE, /* chg */
OF_CPU_VM /* flags */
},
{ OPC_STAX, /* opcode */
"stax", /* mnemonic */
1, /* size */
REG_AX, /* use */
REG_NONE, /* chg */
OF_CPU_VM /* flags */
},
{ OPC_STEAX, /* opcode */
"steax", /* mnemonic */
1, /* size */
REG_EAX, /* use */
REG_NONE, /* chg */
OF_CPU_VM /* flags */
},
/* 65XX opcodes */
{ OP65_ADC, /* opcode */
"adc", /* mnemonic */
0, /* size */
REG_A, /* use */
REG_A, /* chg */
OF_NONE /* flags */
OF_SETF /* flags */
},
{ OP65_AND, /* opcode */
"and", /* mnemonic */
0, /* size */
REG_A, /* use */
REG_A, /* chg */
OF_NONE /* flags */
OF_SETF /* flags */
},
{ OP65_ASL, /* opcode */
"asl", /* mnemonic */
0, /* size */
REG_A, /* use */
REG_A, /* chg */
OF_NONE /* flags */
OF_SETF /* flags */
},
{ OP65_BCC, /* opcode */
"bcc", /* mnemonic */
@ -219,7 +105,7 @@ const OPCDesc OPCTable[OPCODE_COUNT] = {
0, /* size */
REG_A, /* use */
REG_NONE, /* chg */
OF_NONE /* flags */
OF_SETF /* flags */
},
{ OP65_BMI, /* opcode */
"bmi", /* mnemonic */
@ -303,84 +189,84 @@ const OPCDesc OPCTable[OPCODE_COUNT] = {
0, /* size */
REG_A, /* use */
REG_NONE, /* chg */
OF_NONE /* flags */
OF_SETF /* flags */
},
{ OP65_CPX, /* opcode */
"cpx", /* mnemonic */
0, /* size */
REG_X, /* use */
REG_NONE, /* chg */
OF_NONE /* flags */
OF_SETF /* flags */
},
{ OP65_CPY, /* opcode */
"cpy", /* mnemonic */
0, /* size */
REG_Y, /* use */
REG_NONE, /* chg */
OF_NONE /* flags */
OF_SETF /* flags */
},
{ OP65_DEA, /* opcode */
"dea", /* mnemonic */
1, /* size */
REG_A, /* use */
REG_A, /* chg */
OF_NONE /* flags */
OF_REG_INCDEC | OF_SETF /* flags */
},
{ OP65_DEC, /* opcode */
"dec", /* mnemonic */
0, /* size */
REG_NONE, /* use */
REG_NONE, /* chg */
OF_NONE /* flags */
OF_SETF /* flags */
},
{ OP65_DEX, /* opcode */
"dex", /* mnemonic */
1, /* size */
REG_X, /* use */
REG_X, /* chg */
OF_NONE /* flags */
OF_REG_INCDEC | OF_SETF /* flags */
},
{ OP65_DEY, /* opcode */
"dey", /* mnemonic */
1, /* size */
REG_Y, /* use */
REG_Y, /* chg */
OF_NONE /* flags */
OF_REG_INCDEC | OF_SETF /* flags */
},
{ OP65_EOR, /* opcode */
"eor", /* mnemonic */
0, /* size */
REG_A, /* use */
REG_A, /* chg */
OF_NONE /* flags */
OF_SETF /* flags */
},
{ OP65_INA, /* opcode */
"ina", /* mnemonic */
1, /* size */
REG_A, /* use */
REG_A, /* chg */
OF_NONE /* flags */
OF_REG_INCDEC | OF_SETF /* flags */
},
{ OP65_INC, /* opcode */
"inc", /* mnemonic */
0, /* size */
REG_NONE, /* use */
REG_NONE, /* chg */
OF_NONE /* flags */
OF_SETF /* flags */
},
{ OP65_INX, /* opcode */
"inx", /* mnemonic */
1, /* size */
REG_X, /* use */
REG_X, /* chg */
OF_NONE /* flags */
OF_REG_INCDEC | OF_SETF /* flags */
},
{ OP65_INY, /* opcode */
"iny", /* mnemonic */
1, /* size */
REG_Y, /* use */
REG_Y, /* chg */
OF_NONE /* flags */
OF_REG_INCDEC | OF_SETF /* flags */
},
{ OP65_JCC, /* opcode */
"jcc", /* mnemonic */
@ -457,28 +343,28 @@ const OPCDesc OPCTable[OPCODE_COUNT] = {
0, /* size */
REG_NONE, /* use */
REG_A, /* chg */
OF_LOAD /* flags */
OF_LOAD | OF_SETF /* flags */
},
{ OP65_LDX, /* opcode */
"ldx", /* mnemonic */
0, /* size */
REG_NONE, /* use */
REG_X, /* chg */
OF_LOAD /* flags */
OF_LOAD | OF_SETF /* flags */
},
{ OP65_LDY, /* opcode */
"ldy", /* mnemonic */
0, /* size */
REG_NONE, /* use */
REG_Y, /* chg */
OF_LOAD /* flags */
OF_LOAD | OF_SETF /* flags */
},
{ OP65_LSR, /* opcode */
"lsr", /* mnemonic */
0, /* size */
REG_A, /* use */
REG_A, /* chg */
OF_NONE /* flags */
OF_SETF /* flags */
},
{ OP65_NOP, /* opcode */
"nop", /* mnemonic */
@ -492,7 +378,7 @@ const OPCDesc OPCTable[OPCODE_COUNT] = {
0, /* size */
REG_A, /* use */
REG_A, /* chg */
OF_NONE /* flags */
OF_SETF /* flags */
},
{ OP65_PHA, /* opcode */
"pha", /* mnemonic */
@ -527,7 +413,7 @@ const OPCDesc OPCTable[OPCODE_COUNT] = {
1, /* size */
REG_NONE, /* use */
REG_A, /* chg */
OF_NONE /* flags */
OF_SETF /* flags */
},
{ OP65_PLP, /* opcode */
"plp", /* mnemonic */
@ -541,49 +427,49 @@ const OPCDesc OPCTable[OPCODE_COUNT] = {
1, /* size */
REG_NONE, /* use */
REG_X, /* chg */
OF_NONE /* flags */
OF_SETF /* flags */
},
{ OP65_PLY, /* opcode */
"ply", /* mnemonic */
1, /* size */
REG_NONE, /* use */
REG_Y, /* chg */
OF_NONE /* flags */
OF_SETF /* flags */
},
{ OP65_ROL, /* opcode */
"rol", /* mnemonic */
0, /* size */
REG_A, /* use */
REG_A, /* chg */
OF_NONE /* flags */
OF_SETF /* flags */
},
{ OP65_ROR, /* opcode */
"ror", /* mnemonic */
0, /* size */
REG_A, /* use */
REG_A, /* chg */
OF_NONE /* flags */
OF_SETF /* flags */
},
{ OP65_RTI, /* opcode */
"rti", /* mnemonic */
1, /* size */
REG_NONE, /* use */
REG_NONE, /* chg */
OF_RET /* flags */
OF_RET /* flags */
},
{ OP65_RTS, /* opcode */
"rts", /* mnemonic */
1, /* size */
REG_NONE, /* use */
REG_NONE, /* chg */
OF_RET /* flags */
OF_RET /* flags */
},
{ OP65_SBC, /* opcode */
"sbc", /* mnemonic */
0, /* size */
REG_A, /* use */
REG_A, /* chg */
OF_NONE /* flags */
OF_SETF /* flags */
},
{ OP65_SEC, /* opcode */
"sec", /* mnemonic */
@ -632,42 +518,42 @@ const OPCDesc OPCTable[OPCODE_COUNT] = {
1, /* size */
REG_A, /* use */
REG_X, /* chg */
OF_XFR /* flags */
OF_XFR | OF_SETF /* flags */
},
{ OP65_TAY, /* opcode */
"tay", /* mnemonic */
1, /* size */
REG_A, /* use */
REG_Y, /* chg */
OF_XFR /* flags */
OF_XFR | OF_SETF /* flags */
},
{ OP65_TRB, /* opcode */
"trb", /* mnemonic */
0, /* size */
REG_A, /* use */
REG_NONE, /* chg */
OF_NONE /* flags */
OF_SETF /* flags */
},
{ OP65_TSB, /* opcode */
"tsb", /* mnemonic */
0, /* size */
REG_A, /* use */
REG_NONE, /* chg */
OF_NONE /* flags */
OF_SETF /* flags */
},
{ OP65_TSX, /* opcode */
"tsx", /* mnemonic */
1, /* size */
REG_NONE, /* use */
REG_X, /* chg */
OF_XFR /* flags */
OF_XFR | OF_SETF /* flags */
},
{ OP65_TXA, /* opcode */
"txa", /* mnemonic */
1, /* size */
REG_X, /* use */
REG_A, /* chg */
OF_XFR /* flags */
OF_XFR | OF_SETF /* flags */
},
{ OP65_TXS, /* opcode */
"txs", /* mnemonic */
@ -681,7 +567,7 @@ const OPCDesc OPCTable[OPCODE_COUNT] = {
1, /* size */
REG_Y, /* use */
REG_A, /* chg */
OF_XFR /* flags */
OF_XFR | OF_SETF /* flags */
},
};
@ -695,7 +581,7 @@ const OPCDesc OPCTable[OPCODE_COUNT] = {
static int FindCmp (const void* Key, const void* Desc)
/* Compare function for FindOpcode */
{
{
return strcmp (Key, ((OPCDesc*)Desc)->Mnemo);
}

View File

@ -52,24 +52,6 @@
/* Definitions for the possible opcodes */
typedef enum {
/* Opcodes for the virtual stack machine */
OPC_CALL,
OPC_ENTER,
OPC_JMP,
OPC_LDA,
OPC_LDAX,
OPC_LDEAX,
OPC_LEA,
OPC_LEAVE,
OPC_PHA,
OPC_PHAX,
OPC_PHEAX,
OPC_RET,
OPC_SPACE,
OPC_STA,
OPC_STAX,
OPC_STEAX,
/* 65XX opcodes */
OP65_ADC,
OP65_AND,
@ -193,19 +175,18 @@ typedef enum {
/* Opcode info */
#define OF_NONE 0x0000U /* No additional information */
#define OF_CPU_6502 0x0000U /* 6502 opcode */
#define OF_CPU_VM 0x0001U /* Virtual machine opcode */
#define OF_MASK_CPU 0x0001U /* Mask for the cpu field */
#define OF_UBRA 0x0010U /* Unconditional branch */
#define OF_CBRA 0x0020U /* Conditional branch */
#define OF_ZBRA 0x0040U /* Branch on zero flag condition */
#define OF_FBRA 0x0080U /* Branch on cond set by a load */
#define OF_LBRA 0x0100U /* Jump/branch is long */
#define OF_RET 0x0200U /* Return from function */
#define OF_LOAD 0x0400U /* Register load */
#define OF_STORE 0x0800U /* Register store */
#define OF_XFR 0x1000U /* Transfer instruction */
#define OF_CALL 0x2000U /* A subroutine call */
#define OF_UBRA 0x0001U /* Unconditional branch */
#define OF_CBRA 0x0002U /* Conditional branch */
#define OF_ZBRA 0x0004U /* Branch on zero flag condition */
#define OF_FBRA 0x0008U /* Branch on cond set by a load */
#define OF_LBRA 0x0010U /* Jump/branch is long */
#define OF_RET 0x0020U /* Return from function */
#define OF_LOAD 0x0040U /* Register load */
#define OF_STORE 0x0080U /* Register store */
#define OF_XFR 0x0100U /* Transfer instruction */
#define OF_CALL 0x0200U /* A subroutine call */
#define OF_REG_INCDEC 0x0400U /* A register increment or decrement */
#define OF_SETF 0x0800U /* Insn will set all load flags (not carry) */
/* Combined infos */
#define OF_BRA (OF_UBRA | OF_CBRA) /* Operation is a jump/branch */