From 15c420fd392ea8c3b1ebdcf3d2bc759c25ca3cda Mon Sep 17 00:00:00 2001 From: uz Date: Sat, 15 Aug 2009 15:58:21 +0000 Subject: [PATCH] Some branch improvements. git-svn-id: svn://svn.cc65.org/cc65/trunk@4019 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/codeopt.c | 13 +++++--- src/cc65/coptind.c | 81 ++++++++++++++++++++++++++++++++++++++++++++-- src/cc65/coptind.h | 7 +++- 3 files changed, 93 insertions(+), 8 deletions(-) diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index 95f6f2f30..254f30e23 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -1014,7 +1014,8 @@ static OptFunc DOptDeadJumps = { OptDeadJumps, "OptDeadJumps", 100, 0, static OptFunc DOptDecouple = { OptDecouple, "OptDecouple", 100, 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 DOptJumpTarget = { OptJumpTarget, "OptJumpTarget", 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 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 }; @@ -1093,7 +1094,8 @@ static OptFunc* OptFuncs[] = { &DOptDecouple, &DOptDupLoads, &DOptJumpCascades, - &DOptJumpTarget, + &DOptJumpTarget1, + &DOptJumpTarget2, &DOptLoad1, &DOptNegA1, &DOptNegA2, @@ -1453,7 +1455,8 @@ static unsigned RunOptGroup3 (CodeSeg* S) C += RunOptFunc (S, &DOptDeadJumps, 1); C += RunOptFunc (S, &DOptRTS, 1); C += RunOptFunc (S, &DOptDeadCode, 1); - C += RunOptFunc (S, &DOptJumpTarget, 1); + C += RunOptFunc (S, &DOptJumpTarget1, 1); + C += RunOptFunc (S, &DOptJumpTarget2, 1); C += RunOptFunc (S, &DOptCondBranches, 1); C += RunOptFunc (S, &DOptRTSJumps1, 1); C += RunOptFunc (S, &DOptBoolTrans, 1); @@ -1549,7 +1552,7 @@ static unsigned RunOptGroup6 (CodeSeg* S) * may have opened new oportunities. */ Changes += RunOptFunc (S, &DOptUnusedLoads, 1); - Changes += RunOptFunc (S, &DOptJumpTarget, 5); + Changes += RunOptFunc (S, &DOptJumpTarget1, 5); Changes += RunOptFunc (S, &DOptStore5, 1); } @@ -1560,7 +1563,7 @@ static unsigned RunOptGroup6 (CodeSeg* S) * may have opened new oportunities. */ Changes += RunOptFunc (S, &DOptUnusedLoads, 1); - Changes += RunOptFunc (S, &DOptJumpTarget, 5); + Changes += RunOptFunc (S, &DOptJumpTarget1, 5); Changes += RunOptFunc (S, &DOptStore5, 1); } diff --git a/src/cc65/coptind.c b/src/cc65/coptind.c index c1bbf1ea6..2ca307e37 100644 --- a/src/cc65/coptind.c +++ b/src/cc65/coptind.c @@ -544,7 +544,7 @@ unsigned OptRTS (CodeSeg* S) -unsigned OptJumpTarget (CodeSeg* S) +unsigned OptJumpTarget1 (CodeSeg* S) /* If the instruction preceeding an unconditional branch is the same as the * instruction preceeding the jump target, the jump target may be moved * one entry back. This is a size optimization, since the instruction before @@ -623,6 +623,83 @@ NextEntry: +unsigned OptJumpTarget2 (CodeSeg* S) +/* If a bcs jumps to a sec insn or a bcc jumps to clc, skip this insn, since + * it's job is already done. + */ +{ + unsigned Changes = 0; + + /* Walk over the entries */ + unsigned I = 0; + while (I < CS_GetEntryCount (S)) { + + /* OP that may be skipped */ + opc_t OPC; + + /* Jump target insn, old and new */ + CodeEntry* T; + CodeEntry* N; + + /* New jump label */ + CodeLabel* L; + + /* Get next entry */ + CodeEntry* E = CS_GetEntry (S, I); + + /* Check if this is a bcc insn */ + if (E->OPC == OP65_BCC || E->OPC == OP65_JCC) { + OPC = OP65_CLC; + } else if (E->OPC == OP65_BCS || E->OPC == OP65_JCS) { + OPC = OP65_SEC; + } else { + /* Not what we're looking for */ + goto NextEntry; + } + + /* Must have a jump target */ + if (E->JumpTo == 0) { + goto NextEntry; + } + + /* Get the owner insn of the jump target and check if it's the one, we + * will skip if present. + */ + T = E->JumpTo->Owner; + if (T->OPC != OPC) { + goto NextEntry; + } + + /* Get the entry following the branch target */ + N = CS_GetNextEntry (S, CS_GetEntryIndex (S, T)); + if (N == 0) { + /* There is no such entry */ + goto NextEntry; + } + + /* Get the label for the instruction following the jump target. + * This routine will create a new label if the instruction does + * not already have one. + */ + L = CS_GenLabel (S, N); + + /* Change the jump target to point to this new label */ + CS_MoveLabelRef (S, E, L); + + /* Remember that we had changes */ + ++Changes; + +NextEntry: + /* Next entry */ + ++I; + } + + /* Return the number of changes made */ + return Changes; +} + + + /*****************************************************************************/ /* Optimize conditional branches */ /*****************************************************************************/ @@ -1481,7 +1558,7 @@ unsigned OptTransfers4 (CodeSeg* S) (LoadEntry->AM == AM65_ABS || LoadEntry->AM == AM65_ZP || LoadEntry->AM == AM65_IMM) && - !MemAccess (S, Load+1, Xfer-1, LoadEntry->Arg)) { + !MemAccess (S, Load+1, Xfer-1, LoadEntry->Arg)) { /* Generate the replacement load insn */ CodeEntry* X = 0; diff --git a/src/cc65/coptind.h b/src/cc65/coptind.h index ca799bcd6..2c7aa9034 100644 --- a/src/cc65/coptind.h +++ b/src/cc65/coptind.h @@ -77,13 +77,18 @@ unsigned OptRTS (CodeSeg* S); * label, the dead code elimination should take care of it. */ -unsigned OptJumpTarget (CodeSeg* S); +unsigned OptJumpTarget1 (CodeSeg* S); /* If the instruction preceeding an unconditional branch is the same as the * instruction preceeding the jump target, the jump target may be moved * one entry back. This is a size optimization, since the instruction before * the branch gets removed. */ +unsigned OptJumpTarget2 (CodeSeg* S); +/* If a bcs jumps to a sec insn or a bcc jumps to clc, skip this insn, since + * it's job is already done. + */ + unsigned OptCondBranches (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