https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64308
--- Comment #3 from Tavian Barnes <tavianator at gmail dot com> --- @Richard Biener: Yes the range for _16 could be [0, 4294967294]. Why can't VRP can't assume division by zero doesn't occur? If it can then it could say anything mod [a, b] fits in [0, b - 1]. That's a reasonable improvement by itself but it's not enough to optimize this PR, because to use divl for (ret * b % m), you need (ret * b / m) to fit in [0, 4294967295] as well. And to know that that, as Marc Glisse suggests, you'd need symbolic ranges. @Marc Glisse: Is there currently no support at all for symbolic ranges? If you can infer that b < m is an invariant then that's all you need. Formally it's something like this: If x, y, and z are 32-bit unsigned integers, and x <= z || y <= z, then (uint64_t)x * (uint64_t)y % z can be computed with mull and divl because x * y / z is always <= max(x, y) which fits in 32 bits.