PR middle-end/81908 - FAIL: gfortran.dg/alloc_comp_auto_array_2.f90 -O3 -g -m32
authorMartin Sebor <msebor@redhat.com>
Fri, 25 Aug 2017 00:25:57 +0000 (00:25 +0000)
committerMartin Sebor <msebor@gcc.gnu.org>
Fri, 25 Aug 2017 00:25:57 +0000 (18:25 -0600)
gcc/ChangeLog:

PR middle-end/81908
* gimple-fold.c (size_must_be_zero_p): New function.
(gimple_fold_builtin_memory_op): Call it.

gcc/testsuite/ChangeLog:

PR middle-end/81908
* gcc.dg/tree-ssa/builtins-folding-gimple-2.c: New test.
* gcc.dg/tree-ssa/builtins-folding-gimple-3.c: New test.
* gcc.dg/tree-ssa/pr81908.c: New test.

From-SVN: r251347

gcc/ChangeLog
gcc/gimple-fold.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr81908.c [new file with mode: 0644]

index 93ad528214bbd91f008fed22600e69c6d7b5b452..4f2350a2cc60aaeaf784fe72d0c064f2a4717a5d 100644 (file)
@@ -1,3 +1,9 @@
+2017-08-24  Martin Sebor  <msebor@redhat.com>
+
+       PR middle-end/81908
+       * gimple-fold.c (size_must_be_zero_p): New function.
+       (gimple_fold_builtin_memory_op): Call it.
+
 2017-08-24  Steven Munroe  <munroesj@gcc.gnu.org>
 
        * config/rs6000/mm_malloc.h: New file.
index 251446c5b828db0c9e6f99e44a1e798b4b95db82..bf39f283ad93c2cd836a1fc4b82c5c171d2f0979 100644 (file)
@@ -628,6 +628,36 @@ var_decl_component_p (tree var)
   return SSA_VAR_P (inner);
 }
 
