Merge pull request #2941 from avolkov76/anv-coptstop-refactor

[cc65] Refactor OptStackOps() subopt precondition evaluation framework, phase 1
This commit is contained in:
Bob Andrews
2026-03-21 14:50:25 +01:00
committed by GitHub
6 changed files with 651 additions and 457 deletions

View File

@@ -756,6 +756,10 @@ void ResetStackOpData (StackOpData* Data)
Data->PushIndex = -1;
Data->OpIndex = -1;
/* Clear to prevent silent optimizer bugs */
Data->ZPLo = 0;
Data->ZPHi = 0;
}
@@ -946,10 +950,9 @@ void AdjustStackOffset (StackOpData* D, unsigned Offs)
int IsRegVar (StackOpData* D)
int IsRegVar (const StackOpData* D)
/* If the value pushed is that of a zeropage variable that is unchanged until Op,
** replace ZPLo and ZPHi in the given StackOpData struct by the variable and return true.
** Otherwise leave D untouched and return false.
** return true.
*/
{
CodeEntry* LoadA = D->Lhs.A.LoadEntry;
@@ -979,9 +982,7 @@ int IsRegVar (StackOpData* D)
return 0;
}
/* Use the zero page location directly */
D->ZPLo = LoadA->Arg;
D->ZPHi = LoadX->Arg;
/* ZP location can be used directly */
return 1;
}
@@ -990,6 +991,8 @@ int IsRegVar (StackOpData* D)
void AddStoreLhsA (StackOpData* D)
/* Add a store to zero page after the push insn */
{
CHECK (D->ZPLo != 0);
CodeEntry* X = NewCodeEntry (OP65_STA, AM65_ZP, D->ZPLo, 0, D->PushEntry->LI);
InsertEntry (D, X, D->PushIndex+1);
}
@@ -999,6 +1002,8 @@ void AddStoreLhsA (StackOpData* D)
void AddStoreLhsX (StackOpData* D)
/* Add a store to zero page after the push insn */
{
CHECK (D->ZPHi != 0);
CodeEntry* X = NewCodeEntry (OP65_STX, AM65_ZP, D->ZPHi, 0, D->PushEntry->LI);
InsertEntry (D, X, D->PushIndex+1);
}
@@ -1071,6 +1076,8 @@ void AddOpLow (StackOpData* D, opc_t OPC, LoadInfo* LI)
} else {
CHECK (D->ZPLo != 0);
/* Op with temp storage */
X = NewCodeEntry (OPC, AM65_ZP, D->ZPLo, 0, D->OpEntry->LI);
InsertEntry (D, X, D->IP++);
@@ -1134,6 +1141,9 @@ void AddOpHigh (StackOpData* D, opc_t OPC, LoadInfo* LI, int KeepResult)
}
} else {
CHECK (D->ZPHi != 0);
/* opc zphi */
X = NewCodeEntry (OPC, AM65_ZP, D->ZPHi, 0, D->OpEntry->LI);
InsertEntry (D, X, D->IP++);

View File

@@ -223,10 +223,9 @@ void AdjustStackOffset (StackOpData* D, unsigned Offs);
** OpIndex is adjusted according to the insertions.
*/
int IsRegVar (StackOpData* D);
int IsRegVar (const StackOpData* D);
/* If the value pushed is that of a zeropage variable that is unchanged until Op,
** replace ZPLo and ZPHi in the given StackOpData struct by the variable and return true.
** Otherwise leave D untouched and return false.
** return true.
*/
void AddStoreLhsA (StackOpData* D);

File diff suppressed because it is too large Load Diff

View File

@@ -8,6 +8,7 @@
unsigned char a, b;
unsigned char c = 199;
unsigned char d = 100;
int i = 50;
int main(void) {
int fails = 0;
@@ -38,6 +39,117 @@ int main(void) {
printf("AND error: a %d instead of %d\n", a, b);
fails++;
}
a = c + (d != 0);
b = c + 1;
printf("%u ^ (%u != 0) => %u\n", c, d, a);
if (a != b) {
printf("ADD error: a %d instead of %d\n", a, b);
fails++;
}
a = c - (d != 0);
b = c - 1;
printf("%u ^ (%u != 0) => %u\n", c, d, a);
if (a != b) {
printf("SUB error: a %d instead of %d\n", a, b);
fails++;
}
a = c ^ (d >= 0);
b = c ^ 1;
printf("%u ^ (%u >= 0) => %u\n", c, d, a);
if (a != b) {
printf("XOR error: a %d instead of %d\n", a, b);
fails++;
}
a = c | (d >= 0);
b = c | 1;
printf("%u | (%u >= 0) => %u\n", c, d, a);
if (a != b) {
printf("OR error: a %d instead of %d\n", a, b);
fails++;
}
a = c & (d >= 0);
b = c & 1;
printf("%u & (%u >= 0) => %u\n", c, d, a);
if (a != b) {
printf("AND error: a %d instead of %d\n", a, b);
fails++;
}
a = c + (d >= 0);
b = c + 1;
printf("%u ^ (%u >= 0) => %u\n", c, d, a);
if (a != b) {
printf("ADD error: a %d instead of %d\n", a, b);
fails++;
}
a = c - (d >= 0);
b = c - 1;
printf("%u ^ (%u >= 0) => %u\n", c, d, a);
if (a != b) {
printf("SUB error: a %d instead of %d\n", a, b);
fails++;
}
printf("%d errors\n", fails);
a = c ^ (i >= 0);
b = c ^ 1;
printf("%u ^ (%d >= 0) => %u\n", c, d, a);
if (a != b) {
printf("XOR int cmp error: a %d instead of %d\n", a, b);
fails++;
}
a = c | (i >= 0);
b = c | 1;
printf("%u | (%d >= 0) => %u\n", c, i, a);
if (a != b) {
printf("OR int cmp error: a %d instead of %d\n", a, b);
fails++;
}
a = c & (i >= 0);
b = c & 1;
printf("%u & (%d >= 0) => %u\n", c, i, a);
if (a != b) {
printf("AND int cmp error: a %d instead of %d\n", a, b);
fails++;
}
a = c + (i >= 0);
b = c + 1;
printf("%u ^ (%d >= 0) => %u\n", c, i, a);
if (a != b) {
printf("ADD int cmp error: a %d instead of %d\n", a, b);
fails++;
}
a = c - (i >= 0);
b = c - 1;
printf("%u ^ (%d >= 0) => %u\n", c, i, a);
if (a != b) {
printf("SUB int cmp error: a %d instead of %d\n", a, b);
fails++;
}
printf("%d errors\n", fails);
return fails;

22
test/val/bug2946.c Normal file
View File

@@ -0,0 +1,22 @@
/* bug #2946: Incomplete, non-removable Rhs asserts in OptStackOps */
#include <stdio.h>
#include <stdlib.h>
unsigned char a, b = 0;
unsigned char c = 10;
unsigned char d = 1;
int main(void) {
/* 'if' needed to produce a label below, moved by OptJumpTarget3 */
if (b != 0) {
/* Operation not important; it only affects the removal of one LDX #$00 */
b = 0;
}
/* d >= 0 is const, A/X=1 (Warning: Result of comparison is always true) */
a = c - (d >= 0);
return !(a == 9);
}

22
test/val/bug2947.c Normal file
View File

@@ -0,0 +1,22 @@
/* bug #2947: Opt_a_tosbitwise() attempts to remove non-removable Rhs X */
#include <stdio.h>
#include <stdlib.h>
unsigned char a, b = 0;
unsigned char c = 10;
unsigned char d = 1;
int main(void) {
/* 'if' needed to produce a label below, moved by OptJumpTarget3 */
if (b != 0) {
/* Operation not important; it only affects the removal of one LDX #$00 */
b = 0;
}
/* d >= 0 is const, A/X=1 (Warning: Result of comparison is always true) */
a = c ^ (d >= 0);
return !(a == 11);
}