On 08/24/2017 09:03 AM, Martin Sebor wrote: > On 08/24/2017 08:03 AM, Richard Biener wrote: >> On Wed, Aug 23, 2017 at 9:42 PM, Martin Sebor <mse...@gmail.com> wrote: >>> Bug 81908 is about a -Wstringop-overflow warning for a Fortran >>> test triggered by a recent VRP improvement. A simple test case >>> that approximates the warning is: >>> >>> void f (char *d, const char *s, size_t n) >>> { >>> if (n > 0 && n <= SIZE_MAX / 2) >>> n = 0; >>> >>> memcpy (d, s, n); // n in ~[1, SIZE_MAX / 2] >>> } >>> >>> Since the only valid value of n is zero the call to memcpy can >>> be considered a no-op (a value of n > SIZE_MAX is in excess of >>> the maximum size of the largest object and would surely make >>> the call crash). >>> >>> The important difference between the test case and Bug 81908 >>> is that in the latter, the code is emitted by GCC itself from >>> what appears to be correct source (looks like it's the result >>> of the loop distribution pass). I believe the warning for >>> the test case above and for other human-written code like it >>> is helpful, but warning for code emitted by GCC, even if it's >>> dead or unreachable, is obviously not (at least not to users). >>> >>> The attached patch enhances the gimple_fold_builtin_memory_op >>> function to eliminate this patholohgical case by making use >>> of range information to fold into no-ops calls to memcpy whose >>> size argument is in a range where the only valid value is zero. >>> This gets rid of the warning and improves the emitted code. >>> >>> Tested on x86_64-linux. >> >> @@ -646,6 +677,12 @@ gimple_fold_builtin_memory_op >> (gimple_stmt_iterator *gsi, >> tree destvar, srcvar; >> location_t loc = gimple_location (stmt); >> >> + if (tree valid_len = only_valid_value (len)) >> + { >> + /* LEN is in range whose only valid value is zero. */ >> + len = valid_len; >> + } >> + >> /* If the LEN parameter is zero, return DEST. */ >> if (integer_zerop (len)) >> >> just enhance this check to >> >> if (integer_zerop (len) >> || size_must_be_zero_p (len)) >> >> ? 'only_valid_value' looks too generic for this. > > Sure. > > FWIW, the reason I did it this was because my original patch > returned error_mark_node for entirely invalid ranges and had > the caller replace the call with a trap. I decided not to > include that part in this fix to keep it contained. Seems reasonable. Though I would suggest going forward with trap replacement for clearly invalid ranges as a follow-up. Once you do trap replacement, the input operands all become dead as does all the code after the trap and the outgoing edges in the CFG.
That often exposes a fair amount of cleanup. Furthermore on targets that have conditional traps, the controlling condition often turns into a conditional trap. In all, you get a lot of nice cascading effects when you turn something that is clearly bogus into a trap. gimple-ssa-isolate-erroneous-paths probably has the infrastructure you need, including a code you can crib to detect PHI arguments which would cause bogus behavior and allow you to isolate that specific path. > >> >> + if (!wi::fits_uhwi_p (min) || !wi::fits_uhwi_p (max)) >> + return NULL_TREE; >> + >> >> why? > > Only because I never remember what APIs are safe to use with > what input. > >> + if (wi::eq_p (min, wone) >> + && wi::geu_p (max + 1, ssize_max)) >> >> if (wi::eq_p (min, 1) >> && wi::gtu_p (max, wi::max_value (prec, SIGNED))) >> >> your ssize_max isn't signed size max, and max + 1 might overflow to zero. > > You're right that the addition to max would be better done > as subtraction from the result of (1 << N). Thank you. > > If (max + 1) overflowed then (max == TYPE_MAX) would have > to hold which I thought could never be true for an anti > range. (The patch includes tests for this case.) Was I > wrong? Couldn't we have an anti range like ~[TYPE_MAX,TYPE_MAX]? Or am I misunderstanding something. > > Attached is an updated version with the suggested changes > plus an additional test to verify the absence of warnings. The patch is OK. I'll note this is another use of anti-ranges. I'd really like to see Aldy's work on the new range API move forward and get rid of anti-ranges. THanks, jeff