https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100499

--- Comment #25 from rguenther at suse dot de <rguenther at suse dot de> ---
On Wed, 26 May 2021, aldyh at gcc dot gnu.org wrote:

> 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?

It's probably too strict for multiple_of_p which is fine with
overflows that preserve modulo behavior.

Reply via email to