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]

[PATCH] avoid warning for memcpy to self (PR 83456)


I have become convinced that issuing -Wrestrict in gimple-fold
for calls to memcpy() where the source pointer is the same as
the destination causes more trouble than it's worth, especially
when inlining is involved, as in:

  inline void bar (void *d, void *s, unsigned N)
  {
    if (s != d)
      memcpy (d, s, N);
  }

  void foo (void* src)
  {
    bar (src, src, 1);
  }

It seems that there should be a way to teach GCC to avoid
folding statements in dead blocks (e.g., in a block controlled
by 'if (0 != 0)' as the one below), and that it might even speed
up compilation, but in the meantime it leads to false positive
-Wrestrict warnings.

The attached patch removes this instance of the warning and
adjusts tests not to expect it.

Martin
PR tree-optimization/83456 - -Wrestrict false positive on a non-overlapping memcpy in an inline function

gcc/ChangeLog:

	PR tree-optimization/83456
	* gimple-fold.c (gimple_fold_builtin_memory_op): Avoid warning
	for perfectly overlapping calls to memcpy.
	(gimple_fold_builtin_memory_chk): Same.

gcc/testsuite/ChangeLog:

	PR tree-optimization/83456
	* c-c++-common/Wrestrict-2.c: Remove test cases.
	* c-c++-common/Wrestrict.c: Same.
	* gcc.dg/Wrestrict-12.c: New test.

Index: gcc/gimple-fold.c
===================================================================
--- gcc/gimple-fold.c	(revision 258339)
+++ gcc/gimple-fold.c	(working copy)
@@ -713,13 +713,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterato
     {
       /* Avoid diagnosing exact overlap in calls to __builtin_memcpy.
 	 It's safe and may even be emitted by GCC itself (see bug
-	 32667).  However, diagnose it in explicit calls to the memcpy
-	 function.  */
-      if (check_overlap && *IDENTIFIER_POINTER (DECL_NAME (func)) != '_')
-      	warning_at (loc, OPT_Wrestrict,
-      		    "%qD source argument is the same as destination",
-      		    func);
-
+	 32667).  */
       unlink_stmt_vdef (stmt);
       if (gimple_vdef (stmt) && TREE_CODE (gimple_vdef (stmt)) == SSA_NAME)
 	release_ssa_name (gimple_vdef (stmt));
