mirror of
https://github.com/cc65/cc65.git
synced 2024-12-23 04:30:10 +00:00
Fixed potential bugs with boolean branch optimizers when more than one jeq/jne follows.
This commit is contained in:
parent
79c52e742f
commit
f321bb16e5
@ -255,7 +255,8 @@ unsigned OptBoolTrans (CodeSeg* S)
|
||||
if (E->OPC == OP65_JSR &&
|
||||
(Cond = FindBoolCmpCond (E->Arg)) != CMP_INV &&
|
||||
(N = CS_GetNextEntry (S, I)) != 0 &&
|
||||
(N->Info & OF_ZBRA) != 0) {
|
||||
(N->Info & OF_ZBRA) != 0 &&
|
||||
(GetRegInfo (S, I + 2, PSTATE_Z) & PSTATE_Z) == 0) {
|
||||
|
||||
/* Make the boolean transformer unnecessary by changing the
|
||||
** the conditional jump to evaluate the condition flags that
|
||||
@ -606,7 +607,8 @@ unsigned OptBNegA2 (CodeSeg* S)
|
||||
CE_IsCallTo (L[0], "bnega") &&
|
||||
!CE_HasLabel (L[0]) &&
|
||||
(L[1]->Info & OF_ZBRA) != 0 &&
|
||||
!CE_HasLabel (L[1])) {
|
||||
!CE_HasLabel (L[1]) &&
|
||||
(GetRegInfo (S, I + 3, PSTATE_Z) & PSTATE_Z) == 0) {
|
||||
|
||||
/* Invert the branch */
|
||||
CE_ReplaceOPC (L[1], GetInverseBranch (L[1]->OPC));
|
||||
@ -709,7 +711,8 @@ unsigned OptBNegAX2 (CodeSeg* S)
|
||||
CS_GetEntries (S, L+1, I+1, 3) &&
|
||||
CE_IsCallTo (L[1], "ldaxysp") &&
|
||||
CE_IsCallTo (L[2], "bnegax") &&
|
||||
(L[3]->Info & OF_ZBRA) != 0) {
|
||||
(L[3]->Info & OF_ZBRA) != 0 &&
|
||||
(GetRegInfo (S, I + 4, PSTATE_Z) & PSTATE_Z) == 0) {
|
||||
|
||||
CodeEntry* X;
|
||||
|
||||
@ -781,7 +784,8 @@ unsigned OptBNegAX3 (CodeSeg* S)
|
||||
CE_IsCallTo (L[1], "bnegax") &&
|
||||
!CE_HasLabel (L[1]) &&
|
||||
(L[2]->Info & OF_ZBRA) != 0 &&
|
||||
!CE_HasLabel (L[2])) {
|
||||
!CE_HasLabel (L[2]) &&
|
||||
(GetRegInfo (S, I + 4, PSTATE_Z) & PSTATE_Z) == 0) {
|
||||
|
||||
/* ldx --> ora */
|
||||
CE_ReplaceOPC (L[0], OP65_ORA);
|
||||
@ -840,7 +844,8 @@ unsigned OptBNegAX4 (CodeSeg* S)
|
||||
strncmp (L[0]->Arg,"bnega",5) == 0 &&
|
||||
!CE_HasLabel (L[0]) &&
|
||||
(L[1]->Info & OF_ZBRA) != 0 &&
|
||||
!CE_HasLabel (L[1])) {
|
||||
!CE_HasLabel (L[1]) &&
|
||||
(GetRegInfo (S, I + 3, PSTATE_Z) & PSTATE_Z) == 0) {
|
||||
|
||||
CodeEntry* X;
|
||||
|
||||
|
161
test/val/booltrans.c
Normal file
161
test/val/booltrans.c
Normal file
@ -0,0 +1,161 @@
|
||||
/* Optimization bugs with multiple inverse Z branches following one boolean transformer */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
unsigned failures;
|
||||
|
||||
int a;
|
||||
|
||||
/* To reveal the bug, the second Z branch must jump over the destination of the first Z branch */
|
||||
|
||||
int test_booltrans(int8_t x)
|
||||
{
|
||||
a = x;
|
||||
__asm__("lda #$00");
|
||||
__asm__("cmp %v", a);
|
||||
__asm__("jsr booleq");
|
||||
__asm__("jeq %g", L1);
|
||||
__asm__("jne %g", L0);
|
||||
L1:
|
||||
return 1;
|
||||
L0:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_bnega2(int8_t x)
|
||||
{
|
||||
a = x;
|
||||
__asm__("lda %v", a);
|
||||
__asm__("jsr bnega");
|
||||
__asm__("jeq %g", L1);
|
||||
__asm__("jne %g", L0);
|
||||
L1:
|
||||
return 1;
|
||||
L0:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_bnegax2(int16_t x)
|
||||
{
|
||||
int a = x;
|
||||
__asm__("ldy #%o+1", a);
|
||||
__asm__("jsr ldaxysp");
|
||||
__asm__("jsr bnegax");
|
||||
__asm__("jeq %g", L1);
|
||||
__asm__("jne %g", L0);
|
||||
L1:
|
||||
return 1;
|
||||
L0:
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall__ f(void) {}
|
||||
|
||||
int test_bnegax3(int16_t x)
|
||||
{
|
||||
a = x;
|
||||
__asm__("lda %v", a);
|
||||
__asm__("ldx %v+1", a);
|
||||
__asm__("jsr %v", f);
|
||||
__asm__("jsr bnegax");
|
||||
__asm__("jeq %g", L1);
|
||||
__asm__("jne %g", L0);
|
||||
L1:
|
||||
return 1;
|
||||
L0:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_bnegax4(int16_t x)
|
||||
{
|
||||
a = x;
|
||||
__asm__("lda %v", a);
|
||||
__asm__("ldx %v+1", a);
|
||||
__asm__("jsr bnegax");
|
||||
__asm__("jeq %g", L1);
|
||||
__asm__("jne %g", L0);
|
||||
L1:
|
||||
return 1;
|
||||
L0:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
a = test_booltrans(0);
|
||||
if (a != 0)
|
||||
{
|
||||
++failures;
|
||||
printf("test_booltrans(0): %d, expected: 0\n", a);
|
||||
}
|
||||
|
||||
a = test_booltrans(1);
|
||||
if (a != 1)
|
||||
{
|
||||
++failures;
|
||||
printf("test_booltrans(1): %d, expected: 1\n", a);
|
||||
}
|
||||
|
||||
a = test_bnega2(0);
|
||||
if (a != 0)
|
||||
{
|
||||
++failures;
|
||||
printf("test_bnega2(0): %d, expected: 0\n", a);
|
||||
}
|
||||
|
||||
a = test_bnega2(1);
|
||||
if (a != 1)
|
||||
{
|
||||
++failures;
|
||||
printf("test_bnega2(1): %d, expected: 1\n", a);
|
||||
}
|
||||
|
||||
a = test_bnegax2(0);
|
||||
if (a != 0)
|
||||
{
|
||||
++failures;
|
||||
printf("test_bnegax2(0): %d, expected: 0\n", a);
|
||||
}
|
||||
|
||||
a = test_bnegax2(1);
|
||||
if (a != 1)
|
||||
{
|
||||
++failures;
|
||||
printf("test_bnegax2(1): %d, expected: 1\n", a);
|
||||
}
|
||||
|
||||
a = test_bnegax3(0);
|
||||
if (a != 0)
|
||||
{
|
||||
++failures;
|
||||
printf("test_bnegax3(0): %d, expected: 0\n", a);
|
||||
}
|
||||
|
||||
a = test_bnegax3(1);
|
||||
if (a != 1)
|
||||
{
|
||||
++failures;
|
||||
printf("test_bnegax3(1): %d, expected: 1\n", a);
|
||||
}
|
||||
|
||||
a = test_bnegax4(0);
|
||||
if (a != 0)
|
||||
{
|
||||
++failures;
|
||||
printf("test_bnegax4(0): %d, expected: 0\n", a);
|
||||
}
|
||||
|
||||
a = test_bnegax4(1);
|
||||
if (a != 1)
|
||||
{
|
||||
++failures;
|
||||
printf("test_bnegax4(1): %d, expected: 1\n", a);
|
||||
}
|
||||
|
||||
if (failures > 0)
|
||||
{
|
||||
printf("failures: %u\n", failures);
|
||||
}
|
||||
return failures;
|
||||
}
|
Loading…
Reference in New Issue
Block a user