From 32f1a92aa57d64469e80bb109c292064ea8f7ba6 Mon Sep 17 00:00:00 2001 From: Jan Mercl <0xjnml@gmail.com> Date: Sun, 4 Oct 2026 00:12:23 +0200 Subject: [PATCH] Do not apply the flags of a conditional instruction in TransformConstDst A conditional instruction sets its flags only where its condition holds, so after it they are not known. TransformConstDst handed them to ApplyConditionAfter anyway: `if_e cmp f, #0 wz` folded as an unconditional compare turned the `if_e jmp` after it into a jmp, and `(12 != g) || f` came out 0 for a g of 0 (flexprop issue 118). Test/cexec06.c is the reproducer as a hardware test. --- Test/Expect/cexec06.txt | 1 + Test/cexec06.c | 35 +++++++++++++++++++++++++++++++++++ backends/asm/optimize_ir.c | 5 +++++ 3 files changed, 41 insertions(+) create mode 100644 Test/Expect/cexec06.txt create mode 100644 Test/cexec06.c diff --git a/Test/Expect/cexec06.txt b/Test/Expect/cexec06.txt new file mode 100644 index 000000000..18608e9f3 --- /dev/null +++ b/Test/Expect/cexec06.txt @@ -0,0 +1 @@ +1 1 diff --git a/Test/cexec06.c b/Test/cexec06.c new file mode 100644 index 000000000..927fae68c --- /dev/null +++ b/Test/cexec06.c @@ -0,0 +1,35 @@ +// +// a conditional instruction that sets flags must not be folded +// as if it always ran (flexprop issue 118) +// +#include +#include + +int g; // 0 +int seed = 5; + +void myexit(int n) +{ + putchar(0xff); + putchar(0x0); + putchar(n); + waitcnt(getcnt() + 40000000); +#ifdef __OUTPUT_BYTECODE__ + _cogstop(_cogid()); +#else + __asm { + cogid n + cogstop n + } +#endif +} + +void main() { + int v = seed; + _Bool f = (v < v); // false, and the optimizer can tell + int r = (12 != g) || f; // 1, since g is 0 + _Bool f2 = (seed > 100); // false, and the optimizer cannot tell + int r2 = (12 != g) || f2; + printf("%d %d\n", r, r2); + myexit(0); +} diff --git a/backends/asm/optimize_ir.c b/backends/asm/optimize_ir.c index ff9b671a3..fbffe440c 100644 --- a/backends/asm/optimize_ir.c +++ b/backends/asm/optimize_ir.c @@ -2045,6 +2045,11 @@ TransformConstDst(IRList *irl, IR *ir, Operand *imm) } if (InstrSetsAnyFlags(ir)) { int condchange = 0; + if (ir->cond != COND_TRUE) { + // a conditional instruction sets the flags only where it runs, + // so what they are after it is not known + return 0; + } if (!ApplyConditionAfter(irl,ir, cval, val1, &condchange)) { return condchange; // Couldn't apply condition :( }