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?

Reply via email to