@@ -2499,15 +2493,6 @@ gimple_fold_builtin_memory_chk (gimple_stmt_iterat
      (resp. DEST+LEN for __mempcpy_chk).  */
   if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0))
     {
-      if (fcode != BUILT_IN_MEMMOVE && fcode != BUILT_IN_MEMMOVE_CHK)
-	{
-	  tree func = gimple_call_fndecl (stmt);
-
-	  warning_at (loc, OPT_Wrestrict,
-		      "%qD source argument is the same as destination",
-		      func);
-	}
-
       if (fcode != BUILT_IN_MEMPCPY_CHK)
 	{
 	  replace_call_with_value (gsi, dest);
Index: gcc/testsuite/c-c++-common/Wrestrict-2.c
===================================================================
--- gcc/testsuite/c-c++-common/Wrestrict-2.c	(revision 258339)
+++ gcc/testsuite/c-c++-common/Wrestrict-2.c	(working copy)
@@ -12,13 +12,13 @@
 
 static void wrap_memcpy (void *d, const void *s, size_t n)
 {
-  memcpy (d, s, n);   /* { dg-warning "source argument is the same as destination" "memcpy" } */
+  memcpy (d, s, n);   /* { dg-warning "accessing 2 bytes at offsets 0 and 1 overlaps 1 byte at offset 1" "memcpy" } */
 }
 
-void call_memcpy (void *d, size_t n)
+void call_memcpy (char *d)
 {
-  const void *s = d;
-  wrap_memcpy (d, s, n);
+  const void *s = d + 1;
+  wrap_memcpy (d, s, 2);
 }
 
 
Index: gcc/testsuite/c-c++-common/Wrestrict.c
===================================================================
--- gcc/testsuite/c-c++-common/Wrestrict.c	(revision 258339)
+++ gcc/testsuite/c-c++-common/Wrestrict.c	(working copy)
@@ -52,7 +52,6 @@ void test_memcpy_cst (void *d, const void *s)
   } while (0)
 
   T (a, a, 0);
-  T (a, s = a, 3);           /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
 
   /* This isn't detected because memcpy calls with small power-of-2 sizes
      are intentionally folded into safe copies equivalent to memmove.
@@ -64,19 +63,6 @@ void test_memcpy_cst (void *d, const void *s)
   T (a, a + 3, 5);           /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
 
   {
-    char a[3] = { 1, 2, 3 };
-
-    /* Verify that a call to memcpy with an exact overlap is diagnosed
-       (also tested above) but an excplicit one to __builtin_memcpy is
-       not.  See bug 32667 for the rationale.  */
-    (memcpy)(a, a, sizeof a);   /* { dg-warning "source argument is the same as destination" "memcpy" } */
-    sink (a);
-
-    __builtin_memcpy (a, a, sizeof a);
-    sink (a);
-  }
-
-  {
     char a[3][7];
     sink (a);
 
@@ -116,11 +102,6 @@ void test_memcpy_cst (void *d, const void *s)
     memcpy (d, s, sizeof x.a);
     sink (&x);
 
-    d = x.a;
-    s = x.a;
-    memcpy (d, s, sizeof x.a);    /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
-    sink (&x);
-
     d = x.a + 4;
     s = x.b;
     memcpy (d, s, sizeof x.a);    /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
@@ -450,19 +431,6 @@ void test_memcpy_var (char *d, const char *s)
   memcpy (d, d, 0);
   sink (d);
 
-  memcpy (d, d, n);               /* { dg-warning "source argument is the same as destination" "memcpy" } */
-  sink (d);
-
-  memcpy (d, &d[0], n);           /* { dg-warning "source argument is the same as destination" "memcpy" } */
-  sink (d);
-
-  memcpy (&d[0], d,  n);          /* { dg-warning "source argument is the same as destination" "memcpy" } */
-  sink (d);
-
-  s = d;
-  memcpy (d, s, n);               /* { dg-warning "source argument is the same as destination" "memcpy" } */
-  sink (d);
-
   /* The following overlaps if n is greater than 1.  */
   s = d + 1;
   memcpy (d, s, n);
@@ -499,10 +467,6 @@ void test_memcpy_var (char *d, const char *s)
   s = d + 5;
   n = 7;
   memcpy (d, s, n);               /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
-
-  n = UR (0, 1);
-  s = d;
-  memcpy (d, s, n);               /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
 }
 
 
Index: gcc/testsuite/gcc.dg/Wrestrict-12.c
===================================================================
--- gcc/testsuite/gcc.dg/Wrestrict-12.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/Wrestrict-12.c	(working copy)
@@ -0,0 +1,66 @@
+/* PR tree-optimization/83456 - -Wrestrict false positive on
+   a non-overlapping memcpy in an inline function
+   { dg-do compile }
+   { dg-options "-O2 -Wrestrict -ftrack-macro-expansion=0" }  */
+
+extern void* memcpy (void*, const void*, __SIZE_TYPE__);
+
+/* Test case from comment #0.  */
+
+inline void pr83456_comment0 (void *d, void *s, unsigned N)
+{
+  if (s != d)
+    memcpy (d, s, N);
+}
+
+void call_pr83456_comment0 (void* src)
+{
+  pr83456_comment0 (src, src, 1);
+}
+
+
+/* Test case from comment #1.  */
+
+char a[4];
+
+void pr83456_comment1 (unsigned n)
+{
+  for (int i = 0; i < 1; i++)
+    {
+      if (!i)
+	continue;
+
+      memcpy (a, a, n);
+    }
+}
+
+/* Test case from comment #2.  */
+
+struct netdevice {
+  void *priv;
+};
+
+struct ip_tunnel {
+  struct netdevice *dev;
+  int ip6rd[3];
+};
+
+struct sit_net {
+  struct netdevice *fb_tunnel_dev;
+};
+
+void ipip6_tunnel_clone_6rd (struct netdevice *dev, struct sit_net *sitn)
+{
+  struct ip_tunnel *t = dev->priv;
+  if (t->dev == sitn->fb_tunnel_dev)
+    return;
+
+  struct ip_tunnel *t0 = sitn->fb_tunnel_dev->priv;
+  memcpy(&t->ip6rd, &t0->ip6rd, sizeof(t->ip6rd));
+}
+
+void sit_init_net (struct sit_net *sitn, struct netdevice *fb_tunnel_dev)
+{
+  sitn->fb_tunnel_dev = fb_tunnel_dev;
+  ipip6_tunnel_clone_6rd (sitn->fb_tunnel_dev, sitn);
+}

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