This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] handle pathological anti-ranges in gimple_fold_builtin_memory_op (PR 81908)
- From: Richard Biener <richard dot guenther at gmail dot com>
- To: Martin Sebor <msebor at gmail dot com>
- Cc: Gcc Patch List <gcc-patches at gcc dot gnu dot org>
- Date: Thu, 24 Aug 2017 16:03:32 +0200
- Subject: Re: [PATCH] handle pathological anti-ranges in gimple_fold_builtin_memory_op (PR 81908)
- Authentication-results: sourceware.org; auth=none
- References: <fdd45b8d-876d-0639-34d2-96af298a44d4@gmail.com>
On Wed, Aug 23, 2017 at 9:42 PM, Martin Sebor <msebor@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.
+ if (!wi::fits_uhwi_p (min) || !wi::fits_uhwi_p (max))
+ return NULL_TREE;
+
why?
+ 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.
Richard.
> Martin