https://gcc.gnu.org/g:cd52e71e8aea258342deca45868bf2529d4fdd76
commit r17-1493-gcd52e71e8aea258342deca45868bf2529d4fdd76 Author: Andrew MacLeod <[email protected]> Date: Wed Jun 10 09:41:27 2026 -0400 Refine modulo range operations with fixed quotient. When all combines of x / y produce the same quotient Q, further refine modulo operations by treating x % y == x - Q * y PR tree-optimization/125706 gcc/ * range-op.cc (operator_trunc_mod::wi_fold): Apply fixed quotient refinement. gcc/testsuite/ * gcc.dg/pr125706.c: New. Diff: --- gcc/range-op.cc | 18 ++++++++++++++++++ gcc/testsuite/gcc.dg/pr125706.c | 14 ++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 5eb3582a2357..94edfdc98708 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -4367,6 +4367,24 @@ operator_trunc_mod::wi_fold (irange &r, tree type, new_ub = wi::min (new_ub, tmp, sign); value_range_with_overflow (r, type, new_lb, new_ub); + + // When all positive and all X/Y combinations produce the same quotient + // we can refine the result with X % Y == X - Q * Y. + // Ensure that division by 0 is not an option. + if (wi::gt_p (rh_lb, 0, sign) && wi::ge_p (lh_lb, 0, sign)) + { + wide_int q_lb = wi::div_trunc (lh_lb, rh_ub, sign); + wide_int q_ub = wi::div_trunc (lh_ub, rh_lb, sign); + + if (q_lb == q_ub) + { + new_lb = lh_lb - q_lb * rh_ub; + new_ub = lh_ub - q_lb * rh_lb; + + int_range<2> refined (type, new_lb, new_ub); + r.intersect (refined); + } + } } bool diff --git a/gcc/testsuite/gcc.dg/pr125706.c b/gcc/testsuite/gcc.dg/pr125706.c new file mode 100644 index 000000000000..d71c5ac613c6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr125706.c @@ -0,0 +1,14 @@ +// { dg-do compile } +// { dg-options "-O2 -fdump-tree-evrp" } + +#include <stdint.h> + +int8_t src(uint8_t v2_u8, int8_t v4_i8, int8_t v5_i8) { + if (!(((uint8_t)6 <= v2_u8) && (v2_u8 <= (uint8_t)7))) __builtin_unreachable(); + if (!(((int8_t)65 <= v4_i8) && (v4_i8 <= (int8_t)80))) __builtin_unreachable(); + if (!(((int8_t)100 <= v5_i8) && (v5_i8 <= (int8_t)101))) __builtin_unreachable(); + int8_t i0_i8 = (int8_t)(v5_i8 % v4_i8); + int8_t i1_i8 = (int8_t)((int8_t)i0_i8 >> (uint8_t)v2_u8); + return i1_i8; +} +// { dg-final { scan-tree-dump "20, 36" "evrp" } }
