From 6512c0f187d84dd046380aa53673dc5ae20795e3 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Fri, 25 Aug 2017 00:25:57 +0000 Subject: [PATCH] PR middle-end/81908 - FAIL: gfortran.dg/alloc_comp_auto_array_2.f90 -O3 -g -m32 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 | 6 +++ gcc/gimple-fold.c | 35 +++++++++++++- gcc/testsuite/ChangeLog | 7 +++ .../tree-ssa/builtins-folding-gimple-2.c | 44 ++++++++++++++++++ .../tree-ssa/builtins-folding-gimple-3.c | 43 +++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr81908.c | 46 +++++++++++++++++++ 6 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-2.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-3.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr81908.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 93ad528214b..4f2350a2cc6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2017-08-24 Martin Sebor + + 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 * config/rs6000/mm_malloc.h: New file. diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 251446c5b82..bf39f283ad9 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -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)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7ea69198002..5fb7094419f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2017-08-24 Martin Sebor + + 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 * 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 index 00000000000..5bdb342e85b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-2.c @@ -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 index 00000000000..716be5b8094 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-3.c @@ -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 index 00000000000..b1e316a527c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr81908.c @@ -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); +} -- 2.30.2