Merge pull request #2776 from colinleroy/optimize-incdecsp-further

Further optimize inc/decsp
This commit is contained in:
Bob Andrews
2025-07-10 17:02:32 +02:00
committed by GitHub
3 changed files with 83 additions and 30 deletions

View File

@@ -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.

View File

@@ -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
View 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