Another optimization step
git-svn-id: svn://svn.cc65.org/cc65/trunk@1603 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -1131,18 +1131,81 @@ void g_tosint (unsigned flags)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void g_reglong (unsigned flags)
|
void g_regint (unsigned Flags)
|
||||||
/* Make sure, the value in the primary register a long. Convert if necessary */
|
/* Make sure, the value in the primary register an int. Convert if necessary */
|
||||||
{
|
{
|
||||||
switch (flags & CF_TYPE) {
|
unsigned L;
|
||||||
|
|
||||||
|
switch (Flags & CF_TYPE) {
|
||||||
|
|
||||||
case CF_CHAR:
|
case CF_CHAR:
|
||||||
|
if (Flags & CF_FORCECHAR) {
|
||||||
|
/* Conversion is from char */
|
||||||
|
if (Flags & CF_UNSIGNED) {
|
||||||
|
AddCodeLine ("ldx #$00");
|
||||||
|
} else {
|
||||||
|
L = GetLocalLabel();
|
||||||
|
AddCodeLine ("ldx #$00");
|
||||||
|
AddCodeLine ("cmp #$80");
|
||||||
|
AddCodeLine ("bcc %s", LocalLabelName (L));
|
||||||
|
AddCodeLine ("dex");
|
||||||
|
g_defcodelabel (L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
case CF_INT:
|
case CF_INT:
|
||||||
if (flags & CF_UNSIGNED) {
|
case CF_LONG:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
typeerror (Flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void g_reglong (unsigned Flags)
|
||||||
|
/* Make sure, the value in the primary register a long. Convert if necessary */
|
||||||
|
{
|
||||||
|
unsigned L;
|
||||||
|
|
||||||
|
switch (Flags & CF_TYPE) {
|
||||||
|
|
||||||
|
case CF_CHAR:
|
||||||
|
if (Flags & CF_FORCECHAR) {
|
||||||
|
/* Conversion is from char */
|
||||||
|
if (Flags & CF_UNSIGNED) {
|
||||||
|
if (CodeSizeFactor >= 200) {
|
||||||
|
AddCodeLine ("ldx #$00");
|
||||||
|
AddCodeLine ("stx sreg");
|
||||||
|
AddCodeLine ("stx sreg+1");
|
||||||
|
} else {
|
||||||
|
AddCodeLine ("jsr aulong");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (CodeSizeFactor >= 366) {
|
||||||
|
L = GetLocalLabel();
|
||||||
|
AddCodeLine ("ldx #$00");
|
||||||
|
AddCodeLine ("cmp #$80");
|
||||||
|
AddCodeLine ("bcc %s", LocalLabelName (L));
|
||||||
|
AddCodeLine ("dex");
|
||||||
|
g_defcodelabel (L);
|
||||||
|
AddCodeLine ("stx sreg");
|
||||||
|
AddCodeLine ("stx sreg+1");
|
||||||
|
} else {
|
||||||
|
AddCodeLine ("jsr along");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
|
case CF_INT:
|
||||||
|
if (Flags & CF_UNSIGNED) {
|
||||||
if (CodeSizeFactor >= 200) {
|
if (CodeSizeFactor >= 200) {
|
||||||
ldyconst (0);
|
ldyconst (0);
|
||||||
AddCodeLine ("sty sreg");
|
AddCodeLine ("sty sreg");
|
||||||
AddCodeLine ("sty sreg+1");
|
AddCodeLine ("sty sreg+1");
|
||||||
} else {
|
} else {
|
||||||
AddCodeLine ("jsr axulong");
|
AddCodeLine ("jsr axulong");
|
||||||
}
|
}
|
||||||
@@ -1155,7 +1218,7 @@ void g_reglong (unsigned flags)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
typeerror (flags);
|
typeerror (Flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1223,9 +1286,14 @@ unsigned g_typecast (unsigned lhs, unsigned rhs)
|
|||||||
rtype = rhs & CF_TYPE;
|
rtype = rhs & CF_TYPE;
|
||||||
|
|
||||||
/* Check if a conversion is needed */
|
/* Check if a conversion is needed */
|
||||||
if (ltype == CF_LONG && rtype != CF_LONG && (rhs & CF_CONST) == 0) {
|
if ((rhs & CF_CONST) == 0) {
|
||||||
/* We must promote the primary register to long */
|
if (ltype == CF_LONG && rtype != CF_LONG) {
|
||||||
g_reglong (rhs);
|
/* We must promote the primary register to long */
|
||||||
|
g_reglong (rhs);
|
||||||
|
} else if (ltype == CF_INT && rtype != CF_INT) {
|
||||||
|
/* We must promote the primary register to int */
|
||||||
|
g_regint (rhs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do not need any other action. If the left type is int, and the primary
|
/* Do not need any other action. If the left type is int, and the primary
|
||||||
|
|||||||
@@ -186,7 +186,10 @@ void g_toslong (unsigned flags);
|
|||||||
void g_tosint (unsigned flags);
|
void g_tosint (unsigned flags);
|
||||||
/* Make sure, the value on TOS is an int. Convert if necessary */
|
/* Make sure, the value on TOS is an int. Convert if necessary */
|
||||||
|
|
||||||
void g_reglong (unsigned flags);
|
void g_regint (unsigned Flags);
|
||||||
|
/* Make sure, the value in the primary register an int. Convert if necessary */
|
||||||
|
|
||||||
|
void g_reglong (unsigned Flags);
|
||||||
/* Make sure, the value in the primary register a long. Convert if necessary */
|
/* Make sure, the value in the primary register a long. Convert if necessary */
|
||||||
|
|
||||||
unsigned g_typeadjust (unsigned lhs, unsigned rhs);
|
unsigned g_typeadjust (unsigned lhs, unsigned rhs);
|
||||||
|
|||||||
@@ -333,6 +333,70 @@ static unsigned OptShift3 (CodeSeg* S)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Optimize loads */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static 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.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
unsigned I;
|
||||||
|
unsigned Changes = 0;
|
||||||
|
|
||||||
|
/* Generate register info */
|
||||||
|
CS_GenRegInfo (S);
|
||||||
|
|
||||||
|
/* Walk over the entries */
|
||||||
|
I = 0;
|
||||||
|
while (I < CS_GetEntryCount (S)) {
|
||||||
|
|
||||||
|
CodeEntry* E;
|
||||||
|
|
||||||
|
/* Get next entry */
|
||||||
|
E = CS_GetEntry (S, I);
|
||||||
|
|
||||||
|
/* Check for the sequence */
|
||||||
|
if (CE_IsCallTo (E, "ldaxysp") &&
|
||||||
|
RegValIsKnown (E->RI->In.RegY) &&
|
||||||
|
!RegXUsed (S, I+1)) {
|
||||||
|
|
||||||
|
CodeEntry* X;
|
||||||
|
|
||||||
|
/* Reload the Y register */
|
||||||
|
const char* Arg = MakeHexArg (E->RI->In.RegY - 1);
|
||||||
|
X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI);
|
||||||
|
CS_InsertEntry (S, X, I+1);
|
||||||
|
|
||||||
|
/* Load from stack */
|
||||||
|
X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, E->LI);
|
||||||
|
CS_InsertEntry (S, X, I+2);
|
||||||
|
|
||||||
|
/* Now remove the call to the subroutine */
|
||||||
|
CS_DelEntry (S, I);
|
||||||
|
|
||||||
|
/* Remember, we had changes */
|
||||||
|
++Changes;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Next entry */
|
||||||
|
++I;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the register info */
|
||||||
|
CS_FreeRegInfo (S);
|
||||||
|
|
||||||
|
/* Return the number of changes made */
|
||||||
|
return Changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Optimize stores through pointers */
|
/* Optimize stores through pointers */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -1355,6 +1419,7 @@ static OptFunc DOptDecouple = { OptDecouple, "OptDecouple", 100, 0,
|
|||||||
static OptFunc DOptDupLoads = { OptDupLoads, "OptDupLoads", 0, 0, 0, 0, 0, 0 };
|
static OptFunc DOptDupLoads = { OptDupLoads, "OptDupLoads", 0, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptJumpCascades = { OptJumpCascades, "OptJumpCascades", 100, 0, 0, 0, 0, 0 };
|
static OptFunc DOptJumpCascades = { OptJumpCascades, "OptJumpCascades", 100, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptJumpTarget = { OptJumpTarget, "OptJumpTarget", 100, 0, 0, 0, 0, 0 };
|
static OptFunc DOptJumpTarget = { OptJumpTarget, "OptJumpTarget", 100, 0, 0, 0, 0, 0 };
|
||||||
|
static OptFunc DOptLoad1 = { OptLoad1, "OptLoad1", 100, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptRTS = { OptRTS, "OptRTS", 100, 0, 0, 0, 0, 0 };
|
static OptFunc DOptRTS = { OptRTS, "OptRTS", 100, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptRTSJumps1 = { OptRTSJumps1, "OptRTSJumps1", 100, 0, 0, 0, 0, 0 };
|
static OptFunc DOptRTSJumps1 = { OptRTSJumps1, "OptRTSJumps1", 100, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptRTSJumps2 = { OptRTSJumps2, "OptRTSJumps2", 100, 0, 0, 0, 0, 0 };
|
static OptFunc DOptRTSJumps2 = { OptRTSJumps2, "OptRTSJumps2", 100, 0, 0, 0, 0, 0 };
|
||||||
@@ -1415,6 +1480,7 @@ static OptFunc* OptFuncs[] = {
|
|||||||
&DOptDupLoads,
|
&DOptDupLoads,
|
||||||
&DOptJumpCascades,
|
&DOptJumpCascades,
|
||||||
&DOptJumpTarget,
|
&DOptJumpTarget,
|
||||||
|
&DOptLoad1,
|
||||||
&DOptNegA1,
|
&DOptNegA1,
|
||||||
&DOptNegA2,
|
&DOptNegA2,
|
||||||
&DOptNegAX1,
|
&DOptNegAX1,
|
||||||
@@ -1629,7 +1695,7 @@ static void WriteOptStats (const char* Name)
|
|||||||
O->Name,
|
O->Name,
|
||||||
O->TotalRuns,
|
O->TotalRuns,
|
||||||
O->LastRuns,
|
O->LastRuns,
|
||||||
O->TotalChanges,
|
O->TotalChanges,
|
||||||
O->LastChanges);
|
O->LastChanges);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1759,6 +1825,7 @@ static unsigned RunOptGroup3 (CodeSeg* S)
|
|||||||
C += RunOptFunc (S, &DOptCmp6, 1);
|
C += RunOptFunc (S, &DOptCmp6, 1);
|
||||||
C += RunOptFunc (S, &DOptCmp7, 1);
|
C += RunOptFunc (S, &DOptCmp7, 1);
|
||||||
C += RunOptFunc (S, &DOptTest1, 1);
|
C += RunOptFunc (S, &DOptTest1, 1);
|
||||||
|
C += RunOptFunc (S, &DOptLoad1, 1);
|
||||||
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, &DOptDupLoads, 1);
|
||||||
|
|||||||
@@ -172,8 +172,8 @@ int TypeCast (ExprDesc* lval)
|
|||||||
/* Load the value into the primary */
|
/* Load the value into the primary */
|
||||||
exprhs (CF_NONE, k, lval);
|
exprhs (CF_NONE, k, lval);
|
||||||
|
|
||||||
/* Emit typecast code. ### CHARS */
|
/* Emit typecast code. */
|
||||||
g_typecast (TypeOf (OldType), TypeOf (NewType));
|
g_typecast (TypeOf (OldType), TypeOf (NewType) | CF_FORCECHAR);
|
||||||
|
|
||||||
/* Value is now in primary */
|
/* Value is now in primary */
|
||||||
lval->Flags = E_MEXPR;
|
lval->Flags = E_MEXPR;
|
||||||
@@ -190,7 +190,7 @@ int TypeCast (ExprDesc* lval)
|
|||||||
exprhs (CF_NONE, k, lval);
|
exprhs (CF_NONE, k, lval);
|
||||||
|
|
||||||
/* Emit typecast code */
|
/* Emit typecast code */
|
||||||
g_typecast (TypeOf (OldType), TypeOf (NewType));
|
g_typecast (TypeOf (OldType), TypeOf (NewType) | CF_FORCECHAR);
|
||||||
|
|
||||||
/* Value is now in primary */
|
/* Value is now in primary */
|
||||||
lval->Flags = E_MEXPR;
|
lval->Flags = E_MEXPR;
|
||||||
|
|||||||
Reference in New Issue
Block a user