Merge pull request #2776 from colinleroy/optimize-incdecsp-further
Further optimize inc/decsp
This commit is contained in:
@@ -907,6 +907,11 @@ static unsigned RunOptGroup7 (CodeSeg* S)
|
||||
between branches */
|
||||
C += RunOptFunc (S, &DOptBranchDist, 3);
|
||||
|
||||
/* Re-optimize inc/decsp that may now be grouped */
|
||||
C += RunOptFunc (S, &DOptStackPtrOps, 5);
|
||||
/* Re-optimize JSR/RTS that may now be grouped */
|
||||
C += RunOptFunc (S, &DOptRTS, 1);
|
||||
|
||||
Changes += C;
|
||||
/* If we had changes, we must run dead code elimination again,
|
||||
** since the changes may have introduced dead code.
|
||||
|
||||
@@ -380,28 +380,37 @@ unsigned OptIndLoads2 (CodeSeg* S)
|
||||
|
||||
|
||||
|
||||
static unsigned IsDecSP (const CodeEntry* E)
|
||||
/* Check if this is an insn that decrements the stack pointer. If so, return
|
||||
** the decrement. If not, return zero.
|
||||
** The function expects E to be a subroutine call.
|
||||
static signed IsSPShift (const CodeEntry* E)
|
||||
/* Check if this is an insn that increments/decrements the stack pointer.
|
||||
** If so, return the value (negative for dec, positive for inc). If not, return zero.
|
||||
*/
|
||||
{
|
||||
if (E->OPC != OP65_JSR && E->OPC != OP65_JMP) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strncmp (E->Arg, "decsp", 5) == 0) {
|
||||
if (E->Arg[5] >= '1' && E->Arg[5] <= '8') {
|
||||
return -(E->Arg[5] - '0');
|
||||
}
|
||||
} else if (strcmp (E->Arg, "subysp") == 0 && RegValIsKnown (E->RI->In.RegY)) {
|
||||
return -(E->RI->In.RegY);
|
||||
} else if (strncmp (E->Arg, "incsp", 5) == 0) {
|
||||
if (E->Arg[5] >= '1' && E->Arg[5] <= '8') {
|
||||
return (E->Arg[5] - '0');
|
||||
}
|
||||
} else if (strcmp (E->Arg, "subysp") == 0 && RegValIsKnown (E->RI->In.RegY)) {
|
||||
return E->RI->In.RegY;
|
||||
} else if (strcmp (E->Arg, "addysp") == 0 && RegValIsKnown (E->RI->In.RegY)) {
|
||||
return (E->RI->In.RegY);
|
||||
}
|
||||
|
||||
/* If we come here, it's not a decsp op */
|
||||
/* If we come here, it's not a dec/incsp op */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned OptStackPtrOps (CodeSeg* S)
|
||||
/* Merge adjacent calls to decsp into one. NOTE: This function won't merge all
|
||||
/* Merge adjacent calls to inc/decsp into one. NOTE: This function won't merge all
|
||||
** known cases!
|
||||
*/
|
||||
{
|
||||
@@ -412,38 +421,45 @@ unsigned OptStackPtrOps (CodeSeg* S)
|
||||
I = 0;
|
||||
while (I < CS_GetEntryCount (S)) {
|
||||
|
||||
unsigned Dec1;
|
||||
unsigned Dec2;
|
||||
signed Val1;
|
||||
signed Val2;
|
||||
const CodeEntry* N;
|
||||
|
||||
/* Get the next entry */
|
||||
const CodeEntry* E = CS_GetEntry (S, I);
|
||||
|
||||
/* Check for decspn or subysp */
|
||||
if (E->OPC == OP65_JSR &&
|
||||
(Dec1 = IsDecSP (E)) > 0 &&
|
||||
(N = CS_GetNextEntry (S, I)) != 0 &&
|
||||
(Dec2 = IsDecSP (N)) > 0 &&
|
||||
(Dec1 += Dec2) <= 255 &&
|
||||
/* Check for decspn, incspn, subysp or addysp */
|
||||
if (E->OPC == OP65_JSR &&
|
||||
(Val1 = IsSPShift (E)) != 0 &&
|
||||
(N = CS_GetNextEntry (S, I)) != 0 &&
|
||||
(N->OPC == OP65_JSR || N->OPC == OP65_JMP) &&
|
||||
(Val2 = IsSPShift (N)) != 0 &&
|
||||
abs(Val1 += Val2) <= 255 &&
|
||||
!CE_HasLabel (N)) {
|
||||
|
||||
CodeEntry* X;
|
||||
char Buf[20];
|
||||
|
||||
/* We can combine the two */
|
||||
if (Dec1 <= 8) {
|
||||
/* Insert a call to decsp */
|
||||
xsprintf (Buf, sizeof (Buf), "decsp%u", Dec1);
|
||||
X = NewCodeEntry (OP65_JSR, AM65_ABS, Buf, 0, N->LI);
|
||||
CS_InsertEntry (S, X, I+2);
|
||||
} else {
|
||||
/* Insert a call to subysp */
|
||||
const char* Arg = MakeHexArg (Dec1);
|
||||
X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, N->LI);
|
||||
CS_InsertEntry (S, X, I+2);
|
||||
X = NewCodeEntry (OP65_JSR, AM65_ABS, "subysp", 0, N->LI);
|
||||
CS_InsertEntry (S, X, I+3);
|
||||
}
|
||||
if (Val1 != 0) {
|
||||
/* We can combine the two */
|
||||
if (abs(Val1) <= 8) {
|
||||
/* Insert a call to inc/decsp using the last OPC */
|
||||
xsprintf (Buf, sizeof (Buf), "%ssp%u", Val1 < 0 ? "dec":"inc", abs(Val1));
|
||||
X = NewCodeEntry (N->OPC, AM65_ABS, Buf, 0, N->LI);
|
||||
CS_InsertEntry (S, X, I+2);
|
||||
} else {
|
||||
/* Insert a call to subysp */
|
||||
const char* Arg = MakeHexArg (abs(Val1));
|
||||
X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, N->LI);
|
||||
CS_InsertEntry (S, X, I+2);
|
||||
if (Val1 < 0) {
|
||||
X = NewCodeEntry (N->OPC, AM65_ABS, "subysp", 0, N->LI);
|
||||
} else {
|
||||
X = NewCodeEntry (N->OPC, AM65_ABS, "addysp", 0, N->LI);
|
||||
}
|
||||
CS_InsertEntry (S, X, I+3);
|
||||
}
|
||||
} /* If total shift == 0, just drop the old code. */
|
||||
|
||||
/* Delete the old code */
|
||||
CS_DelEntries (S, I, 2);
|
||||
|
||||
32
test/val/bug2748.c
Normal file
32
test/val/bug2748.c
Normal file
@@ -0,0 +1,32 @@
|
||||
#include "unittest.h"
|
||||
|
||||
int func(int expr)
|
||||
{
|
||||
{
|
||||
int i = 5;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t c_sp_before, c_sp_after;
|
||||
|
||||
TEST
|
||||
{
|
||||
int a = 11;
|
||||
int b;
|
||||
|
||||
__asm__("lda c_sp");
|
||||
__asm__("ldx c_sp+1");
|
||||
c_sp_before = __AX__;
|
||||
|
||||
b = func(a);
|
||||
|
||||
__asm__("lda c_sp");
|
||||
__asm__("ldx c_sp+1");
|
||||
c_sp_after = __AX__;
|
||||
|
||||
ASSERT_IsTrue(c_sp_before == c_sp_after, "Unexpected stack pointer");
|
||||
ASSERT_IsTrue(b == 5, "Wrong value for b");
|
||||
ASSERT_IsTrue(a == 11, "Wrong value for a");
|
||||
}
|
||||
ENDTEST
|
||||
Reference in New Issue
Block a user