From: Andrew MacLeod Date: Wed, 10 Jun 2026 13:41:27 +0000 (-0400) Subject: Refine modulo range operations with fixed quotient. X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=cd52e71e8aea258342deca45868bf2529d4fdd76;p=thirdparty%2Fgcc.git 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 --git a/gcc/range-op.cc b/gcc/range-op.cc index 5eb3582a235..94edfdc9870 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 00000000000..d71c5ac613c --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr125706.c @@ -0,0 +1,14 @@ +// { dg-do compile } +// { dg-options "-O2 -fdump-tree-evrp" } + +#include + +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" } }