mirror of
https://github.com/cc65/cc65.git
synced 2024-12-25 17:29:50 +00:00
Remove more push/pop sequences.
git-svn-id: svn://svn.cc65.org/cc65/trunk@4010 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
d27664036d
commit
b68db83a2b
@ -51,6 +51,39 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int MemAccess (CodeSeg* S, unsigned From, unsigned To, const char* Arg)
|
||||||
|
/* Checks a range of code entries if there are any memory accesses to Arg.
|
||||||
|
* Note: This function is not 100% safe, because there is more than one way
|
||||||
|
* to express a memory location ("foo" and "foo+0" comes to mind) and there
|
||||||
|
* may be other accesses through pointers. For the code generated by cc65 and
|
||||||
|
* for the purpose of the caller (OptPushPop) it is assumed to be safe enough
|
||||||
|
* however.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
/* Walk over all code entries */
|
||||||
|
while (From <= To) {
|
||||||
|
|
||||||
|
/* Get the next entry */
|
||||||
|
CodeEntry* E = CS_GetEntry (S, From);
|
||||||
|
|
||||||
|
/* For simplicity, we just check if there is an argument and if this
|
||||||
|
* argument equals Arg.
|
||||||
|
*/
|
||||||
|
if (E->Arg && strcmp (E->Arg, Arg) == 0) {
|
||||||
|
/* Found an access */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Next entry */
|
||||||
|
++From;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nothing found */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int GetBranchDist (CodeSeg* S, unsigned From, CodeEntry* To)
|
static int GetBranchDist (CodeSeg* S, unsigned From, CodeEntry* To)
|
||||||
/* Get the branch distance between the two entries and return it. The distance
|
/* Get the branch distance between the two entries and return it. The distance
|
||||||
* will be negative for backward jumps and positive for forward jumps.
|
* will be negative for backward jumps and positive for forward jumps.
|
||||||
@ -1225,6 +1258,8 @@ unsigned OptPushPop (CodeSeg* S)
|
|||||||
unsigned I = 0;
|
unsigned I = 0;
|
||||||
while (I < CS_GetEntryCount (S)) {
|
while (I < CS_GetEntryCount (S)) {
|
||||||
|
|
||||||
|
CodeEntry* X;
|
||||||
|
|
||||||
/* Get next entry */
|
/* Get next entry */
|
||||||
CodeEntry* E = CS_GetEntry (S, I);
|
CodeEntry* E = CS_GetEntry (S, I);
|
||||||
|
|
||||||
@ -1245,19 +1280,47 @@ unsigned OptPushPop (CodeSeg* S)
|
|||||||
} else if (E->OPC == OP65_PLA) {
|
} else if (E->OPC == OP65_PLA) {
|
||||||
/* Found a matching pop */
|
/* Found a matching pop */
|
||||||
Pop = I;
|
Pop = I;
|
||||||
|
/* Check that the block between Push and Pop is a basic
|
||||||
|
* block (one entry, one exit). Otherwise ignore it.
|
||||||
|
*/
|
||||||
|
if (CS_IsBasicBlock (S, Push, Pop)) {
|
||||||
State = FoundPop;
|
State = FoundPop;
|
||||||
|
} else {
|
||||||
|
/* Go into searching mode again */
|
||||||
|
State = Searching;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FoundPop:
|
case FoundPop:
|
||||||
/* Next insn, just check if it is no conditional branch and
|
/* We're at the instruction after the PLA.
|
||||||
* that A is not used later. Check also that the range we have
|
* Check for the following conditions:
|
||||||
* found now is a basic block, which means that the PHA is the
|
* - If this instruction is a store of A, and A is not used
|
||||||
* only entrance and the PLA the only exit.
|
* later, we may replace the PHA by the store and remove
|
||||||
|
* pla if several other conditions are met.
|
||||||
|
* - If this instruction is not a conditional branch, and A
|
||||||
|
* is unused later, we may remove PHA and PLA.
|
||||||
*/
|
*/
|
||||||
if ((E->Info & OF_CBRA) == 0 &&
|
if (E->OPC == OP65_STA &&
|
||||||
!RegAUsed (S, I) &&
|
!RegAUsed (S, I+1) &&
|
||||||
CS_IsBasicBlock (S, Push, Pop)) {
|
!MemAccess (S, Push+1, Pop-1, E->Arg)) {
|
||||||
|
|
||||||
|
/* Insert a STA before the PHA */
|
||||||
|
X = NewCodeEntry (E->OPC, E->AM, E->Arg, E->JumpTo, E->LI);
|
||||||
|
CS_InsertEntry (S, X, Push);
|
||||||
|
|
||||||
|
/* Remove the PHA instead */
|
||||||
|
CS_DelEntry (S, Push+1);
|
||||||
|
|
||||||
|
/* Remove the PLA/STA sequence */
|
||||||
|
CS_DelEntries (S, Pop, 2);
|
||||||
|
|
||||||
|
/* Remember we had changes */
|
||||||
|
++Changes;
|
||||||
|
|
||||||
|
} else if ((E->Info & OF_CBRA) == 0 &&
|
||||||
|
!RegAUsed (S, I)) {
|
||||||
|
|
||||||
/* We can remove the PHA and PLA instructions */
|
/* We can remove the PHA and PLA instructions */
|
||||||
CS_DelEntry (S, Pop);
|
CS_DelEntry (S, Pop);
|
||||||
CS_DelEntry (S, Push);
|
CS_DelEntry (S, Push);
|
||||||
@ -1265,6 +1328,7 @@ unsigned OptPushPop (CodeSeg* S)
|
|||||||
I -= 2;
|
I -= 2;
|
||||||
/* Remember we had changes */
|
/* Remember we had changes */
|
||||||
++Changes;
|
++Changes;
|
||||||
|
|
||||||
}
|
}
|
||||||
/* Go into search mode again */
|
/* Go into search mode again */
|
||||||
State = Searching;
|
State = Searching;
|
||||||
|
Loading…
Reference in New Issue
Block a user