From c2b03e02088d2d459ababaef366ae73a6ab8adf4 Mon Sep 17 00:00:00 2001 From: uz Date: Tue, 29 Sep 2009 18:46:25 +0000 Subject: [PATCH] New optimization step git-svn-id: svn://svn.cc65.org/cc65/trunk@4278 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/codeopt.c | 5 +- src/cc65/coptind.c | 126 +++++++++++++++++++++++++++++++++++---------- src/cc65/coptind.h | 6 +++ 3 files changed, 110 insertions(+), 27 deletions(-) diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index 20fb5b55d..2441df606 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -447,7 +447,7 @@ static unsigned OptShift4 (CodeSeg* S) CS_DelEntry (S, I); /* Remember, we had changes */ - ++Changes; + ++Changes; } NextEntry: @@ -1110,6 +1110,7 @@ static OptFunc DOptIndLoads2 = { OptIndLoads2, "OptIndLoads2", 0, 0, static OptFunc DOptJumpCascades = { OptJumpCascades, "OptJumpCascades", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptJumpTarget1 = { OptJumpTarget1, "OptJumpTarget1", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptJumpTarget2 = { OptJumpTarget2, "OptJumpTarget2", 100, 0, 0, 0, 0, 0 }; +static OptFunc DOptJumpTarget3 = { OptJumpTarget3, "OptJumpTarget3", 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 }; @@ -1198,6 +1199,7 @@ static OptFunc* OptFuncs[] = { &DOptJumpCascades, &DOptJumpTarget1, &DOptJumpTarget2, + &DOptJumpTarget3, &DOptLoad1, &DOptNegA1, &DOptNegA2, @@ -1568,6 +1570,7 @@ static unsigned RunOptGroup3 (CodeSeg* S) C += RunOptFunc (S, &DOptBoolTrans, 1); C += RunOptFunc (S, &DOptJumpTarget1, 1); C += RunOptFunc (S, &DOptJumpTarget2, 1); + C += RunOptFunc (S, &DOptJumpTarget3, 1); C += RunOptFunc (S, &DOptCondBranches1, 1); C += RunOptFunc (S, &DOptCondBranches2, 1); C += RunOptFunc (S, &DOptRTSJumps1, 1); diff --git a/src/cc65/coptind.c b/src/cc65/coptind.c index cf43d44b1..80d6c772c 100644 --- a/src/cc65/coptind.c +++ b/src/cc65/coptind.c @@ -183,8 +183,7 @@ static short ZPRegVal (unsigned short Use, const RegContents* RC) } - -#if 0 /* Currently unused */ + static short RegVal (unsigned short Use, const RegContents* RC) /* Return the contents of the given register */ { @@ -198,7 +197,6 @@ static short RegVal (unsigned short Use, const RegContents* RC) return ZPRegVal (Use, RC); } } -#endif @@ -750,6 +748,82 @@ NextEntry: +unsigned OptJumpTarget3 (CodeSeg* S) +/* Jumps to load instructions of a register, that do already have the matching + * register contents may skip the load instruction, since it's job is already + * done. + */ +{ + 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)) { + + unsigned J, K; + CodeEntry* N; + + /* New jump label */ + CodeLabel* LN = 0; + + /* Get next entry */ + CodeEntry* E = CS_GetEntry (S, I); + + /* Check if this is a load insn with a label */ + if ((E->Info & OF_LOAD) != 0 && + CE_IsConstImm (E) && + CE_HasLabel (E) && + (N = CS_GetNextEntry (S, I)) != 0) { + + /* Walk over all insn that jump here */ + for (J = 0; J < CE_GetLabelCount (E); ++J) { + + /* Get the label */ + CodeLabel* L = CE_GetLabel (E, J); + for (K = 0; K < CL_GetRefCount (L); ++K) { + + /* Get the entry that jumps here */ + CodeEntry* Jump = CL_GetRef (L, K); + + /* Get the register info from this insn */ + short Val = RegVal (E->Chg, &Jump->RI->Out2); + + /* Check if the outgoing value is the one thatr's loaded */ + if (Val == (unsigned char) E->Num) { + + /* Ok, skip the insn. First, generate a label */ + if (LN == 0) { + LN = CS_GenLabel (S, N); + } + + /* Change the jump target to point to this new label */ + CS_MoveLabelRef (S, Jump, LN); + + /* Remember that we had changes */ + ++Changes; + } + } + } + + } + + /* Next entry */ + ++I; + } + + /* Free register info */ + CS_FreeRegInfo (S); + + /* Return the number of changes made */ + return Changes; +} + + + /*****************************************************************************/ /* Optimize conditional branches */ /*****************************************************************************/ @@ -1076,7 +1150,7 @@ unsigned OptDupLoads (CodeSeg* S) break; case OP65_STA: - /* If we store into a known zero page location, and this + /* If we store into a known zero page location, and this * location does already contain the value to be stored, * remove the store. */ @@ -1129,7 +1203,7 @@ unsigned OptDupLoads (CodeSeg* S) * that in the A register, replace the store by a STA. The * optimizer will then remove the load instruction for Y * later. If replacement by A is not possible try a - * replacement by X, but check for invalid addressing modes + * replacement by X, but check for invalid addressing modes * in this case. */ } else if (RegValIsKnown (In->RegY)) { @@ -1182,39 +1256,39 @@ unsigned OptDupLoads (CodeSeg* S) !CE_UseLoadFlags (N)) { /* Value is identical and not followed by a branch */ Delete = 1; - } - break; + } + break; - case OP65_TYA: + case OP65_TYA: if (RegValIsKnown (In->RegY) && In->RegY == In->RegA && - (N = CS_GetNextEntry (S, I)) != 0 && + (N = CS_GetNextEntry (S, I)) != 0 && !CE_UseLoadFlags (N)) { - /* Value is identical and not followed by a branch */ - Delete = 1; - } - break; + /* Value is identical and not followed by a branch */ + Delete = 1; + } + break; - default: - break; + default: + break; - } + } - /* Delete the entry if requested */ - if (Delete) { + /* Delete the entry if requested */ + if (Delete) { - /* Register value is not used, remove the load */ - CS_DelEntry (S, I); + /* Register value is not used, remove the load */ + CS_DelEntry (S, I); - /* Remember, we had changes */ - ++Changes; + /* Remember, we had changes */ + ++Changes; - } else { + } else { - /* Next entry */ - ++I; + /* Next entry */ + ++I; - } + } } diff --git a/src/cc65/coptind.h b/src/cc65/coptind.h index 98d205489..0ea7cd1b9 100644 --- a/src/cc65/coptind.h +++ b/src/cc65/coptind.h @@ -89,6 +89,12 @@ unsigned OptJumpTarget2 (CodeSeg* S); * it's job is already done. */ +unsigned OptJumpTarget3 (CodeSeg* S); +/* Jumps to load instructions of a register, that do already have the matching + * register contents may skip the load instruction, since it's job is already + * done. + */ + unsigned OptCondBranches1 (CodeSeg* S); /* If an immidiate load of a register is followed by a conditional jump that * is never taken because the load of the register sets the flags in such a -- 2.39.5