This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] handle pathological anti-ranges in gimple_fold_builtin_memory_op (PR 81908)


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]