[gcc r17-2865] gimple-fold: fix follow_outer_ssa_edges for undefined overflow cases [PR126313]
Andrea Pinski via Gcc-cvs <[email protected]> Sat, 1 Aug 2026 06:24:07 +0000 (GMT)
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://gcc.gnu.org/g:8adc3726fe0c256f4ad36ba1c7d978261118e2f5 commit r17-2865-g8adc3726fe0c256f4ad36ba1c7d978261118e2f5 Author: Andrea Pinski <[email protected]> Date: Fri Jul 24 12:49:54 2026 -0700 gimple-fold: fix follow_outer_ssa_edges for undefined overflow cases [PR126313] ifcombine uses match and match will use in some cases the global range causing wrong code as the range of the ssa name might be based on the outer condition. The case in the bug report is: ``` # RANGE [irange] int [0, 255] MASK 0xff VALUE 0x0 _2 = (int) a.0_1; if (_2 > 1) goto <bb 4>; [59.00%] else goto <bb 3>; [41.00%] <bb 3> [local count: 440234144]: # RANGE [irange] int [0, 1] MASK 0x1 VALUE 0x0 _8 = (int) a.0_1; if (_2 > _8) goto <bb 4>; [50.00%] else goto <bb 5>; [50.00%] ``` So this was `(_2 <= 1 && _2 <= _8) ? goto 5 else; goto 4;` This starts by combnining `_2 <= 1 && _2 <= _8` into `_2 <= min(1, _8)`. But since _8 has a range of [0,1], match invokes the pattern that was added in r14-868-gb06cfb62229f to giving `_2 <= (_8 & 1)` and then since _8 has a range of [0,1], that expression simpifies into `_2 < _8` which is wrong. as _2 is the same as _8. So we end up with not taking the condition any more. The problem comes follow_outer_ssa_edges is used to save off the global range but we return early if the variable had a type where overflow is undefined as we can't temporary rewrite it. So the fix is to swap around the saving the off the global range before returning early. Bootstrapped and tested on x86_64-linux-gnu with no regressions. PR tree-optimization/126313 gcc/ChangeLog: * gimple-fold.cc (follow_outer_ssa_edges): Swap around returning for undefined overflow and saving off the global range. gcc/testsuite/ChangeLog: * gcc.dg/torture/pr126313.c: New test. Signed-off-by: Andrea Pinski <[email protected]> Diff: --- gcc/gimple-fold.cc | 13 +++++++------ gcc/testsuite/gcc.dg/torture/pr126313.c | 27 +++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc index fdb9b4197662..24041466108f 100644 --- a/gcc/gimple-fold.cc +++ b/gcc/gimple-fold.cc @@ -7677,17 +7677,18 @@ follow_outer_ssa_edges (tree val) && (def_bb == fosa_bb || dominated_by_p (CDI_DOMINATORS, fosa_bb, def_bb)))) return val; - /* We cannot temporarily rewrite stmts with undefined overflow - behavior, so avoid expanding them. */ - if ((ANY_INTEGRAL_TYPE_P (TREE_TYPE (val)) - || POINTER_TYPE_P (TREE_TYPE (val))) - && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (val))) - return NULL_TREE; flow_sensitive_info_storage storage; storage.save_and_clear (val); /* If the definition does not dominate fosa_bb temporarily reset flow-sensitive info. */ fosa_unwind->safe_push (std::make_pair (val, storage)); + /* We cannot temporarily rewrite stmts with undefined overflow + behavior, so avoid expanding them. But still save off the + flow-sensitive info as we might be using the ssa name as the leaf. */ + if ((ANY_INTEGRAL_TYPE_P (TREE_TYPE (val)) + || POINTER_TYPE_P (TREE_TYPE (val))) + && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (val))) + return NULL_TREE; return val; } return val; diff --git a/gcc/testsuite/gcc.dg/torture/pr126313.c b/gcc/testsuite/gcc.dg/torture/pr126313.c new file mode 100644 index 000000000000..f4b754775fde --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr126313.c @@ -0,0 +1,27 @@ +/* { dg-do run } */ +/* PR tree-optimization/126313 */ +unsigned char a = 3; +short b, c, d; +int e; +static inline +char(f)(signed char g, signed char p2) { + return p2 == 0 || g && p2 == 1 ? 0 : g % p2; +} +static inline +unsigned i(short g) { + d = g; + return c; +} +static inline +void fn3(signed char g, int p2) { + if (!(1 >= p2 && p2 <= g)) + e = b | i(f(1, p2) > 0xE151060F); + else { + { d = p2; } + } +} +int main() { + fn3(a, a); + if (d != 0) + __builtin_abort (); +}