So a while back I added support for selecting x/-1 into the ifcvt.cc by
using scc and a couple ALU operations. That code explicitly rejects
STORE_FLAG_VALUE if it is not 1 or -1.
The "1" case has been working well. But -1 has been buggy since
inception -- the affected platforms are m68k and gcn, so not getting a
ton of testing.
In the "1" case we have to subtract one from the output of the SCC insn
to give us a 0/-1 value for T/F. In the -1 case the SCC naturally gives
us the -1 value, so we don't need that subtract one step. But the tense
is inverted, ie -1/0 for T/F and I failed to account for the inverted tense.
This patch obviously fixes the code to handle that inverted tense.
Bootstrapped and regression tested on x86, riscv and m68k. Pushing to
the trunk.
Jeff
PR rtl-optimization/126136
gcc/
* ifcvt.cc (noce_try_store_flag_logical): Fix for STORE_FLAG_VALUE
of -1.
gcc/testsuite
* gcc.dg/torture/pr126136.c: New test.
diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
index 37e757461934..1df5d54efa36 100644
--- a/gcc/ifcvt.cc
+++ b/gcc/ifcvt.cc
@@ -1797,12 +1797,12 @@ noce_try_store_flag_logical (struct noce_if_info
*if_info)
if (!noce_simple_bbs (if_info))
return false;
- bool swapped = false;
+ bool swapped = STORE_FLAG_VALUE == -1;
if (a == CONSTM1_RTX (GET_MODE (dest))
&& if_info->rev_cond)
{
std::swap (a, b);
- swapped = true;
+ swapped = !swapped;
}
if (b != CONSTM1_RTX (GET_MODE (dest)))
diff --git a/gcc/testsuite/gcc.dg/torture/pr126136.c
b/gcc/testsuite/gcc.dg/torture/pr126136.c
new file mode 100644
index 000000000000..cc270f51ca2d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr126136.c
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+
+int i;
+
+__attribute__ ((noipa,noclone,noinline))
+char foo(char val)
+{
+ i++;
+ if (i > 1)
+ return -1;
+ else
+ return val;
+}
+
+int
+main(void)
+{
+ i = 0;
+ if (foo (10) != 10)
+ __builtin_abort ();
+ i += 2;
+ if (foo (10) != -1)
+ __builtin_abort ();
+}