https://gcc.gnu.org/g:17c7aeffec9e1f7576957fdcb21e380d4e209c6f
commit r17-4806-g17c7aeffec9e1f7576957fdcb21e380d4e209c6f Author: Dominic P <[email protected]> Date: Wed Sep 30 07:59:35 2026 +0100 forwprop: Reset the range of a rewritten MOD result [PR101179] 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. gcc/testsuite/ChangeLog: PR tree-optimization/101179 * gcc.dg/torture/pr101179.c: New test. Signed-off-by: Dominic P <[email protected]> Diff: --- gcc/testsuite/gcc.dg/torture/pr101179.c | 28 ++++++++++++++++++++++++++++ gcc/tree-ssa-forwprop.cc | 17 ++++++++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/gcc/testsuite/gcc.dg/torture/pr101179.c b/gcc/testsuite/gcc.dg/torture/pr101179.c new file mode 100644 index 000000000000..0493c01b6260 --- /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 64956b05985a..f341514a8eb8 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);
