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?