mirror of
https://github.com/cc65/cc65.git
synced 2025-02-22 12:29:12 +00:00
Some branch improvements.
git-svn-id: svn://svn.cc65.org/cc65/trunk@4019 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
3381311674
commit
15c420fd39
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
/*****************************************************************************/
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user