https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100499
--- Comment #23 from Aldy Hernandez <aldyh at gcc dot gnu.org> --- I have an upcoming patchset that implements a range evaluator for tree expressions (similar to determine_value_range), as well as a gimple_ranger that evaluates expressions in a higher precision. This combination looks like it could provide a way for determining overflow: // Return TRUE if evaluating EXPR in its type can produce an overflow. // Overflow is determined by calculating the possible range for EXPR // in its natural type and in a wider type. If the results differ, // evaluating EXPR may have overflowed. bool may_overflow_p (const_tree expr) { gimple_ranger ranger; gimple_ranger_wider wranger (TREE_TYPE (expr)); int_range_max r, w; if (!ranger.range_of_expr (r, const_cast <tree> (expr)) || !wranger.range_of_expr (w, const_cast <tree> (expr))) return true; return r != w; } Of course, we'd need to adapt the above to re-use any active ranger instead of instantiating a new one every time. The above yields overflow for the 16-bit expression in question: (gdb) p debug(top) g_2823_lsm.5_6 * 7854 + 57682 (gdb) p may_overflow_p (top) $6 = true This is because the range of the above expression in unsigned 16-bit yields VARYING (R), whereas in 32-bit unsigned yields [57682, 514769572] (W). Plugging in the above into multiple_of_p: diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 4a4358362e1..ea8ec3bbeec 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -13987,6 +13987,9 @@ multiple_of_p (tree type, const_tree top, const_tree bottom) if (TREE_CODE (type) != INTEGER_TYPE) return 0; + if (may_overflow_p (top)) + return false; + switch (TREE_CODE (top)) { case BIT_AND_EXPR: ...yields what I think is the correct result: (base) abulafia:~/bld/t/gcc$ ./xgcc -B./ a.c -O1 -w (base) abulafia:~/bld/t/gcc$ ./a.out start g_2823 = 60533 end g_2823 = 32768 (base) abulafia:~/bld/t/gcc$ ./xgcc -B./ a.c -O1 -fpeel-loops -ftree-loop-vectorize -w (base) abulafia:~/bld/t/gcc$ ./a.out start g_2823 = 60533 end g_2823 = 32768 Does this seem right?