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.