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 */
|
between branches */
|
||||||
C += RunOptFunc (S, &DOptBranchDist, 3);
|
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;
|
Changes += C;
|
||||||
/* If we had changes, we must run dead code elimination again,
|
/* If we had changes, we must run dead code elimination again,
|
||||||
** since the changes may have introduced dead code.
|
** since the changes may have introduced dead code.
|
||||||
|
|||||||
@@ -380,28 +380,37 @@ unsigned OptIndLoads2 (CodeSeg* S)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static unsigned IsDecSP (const CodeEntry* E)
|
static signed IsSPShift (const CodeEntry* E)
|
||||||
/* Check if this is an insn that decrements the stack pointer. If so, return
|
/* Check if this is an insn that increments/decrements the stack pointer.
|
||||||
** the decrement. If not, return zero.
|
** If so, return the value (negative for dec, positive for inc). If not, return zero.
|
||||||
** The function expects E to be a subroutine call.
|
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
|
if (E->OPC != OP65_JSR && E->OPC != OP65_JMP) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (strncmp (E->Arg, "decsp", 5) == 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') {
|
if (E->Arg[5] >= '1' && E->Arg[5] <= '8') {
|
||||||
return (E->Arg[5] - '0');
|
return (E->Arg[5] - '0');
|
||||||
}
|
}
|
||||||
} else if (strcmp (E->Arg, "subysp") == 0 && RegValIsKnown (E->RI->In.RegY)) {
|
} else if (strcmp (E->Arg, "addysp") == 0 && RegValIsKnown (E->RI->In.RegY)) {
|
||||||
return 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
unsigned OptStackPtrOps (CodeSeg* S)
|
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!
|
** known cases!
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
@@ -412,38 +421,45 @@ unsigned OptStackPtrOps (CodeSeg* S)
|
|||||||
I = 0;
|
I = 0;
|
||||||
while (I < CS_GetEntryCount (S)) {
|
while (I < CS_GetEntryCount (S)) {
|
||||||
|
|
||||||
unsigned Dec1;
|
signed Val1;
|
||||||
unsigned Dec2;
|
signed Val2;
|
||||||
const CodeEntry* N;
|
const CodeEntry* N;
|
||||||
|
|
||||||
/* Get the next entry */
|
/* Get the next entry */
|
||||||
const CodeEntry* E = CS_GetEntry (S, I);
|
const CodeEntry* E = CS_GetEntry (S, I);
|
||||||
|
|
||||||
/* Check for decspn or subysp */
|
/* Check for decspn, incspn, subysp or addysp */
|
||||||
if (E->OPC == OP65_JSR &&
|
if (E->OPC == OP65_JSR &&
|
||||||
(Dec1 = IsDecSP (E)) > 0 &&
|
(Val1 = IsSPShift (E)) != 0 &&
|
||||||
(N = CS_GetNextEntry (S, I)) != 0 &&
|
(N = CS_GetNextEntry (S, I)) != 0 &&
|
||||||
(Dec2 = IsDecSP (N)) > 0 &&
|
(N->OPC == OP65_JSR || N->OPC == OP65_JMP) &&
|
||||||
(Dec1 += Dec2) <= 255 &&
|
(Val2 = IsSPShift (N)) != 0 &&
|
||||||
|
abs(Val1 += Val2) <= 255 &&
|
||||||
!CE_HasLabel (N)) {
|
!CE_HasLabel (N)) {
|
||||||
|
|
||||||
CodeEntry* X;
|
CodeEntry* X;
|
||||||
char Buf[20];
|
char Buf[20];
|
||||||
|
|
||||||
/* We can combine the two */
|
if (Val1 != 0) {
|
||||||
if (Dec1 <= 8) {
|
/* We can combine the two */
|
||||||
/* Insert a call to decsp */
|
if (abs(Val1) <= 8) {
|
||||||
xsprintf (Buf, sizeof (Buf), "decsp%u", Dec1);
|
/* Insert a call to inc/decsp using the last OPC */
|
||||||
X = NewCodeEntry (OP65_JSR, AM65_ABS, Buf, 0, N->LI);
|
xsprintf (Buf, sizeof (Buf), "%ssp%u", Val1 < 0 ? "dec":"inc", abs(Val1));
|
||||||
CS_InsertEntry (S, X, I+2);
|
X = NewCodeEntry (N->OPC, AM65_ABS, Buf, 0, N->LI);
|
||||||
} else {
|
CS_InsertEntry (S, X, I+2);
|
||||||
/* Insert a call to subysp */
|
} else {
|
||||||
const char* Arg = MakeHexArg (Dec1);
|
/* Insert a call to subysp */
|
||||||
X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, N->LI);
|
const char* Arg = MakeHexArg (abs(Val1));
|
||||||
CS_InsertEntry (S, X, I+2);
|
X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, N->LI);
|
||||||
X = NewCodeEntry (OP65_JSR, AM65_ABS, "subysp", 0, N->LI);
|
CS_InsertEntry (S, X, I+2);
|
||||||
CS_InsertEntry (S, X, I+3);
|
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 */
|
/* Delete the old code */
|
||||||
CS_DelEntries (S, I, 2);
|
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