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