This showed up in GCC 13 in the original testcase but became latent in GCC 14.
So I created a simple gimple testcase to show the issue.
So what we have is:
  _21 = _20 > lower_9;
  _22 = lower_9 > _20;
  _23 = _21 | _22;

And this would incorrectly be folded into 1 and that is because we treated one 
of
those `>` as `<=` rather than as just `<`. This was due to an incorrect use
of relation_negate rather than relation_swap when dealing with swapping the 
operands.

Pushed as obvious after a bootstrap/test on x86_64-linux-gnu.

        PR tree-optimization/125774

gcc/ChangeLog:

        * gimple-range-fold.cc (fold_using_range::relation_fold_and_or): Use
        relation_swap rather than relation_negate when the operands are 
exchanged.

gcc/testsuite/ChangeLog:

        * gcc.dg/torture/pr125774-1.c: New test.

Signed-off-by: Andrew Pinski <[email protected]>
(cherry picked from commit 905d407ee4b23c749fa00d0cf3b0aed551a07f36)
---
 gcc/gimple-range-fold.cc                  |  2 +-
 gcc/testsuite/gcc.dg/torture/pr125774-1.c | 48 +++++++++++++++++++++++
 2 files changed, 49 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr125774-1.c

diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 2a968a646d2..2a90c69b01a 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -1566,7 +1566,7 @@ fold_using_range::relation_fold_and_or (irange& 
lhs_range, gimple *s,
     return;
 
   if (reverse_op2)
-    relation2 = relation_negate (relation2);
+    relation2 = relation_swap (relation2);
 
   // x && y is false if the relation intersection of the true cases is NULL.
   if (is_and && relation_intersect (relation1, relation2) == VREL_UNDEFINED)
diff --git a/gcc/testsuite/gcc.dg/torture/pr125774-1.c 
b/gcc/testsuite/gcc.dg/torture/pr125774-1.c
new file mode 100644
index 00000000000..00686270d1e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr125774-1.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fgimple -fdump-tree-optimized" } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */
+/* PR tree-optimization/125774 */
+
+__attribute__((noipa))
+_Bool __GIMPLE (ssa,startwith("dom2"))
+f (int a, int b)
+{
+  _Bool _3;
+  _Bool _4;
+  _Bool _5;
+
+  __BB(2):
+  _3 = a_1(D) > b_2(D);
+  _4 = b_2(D) > a_1(D);
+  _5 = _3 | _4;
+  return _5;
+}
+
+__attribute__((noipa))
+_Bool __GIMPLE (ssa,startwith("dom2"))
+f1 (int a, int b)
+{
+  _Bool _3;
+  _Bool _4;
+  _Bool _5;
+
+  __BB(2):
+  _3 = a_1(D) > b_2(D);
+  _4 = a_1(D) < b_2(D);
+  _5 = _3 | _4;
+  return _5;
+}
+
+int main()
+{
+  int a = 10, b = 10;
+  if (f(a,b))
+    __builtin_abort();
+  if (f1(a,b))
+    __builtin_abort();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "return 1" "optimized" } } */
+/* Both functions should be optimized to `a_1 != b_2`. */
+/* { dg-final { scan-tree-dump-times "a_1.D. != b_2.D." 2 "optimized" { target 
__OPTIMIZE__ } } } */
-- 
2.43.0

Reply via email to