On Wed, Sep 30, 2026, 2:47 PM Dominic P <[email protected]> wrote: > When X may be negative, r17-3791 still rewrites M = X % PHI <2^a, 2^b> > into M = X & PHI <2^a-1, 2^b-1> because M is only compared with zero. > That keeps the zero-ness of M but not its value, yet the range recorded > for M before the rewrite stays, so VRP folded M to 0 in the testcase. > Reset the flow-sensitive info of M in that case. > > Bootstrapped and regression tested on x86_64-pc-linux-gnu; dg.exp, > tree-ssa.exp, execute.exp and the new test were also run on > aarch64-linux-gnu (qemu); no regressions. > > Assisted-by: Claude Opus 5 (Anthropic) > > gcc/ChangeLog: > > PR tree-optimization/101179 > * tree-ssa-forwprop.cc (simplify_phi_result_movdiv): Reset the > flow-sensitive info of the result when its value changes. >
Ok. (Using my Gmail as I am in my phone in the airport) > gcc/testsuite/ChangeLog: > > PR tree-optimization/101179 > * gcc.dg/torture/pr101179.c: New test. > > Signed-off-by: Dominic P <[email protected]> > --- > Changes in v2: the reset is decided where the MOD case is checked, with a > comment, as you suggested. > > OK for trunk? > > gcc/testsuite/gcc.dg/torture/pr101179.c | 28 +++++++++++++++++++++++++ > gcc/tree-ssa-forwprop.cc | 17 ++++++++++++--- > 2 files changed, 42 insertions(+), 3 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/torture/pr101179.c > > diff --git a/gcc/testsuite/gcc.dg/torture/pr101179.c > b/gcc/testsuite/gcc.dg/torture/pr101179.c > new file mode 100644 > index 00000000000..0493c01b626 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/torture/pr101179.c > @@ -0,0 +1,28 @@ > +/* { dg-do run } */ > + > +static int __attribute__((noinline)) > +f (int a, int b, int x, int p, int q) > +{ > + if (x > -1 || x < -100) > + return 5; > + int y; > + if (a) > + y = p; > + else > + y = q; > + int m = x % y; > + if (b) > + return 7; > + if (m == 0) > + return 1; > + return 2; > +} > + > +int > +main (void) > +{ > + volatile int one = 1, zero = 0, v = -100; > + if (f (one, zero, v, 64, 16) != 2) > + __builtin_abort (); > + return 0; > +} > diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc > index 64956b05985..f341514a8eb 100644 > --- a/gcc/tree-ssa-forwprop.cc > +++ b/gcc/tree-ssa-forwprop.cc > @@ -4819,6 +4819,7 @@ simplify_phi_result_movdiv (gimple *stmt, tree_code > code) > { > tree rhs1 = gimple_assign_rhs1 (stmt); > tree_code new_code; > + bool needs_reset = false; > > /* Skip complex types (PR127163) */ > if (!INTEGRAL_TYPE_P (TREE_TYPE (rhs1))) > @@ -4828,9 +4829,17 @@ simplify_phi_result_movdiv (gimple *stmt, tree_code > code) > { > case TRUNC_MOD_EXPR: > case FLOOR_MOD_EXPR: > - if (!tree_expr_nonnegative_p (rhs1) > - && !use_in_zero_equality (gimple_assign_lhs (stmt), true)) > - return false; > + if (!tree_expr_nonnegative_p (rhs1)) > + { > + /* For a negative X, the truncating X % 2^k and X & (2^k - 1) > + differ (e.g. -3 % 4 is -3 but -3 & 3 is 1), though both are > + zero for the same X. That is enough when the result is only > + compared with zero, but the range recorded for the MOD > result > + no longer holds for the AND, so reset it. */ > + needs_reset = true; > + if (!use_in_zero_equality (gimple_assign_lhs (stmt), true)) > + return false; > + } > > new_code = BIT_AND_EXPR; > break; > @@ -4889,6 +4898,8 @@ simplify_phi_result_movdiv (gimple *stmt, tree_code > code) > > gimple_assign_set_rhs2 (stmt, new_phires); > gimple_assign_set_rhs_code (stmt, new_code); > + if (needs_reset) > + reset_flow_sensitive_info (gimple_assign_lhs (stmt)); > update_stmt (stmt); > > gsi = gsi_for_phi (phi); > -- > 2.55.0 > >
