> Am 01.08.2026 um 07:42 schrieb Andrea Pinski <[email protected]>:
>
> 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.
Ok
Richard
> 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]>
> ---
> gcc/gimple-fold.cc | 13 ++++++------
> gcc/testsuite/gcc.dg/torture/pr126313.c | 27 +++++++++++++++++++++++++
> 2 files changed, 34 insertions(+), 6 deletions(-)
> create mode 100644 gcc/testsuite/gcc.dg/torture/pr126313.c
>
> diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
> index fdb9b419766..24041466108 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 00000000000..f4b754775fd
> --- /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 ();
> +}
> --
> 2.43.0
>