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__ } } } */
