https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108757
--- Comment #23 from Jiu Fu Guo <guojiufu at gcc dot gnu.org> --- /* Simplify ((t + -N*M) / N + M) -> t / N: (t + -C) >> N + (C>>N) ==> t >> N */ (for div (trunc_div exact_div) (simplify (plus (rshift (plus @0 INTEGER_CST@1) INTEGER_CST@2) INTEGER_CST@3) (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type) && (wi::to_wide (@3) << wi::to_wide (@2)) == -wi::to_wide (@1)) (if (TYPE_OVERFLOW_UNDEFINED (type)) (div @0 @2) #if GIMPLE (with { bool overflowed = true; value_range vr0; if (get_range_query (cfun)->range_of_expr (vr0, @0) && !vr0.varying_p () && !vr0.undefined_p ()) { wide_int wmin0 = vr0.lower_bound (); wide_int wmax0 = vr0.upper_bound (); wide_int w1 = -wi::to_wide (@1); wi::overflow_type min_ovf, max_ovf; wi::sub (wmin0, w1, TYPE_SIGN (type), &min_ovf); wi::sub (wmax0, w1, TYPE_SIGN (type), &max_ovf); if (min_ovf == wi::OVF_NONE && max_ovf == wi::OVF_NONE) overflowed = false; } } (if (!overflowed) (rshift @0 @2))) #endif )))) Got one match for the case. Checking if it is safe(condition) or how to support other forms: signed type, negative N, non-power2 N, negative M ...