https://gcc.gnu.org/g:8f163f4027736e98af0128b302ae8df49252a70b

commit r16-9120-g8f163f4027736e98af0128b302ae8df49252a70b
Author: Andrew Pinski <[email protected]>
Date:   Sat Jun 13 14:42:30 2026 -0700

    range fold: Fix relation folding of |/& when reversed operands [PR125774]
    
    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)

Diff:
---
 gcc/gimple-range-fold.cc                  |  2 +-
 gcc/testsuite/gcc.dg/torture/pr125774-1.c | 48 +++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 2a968a646d2f..2a90c69b01a2 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 000000000000..00686270d1e5
--- /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__ } } } */

Reply via email to