1
0
mirror of https://github.com/cc65/cc65.git synced 2024-07-05 21:29:03 +00:00

More optimizations

git-svn-id: svn://svn.cc65.org/cc65/trunk@970 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2001-09-25 12:34:34 +00:00
parent 9b9508cbd8
commit 8d0dfb5b41
4 changed files with 163 additions and 21 deletions

View File

@ -170,7 +170,7 @@ void g_preamble (void)
AddTextLine ("\t.debuginfo\t%s", (DebugInfo != 0)? "on" : "off");
/* Import the stack pointer for direct auto variable access */
AddTextLine ("\t.importzp\tsp, sreg, regsave, regbank, tmp1, ptr1");
AddTextLine ("\t.importzp\tsp, sreg, regsave, regbank, tmp1, ptr1, ptr2");
/* Define long branch macros */
AddTextLine ("\t.macpack\tlongbranch");
@ -608,7 +608,7 @@ void g_getimmed (unsigned Flags, unsigned long Val, unsigned Offs)
if (B2 == B4) {
AddCodeLine ("stx sreg+1");
Done |= 0x08;
}
}
if ((Done & 0x04) == 0 && B1 != B3) {
AddCodeLine ("lda #$%02X", B3);
AddCodeLine ("sta sreg");
@ -1701,11 +1701,27 @@ void g_addeqlocal (unsigned flags, int offs, unsigned long val)
/* FALLTHROUGH */
case CF_INT:
if (flags & CF_CONST) {
g_getimmed (flags, val, 0);
}
ldyconst (offs);
AddCodeLine ("jsr addeqysp");
if (flags & CF_CONST) {
if (CodeSizeFactor >= 400) {
AddCodeLine ("clc");
AddCodeLine ("lda #$%02X", (int)(val & 0xFF));
AddCodeLine ("adc (sp),y");
AddCodeLine ("sta (sp),y");
AddCodeLine ("iny");
AddCodeLine ("lda #$%02X", (int) ((val >> 8) & 0xFF));
AddCodeLine ("adc (sp),y");
AddCodeLine ("sta (sp),y");
AddCodeLine ("tax");
AddCodeLine ("dey");
AddCodeLine ("lda (sp),y");
} else {
g_getimmed (flags, val, 0);
AddCodeLine ("jsr addeqysp");
}
} else {
AddCodeLine ("jsr addeqysp");
}
break;
case CF_LONG:

View File

@ -256,6 +256,20 @@ static void ReplaceCmp (CodeSeg* S, unsigned I, cmp_t Cond)
static int GetCmpRegVal (const CodeEntry* E)
/* Return the register value for an immediate compare */
{
switch (E->OPC) {
case OP65_CMP: return E->RI->In.RegA;
case OP65_CPX: return E->RI->In.RegX;
case OP65_CPY: return E->RI->In.RegY;
default: Internal ("Invalid opcode in GetCmpRegVal");
return 0; /* Not reached */
}
}
static int IsCmpToZero (const CodeEntry* E)
/* Check if the given instrcuction is a compare to zero instruction */
{
@ -937,6 +951,10 @@ static unsigned OptCmp2 (CodeSeg* S)
* lda/and/ora/eor ...
* cmp #$00
* jeq/jne
* or
* lda/and/ora/eor ...
* cmp #$00
* jsr boolxx
*
* and remove the cmp.
*/
@ -963,11 +981,13 @@ static unsigned OptCmp2 (CodeSeg* S)
E->OPC == OP65_PLA ||
E->OPC == OP65_SBC ||
E->OPC == OP65_TXA ||
E->OPC == OP65_TYA) &&
CS_GetEntries (S, L, I+1, 2) &&
IsCmpToZero (L[0]) &&
!CE_HasLabel (L[0]) &&
(L[1]->Info & OF_FBRA) != 0 &&
E->OPC == OP65_TYA) &&
CS_GetEntries (S, L, I+1, 2) &&
IsCmpToZero (L[0]) &&
!CE_HasLabel (L[0]) &&
((L[1]->Info & OF_FBRA) != 0 ||
(L[1]->OPC == OP65_JSR &&
FindBoolCmpCond (L[1]->Arg) != CMP_INV)) &&
!CE_HasLabel (L[1])) {
/* Remove the compare */
@ -985,7 +1005,7 @@ static unsigned OptCmp2 (CodeSeg* S)
/* Return the number of changes made */
return Changes;
}
}
@ -1128,7 +1148,7 @@ static unsigned OptCmp4 (CodeSeg* S)
++Changes;
}
/* Next entry */
/* Next entry */
++I;
}
@ -1171,7 +1191,7 @@ static unsigned OptCmp5 (CodeSeg* S)
* boolean value but only valid flags. Note: jeq jumps if
* the condition is not met, jne jumps if the condition is met.
* Invert the code if we jump on condition not met.
*/
*/
if (GetBranchCond (N->OPC) == BC_EQ) {
/* Jumps if condition false, invert condition */
Cond = CmpInvertTab [Cond];
@ -1245,6 +1265,110 @@ static unsigned OptCmp6 (CodeSeg* S)
static unsigned OptCmp7 (CodeSeg* S)
/* Check for register compares where the contents of the register and therefore
* the result of the compare is known.
*/
{
unsigned Changes = 0;
unsigned I;
/* Generate register info for this step */
CS_GenRegInfo (S);
/* Walk over the entries */
I = 0;
while (I < CS_GetEntryCount (S)) {
int RegVal;
/* Get next entry */
CodeEntry* E = CS_GetEntry (S, I);
/* Check for a compare against an immediate value */
if ((E->Info & OF_CMP) != 0 &&
(RegVal = GetCmpRegVal (E)) >= 0 &&
CE_KnownImm (E)) {
/* We are able to evaluate the compare at compile time. Check if
* one or more branches are ahead.
*/
unsigned JumpsChanged = 0;
CodeEntry* N;
while ((N = CS_GetNextEntry (S, I)) != 0 && /* Followed by something.. */
(N->Info & OF_CBRA) != 0 && /* ..that is a cond branch.. */
!CE_HasLabel (N)) { /* ..and has no label */
/* Evaluate the branch condition */
int Cond;
switch (GetBranchCond (N->OPC)) {
case BC_CC:
Cond = ((unsigned char)RegVal) < ((unsigned char)E->Num);
break;
case BC_CS:
Cond = ((unsigned char)RegVal) >= ((unsigned char)E->Num);
break;
case BC_EQ:
Cond = ((unsigned char)RegVal) == ((unsigned char)E->Num);
break;
case BC_MI:
Cond = ((signed char)RegVal) < ((signed char)E->Num);
break;
case BC_NE:
Cond = ((unsigned char)RegVal) != ((unsigned char)E->Num);
break;
case BC_PL:
Cond = ((signed char)RegVal) >= ((signed char)E->Num);
break;
case BC_VC:
case BC_VS:
}
/* If the condition is false, we may remove the jump. Otherwise
* the branch will always be taken, so we may replace it by a
* jump (and bail out).
*/
if (!Cond) {
CS_DelEntry (S, I+1);
} else {
CodeLabel* L = N->JumpTo;
CodeEntry* X = NewCodeEntry (OP65_JMP, AM65_BRA, L->Name, L, N->LI);
CS_InsertEntry (S, X, I+2);
CS_DelEntry (S, I+1);
}
/* Remember, we had changes */
++JumpsChanged;
++Changes;
}
/* If we have made changes above, we may also remove the compare */
if (JumpsChanged) {
CS_DelEntry (S, I);
}
}
/* Next entry */
++I;
}
/* Free register info */
CS_FreeRegInfo (S);
/* Return the number of changes made */
return Changes;
}
/*****************************************************************************/
/* Optimize tests */
/*****************************************************************************/
@ -1319,10 +1443,10 @@ static unsigned OptTest1 (CodeSeg* S)
/* Remove the two other insns */
CS_DelEntry (S, I+1);
CS_DelEntry (S, I);
CS_DelEntry (S, I);
/* We had changes */
++Changes;
/* We had changes */
++Changes;
}
}
@ -2576,6 +2700,7 @@ static OptFunc OptFuncs [] = {
OptEntry (OptCmp4, optMain),
OptEntry (OptCmp5, optMain),
OptEntry (OptCmp6, optMain),
OptEntry (OptCmp7, optMain),
/* Optimize tests */
OptEntry (OptTest1, optMain),
/* Remove unused loads */

View File

@ -189,21 +189,21 @@ const OPCDesc OPCTable[OPCODE_COUNT] = {
0, /* size */
REG_A, /* use */
REG_NONE, /* chg */
OF_SETF /* flags */
OF_SETF | OF_CMP /* flags */
},
{ OP65_CPX, /* opcode */
"cpx", /* mnemonic */
0, /* size */
REG_X, /* use */
REG_NONE, /* chg */
OF_SETF /* flags */
OF_SETF | OF_CMP /* flags */
},
{ OP65_CPY, /* opcode */
"cpy", /* mnemonic */
0, /* size */
REG_Y, /* use */
REG_NONE, /* chg */
OF_SETF /* flags */
OF_SETF | OF_CMP /* flags */
},
{ OP65_DEA, /* opcode */
"dea", /* mnemonic */
@ -581,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

@ -187,6 +187,7 @@ typedef enum {
#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) */
#define OF_CMP 0x1000U /* A compare A/X/Y instruction */
/* Combined infos */
#define OF_BRA (OF_UBRA | OF_CBRA) /* Operation is a jump/branch */