From ac61d6826c614036e5ecdb820fbd90d34cdb43c1 Mon Sep 17 00:00:00 2001 From: cuz Date: Sat, 23 Nov 2002 12:05:23 +0000 Subject: [PATCH] Another optimization step git-svn-id: svn://svn.cc65.org/cc65/trunk@1603 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/codegen.c | 86 ++++++++++++++++++++++++++++++++++++++++----- src/cc65/codegen.h | 5 ++- src/cc65/codeopt.c | 69 +++++++++++++++++++++++++++++++++++- src/cc65/typecast.c | 6 ++-- 4 files changed, 152 insertions(+), 14 deletions(-) diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index 40dcd46ab..c4a50b139 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -450,7 +450,7 @@ void g_leave (void) { /* How many bytes of locals do we have to drop? */ int k = -oursp; - + /* If we didn't have a variable argument list, don't call leave */ if (funcargs >= 0) { @@ -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 an int. Convert if necessary */ +{ + unsigned L; + + switch (Flags & CF_TYPE) { + + 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_LONG: + break; + + default: + typeerror (Flags); + } +} + + + +void g_reglong (unsigned Flags) /* Make sure, the value in the primary register a long. Convert if necessary */ { - switch (flags & CF_TYPE) { + 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 (Flags & CF_UNSIGNED) { if (CodeSizeFactor >= 200) { ldyconst (0); AddCodeLine ("sty sreg"); - AddCodeLine ("sty sreg+1"); + AddCodeLine ("sty sreg+1"); } else { AddCodeLine ("jsr axulong"); } @@ -1155,7 +1218,7 @@ void g_reglong (unsigned flags) break; default: - typeerror (flags); + typeerror (Flags); } } @@ -1223,9 +1286,14 @@ unsigned g_typecast (unsigned lhs, unsigned rhs) rtype = rhs & CF_TYPE; /* Check if a conversion is needed */ - if (ltype == CF_LONG && rtype != CF_LONG && (rhs & CF_CONST) == 0) { - /* We must promote the primary register to long */ - g_reglong (rhs); + if ((rhs & CF_CONST) == 0) { + if (ltype == CF_LONG && rtype != CF_LONG) { + /* 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 diff --git a/src/cc65/codegen.h b/src/cc65/codegen.h index 37f5febb7..68e15b189 100644 --- a/src/cc65/codegen.h +++ b/src/cc65/codegen.h @@ -186,7 +186,10 @@ void g_toslong (unsigned flags); void g_tosint (unsigned flags); /* 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 */ unsigned g_typeadjust (unsigned lhs, unsigned rhs); diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index 01bba7b42..f9fcd9428 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -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 */ /*****************************************************************************/ @@ -1355,6 +1419,7 @@ static OptFunc DOptDecouple = { OptDecouple, "OptDecouple", 100, 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 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 DOptRTSJumps1 = { OptRTSJumps1, "OptRTSJumps1", 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, &DOptJumpCascades, &DOptJumpTarget, + &DOptLoad1, &DOptNegA1, &DOptNegA2, &DOptNegAX1, @@ -1629,7 +1695,7 @@ static void WriteOptStats (const char* Name) O->Name, O->TotalRuns, O->LastRuns, - O->TotalChanges, + O->TotalChanges, O->LastChanges); } @@ -1759,6 +1825,7 @@ static unsigned RunOptGroup3 (CodeSeg* S) C += RunOptFunc (S, &DOptCmp6, 1); C += RunOptFunc (S, &DOptCmp7, 1); C += RunOptFunc (S, &DOptTest1, 1); + C += RunOptFunc (S, &DOptLoad1, 1); C += RunOptFunc (S, &DOptUnusedLoads, 1); C += RunOptFunc (S, &DOptUnusedStores, 1); C += RunOptFunc (S, &DOptDupLoads, 1); diff --git a/src/cc65/typecast.c b/src/cc65/typecast.c index bd9641761..406680a77 100644 --- a/src/cc65/typecast.c +++ b/src/cc65/typecast.c @@ -172,8 +172,8 @@ int TypeCast (ExprDesc* lval) /* Load the value into the primary */ exprhs (CF_NONE, k, lval); - /* Emit typecast code. ### CHARS */ - g_typecast (TypeOf (OldType), TypeOf (NewType)); + /* Emit typecast code. */ + g_typecast (TypeOf (OldType), TypeOf (NewType) | CF_FORCECHAR); /* Value is now in primary */ lval->Flags = E_MEXPR; @@ -190,7 +190,7 @@ int TypeCast (ExprDesc* lval) exprhs (CF_NONE, k, lval); /* Emit typecast code */ - g_typecast (TypeOf (OldType), TypeOf (NewType)); + g_typecast (TypeOf (OldType), TypeOf (NewType) | CF_FORCECHAR); /* Value is now in primary */ lval->Flags = E_MEXPR; -- 2.39.5