+/* If the SIZE argument representing the size of an object is in a range
+   of values of which exactly one is valid (and that is zero), return
+   true, otherwise false.  */
+
+static bool
+size_must_be_zero_p (tree size)
+{
+  if (integer_zerop (size))
+    return true;
+
+  if (TREE_CODE (size) != SSA_NAME)
+    return false;
+
+  wide_int min, max;
+  enum value_range_type rtype = get_range_info (size, &min, &max);
+  if (rtype != VR_ANTI_RANGE)
+    return false;
+
+  tree type = TREE_TYPE (size);
+  int prec = TYPE_PRECISION (type);
+
+  wide_int wone = wi::one (prec);
+
+  /* Compute the value of SSIZE_MAX, the largest positive value that
+     can be stored in ssize_t, the signed counterpart of size_t.  */
+  wide_int ssize_max = wi::lshift (wi::one (prec), prec - 1) - 1;
+
+  return wi::eq_p (min, wone) && wi::geu_p (max, ssize_max);
+}
+
 /* Fold function call to builtin mem{{,p}cpy,move}.  Return
    false if no simplification can be made.
    If ENDP is 0, return DEST (like memcpy).
@@ -646,8 +676,9 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
   tree destvar, srcvar;
   location_t loc = gimple_location (stmt);
 
-  /* If the LEN parameter is zero, return DEST.  */
-  if (integer_zerop (len))
+  /* If the LEN parameter is a constant zero or in range where
+     the only valid value is zero, return DEST.  */
+  if (size_must_be_zero_p (len))
     {
       gimple *repl;
       if (gimple_call_lhs (stmt))
index 7ea691980029809c74cbcb405ec585b74e9a7652..5fb7094419f9472117a9a36f0278389847fbd1c0 100644 (file)
@@ -1,3 +1,10 @@
+2017-08-24  Martin Sebor  <msebor@redhat.com>
+
+       PR middle-end/81908
+       * gcc.dg/tree-ssa/builtins-folding-gimple-2.c: New test.
+       * gcc.dg/tree-ssa/builtins-folding-gimple-3.c: New test.
+       * gcc.dg/tree-ssa/pr81908.c: New test.
+
 2017-08-24  Steven Munroe  <munroesj@gcc.gnu.org>
 
        * gcc.target/powerpc/mmx-packuswb-1.c [NO_WARN_X86_INTRINSICS]:
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-2.c b/gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-2.c
new file mode 100644 (file)
index 0000000..5bdb342
--- /dev/null
@@ -0,0 +1,44 @@
+/* PR 81908 - FAIL: gfortran.dg/alloc_comp_auto_array_2.f90 -O3 -g -m32
+   Test to verify that calls to memcpy et al. where the size is in a range
+   with just one valid value -- zero -- are eliminated.
+   { dg-do compile }
+   { dg-options "-O2 -Wall -fdump-tree-optimized" } */
+
+#define INT_MAX    __INT_MAX__
+#define SHRT_MAX   __SHRT_MAX__
+#define SIZE_MAX   __SIZE_MAX__
+#define SSIZE_MAX  (SIZE_MAX / 2)
+
+typedef __PTRDIFF_TYPE__ ssize_t;
+typedef __SIZE_TYPE__    size_t;
+
+#define UNIQUE_FUNCNAME(func, line) test_ ## func ## _ ## line
+#define FUNCNAME(func, line)        UNIQUE_FUNCNAME (func, line)
+
+#define AR(func, type, min, max, val)                                  \
+  void __attribute__ ((noclone, noinline))                             \
+  FUNCNAME (func, __LINE__) (char *d, const char *s, type n)           \
+  {                                                                    \
+    if ((type)min <= n && n <= (type)max)                              \
+      n = val;                                                         \
+    __builtin_ ## func (d, s, n);                                      \
+  } typedef void DummyType
+
+AR (memcpy, short, 1, SHRT_MAX, 0);
+AR (memcpy, int,   1, INT_MAX, 0);
+AR (memcpy, size_t,  1, SSIZE_MAX, 0);
+AR (memcpy, ssize_t, 1, SSIZE_MAX, 0);
+
+AR (memmove, short, 1, SHRT_MAX, 0);
+AR (memmove, int,   1, INT_MAX, 0);
+AR (memmove, ssize_t, 1, SSIZE_MAX, 0);
+AR (memmove, ssize_t, 1, SSIZE_MAX, 0);
+
+AR (mempcpy, short, 1, SHRT_MAX, 0);
+AR (mempcpy, int,   1, INT_MAX, 0);
+AR (mempcpy, size_t,  1, SSIZE_MAX, 0);
+AR (mempcpy, ssize_t, 1, SSIZE_MAX, 0);
+
+/* { dg-final { scan-tree-dump-not "builtin_memcpy" "optimized" } }
+   { dg-final { scan-tree-dump-not "builtin_memmove" "optimized" } }
+   { dg-final { scan-tree-dump-not "builtin_mempcpy" "optimized" } }  */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-3.c b/gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-3.c
new file mode 100644 (file)
index 0000000..716be5b
--- /dev/null
@@ -0,0 +1,43 @@
+/* PR 81908 - FAIL: gfortran.dg/alloc_comp_auto_array_2.f90 -O3 -g -m32
+   Test to verify that calls to memcpy et al. where the size is in a range
+   with more than one valid value are not eliminated (this test complements
+   builtins-folding-gimple-2.c).
+   { dg-do compile }
+   { dg-options "-O2 -Wall -fdump-tree-optimized" } */
+
+#define SHRT_MAX   __SHRT_MAX__
+#define SHRT_MIN   (-SHRT_MAX - 1)
+#define INT_MAX    __INT_MAX__
+#define INT_MIN    (-INT_MAX - 1)
+
+#define UNIQUE_FUNCNAME(func, line) test_ ## func ## _ ## line
+#define FUNCNAME(func, line)        UNIQUE_FUNCNAME (func, line)
+
+#define AR(func, type, min, max, val)                                  \
+  void __attribute__ ((noclone, noinline))                             \
+  FUNCNAME (func, __LINE__) (char *d, const char *s, type n)           \
+  {                                                                    \
+    if ((type)min <= n && n <= (type)max)                              \
+      n = val;                                                         \
+    __builtin_ ## func (d, s, n);                                      \
+  } typedef void DummyType
+
+AR (memcpy, short, SHRT_MIN, 0, 1);
+AR (memcpy, short, SHRT_MIN, 1, 2);
+AR (memcpy, short, 2, SHRT_MAX, 1);
+
+AR (memcpy, int, INT_MIN, 0, 1);
+AR (memcpy, int, INT_MIN, 1, 2);
+AR (memcpy, int, INT_MIN, 2, 3);
+AR (memcpy, int, 2, INT_MAX, 1);
+AR (memcpy, int, 2, INT_MAX, 1);
+
+AR (memmove, short, 2, SHRT_MAX, 1);
+AR (memmove, int,   2, INT_MAX, 1);
+
+AR (mempcpy, short, 2, SHRT_MAX, 1);
+AR (mempcpy, int,   2, INT_MAX, 1);
+
+/* { dg-final { scan-tree-dump-times "builtin_memcpy" 8 "optimized" } }
+   { dg-final { scan-tree-dump-times "builtin_memmove" 2 "optimized" } }
+   { dg-final { scan-tree-dump-times "builtin_mempcpy" 2 "optimized" } }  */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr81908.c b/gcc/testsuite/gcc.dg/tree-ssa/pr81908.c
new file mode 100644 (file)
index 0000000..b1e316a
--- /dev/null
@@ -0,0 +1,46 @@
+/* PR 81908 - FAIL: gfortran.dg/alloc_comp_auto_array_2.f90 -O3 -g -m32
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+#define SIZE_MAX __SIZE_MAX__
+typedef __SIZE_TYPE__ size_t;
+
+void f0 (char *d, const char *s, size_t n)
+{
+  if (n > 0 && n <= SIZE_MAX / 2 - 1)
+    n = 0;
+
+  __builtin_memcpy (d, s, n);
+}
+
+void f1 (char *d, const char *s, size_t n)
+{
+  if (n > 0 && n <= SIZE_MAX / 2)
+    n = 0;
+
+  __builtin_memcpy (d, s, n);   /* { dg-bogus "\\\[-Wstringop-overflow=]" } */
+}
+
+void f2 (char *d, const char *s, size_t n)
+{
+  if (n > 0 && n <= SIZE_MAX / 2 + 1)
+    n = 0;
+
+  __builtin_memcpy (d, s, n);
+}
+
+void f3 (char *d, const char *s, size_t n)
+{
+  if (n > 0 && n <= SIZE_MAX - 1)
+    n = 0;
+
+  __builtin_memcpy (d, s, n);   /* { dg-bogus "\\\[-Wstringop-overflow=]" } */
+}
+
+void f4 (char *d, const char *s, size_t n)
+{
+  if (n > 0 && n <= SIZE_MAX)
+    n = 0;
+
+  __builtin_memcpy (d, s, n);
+}