From 6d9ee1389572ae985f6a39bb99dbd10cdf42c123 Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Wed, 16 Jun 2021 20:27:49 -0700 Subject: amd64: fix conditional jump when compare is swapped and used elsewhere selcmp may potentially swap the arguments and return 1 indicating that the opposite operation should be used. However, if the compare result is used for a conditional jump as well as elsewhere, the original compare op is used instead of the opposite. To fix this, add a check to see whether the opposite compare should be used, regardless of whether selcmp() is done now, or later on during sel(). Bug report and test case from Charlie Stanton. --- amd64/isel.c | 5 +++-- test/cmp1.ssa | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 test/cmp1.ssa diff --git a/amd64/isel.c b/amd64/isel.c index 56e4cf3..5f84561 100644 --- a/amd64/isel.c +++ b/amd64/isel.c @@ -383,9 +383,10 @@ seljmp(Blk *b, Fn *fn) b->jmp.type = Jjf + Cine; } else if (iscmp(fi->op, &k, &c)) { + if (rtype(fi->arg[0]) == RCon) + c = cmpop(c); if (t->nuse == 1) { - if (selcmp(fi->arg, k, fn)) - c = cmpop(c); + selcmp(fi->arg, k, fn); *fi = (Ins){.op = Onop}; } b->jmp.type = Jjf + c; diff --git a/test/cmp1.ssa b/test/cmp1.ssa new file mode 100644 index 0000000..dd5bfa1 --- /dev/null +++ b/test/cmp1.ssa @@ -0,0 +1,17 @@ +# test cmp used in jnz as well as its result value + +export +function w $test(w %c) { +@start + %cmp =w cultw 1, %c + jnz %cmp, @yes, @no +@yes + %cmp =w copy 1 +@no + ret %cmp +} + +# >>> driver +# int test(int); +# int main(void) { return test(0); } +# <<< -- cgit 1.4.1