Commit 6512c0f1 by Martin Sebor Committed by Martin Sebor

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
parent f9dd01fa
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> 2017-08-24 Steven Munroe <munroesj@gcc.gnu.org>
* config/rs6000/mm_malloc.h: New file. * config/rs6000/mm_malloc.h: New file.
......
...@@ -628,6 +628,36 @@ var_decl_component_p (tree var) ...@@ -628,6 +628,36 @@ var_decl_component_p (tree var)
return SSA_VAR_P (inner); 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 /* Fold function call to builtin mem{{,p}cpy,move}. Return
false if no simplification can be made. false if no simplification can be made.
If ENDP is 0, return DEST (like memcpy). If ENDP is 0, return DEST (like memcpy).
...@@ -646,8 +676,9 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi, ...@@ -646,8 +676,9 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
tree destvar, srcvar; tree destvar, srcvar;
location_t loc = gimple_location (stmt); location_t loc = gimple_location (stmt);
/* If the LEN parameter is zero, return DEST. */ /* If the LEN parameter is a constant zero or in range where
if (integer_zerop (len)) the only valid value is zero, return DEST. */
if (size_must_be_zero_p (len))
{ {
gimple *repl; gimple *repl;
if (gimple_call_lhs (stmt)) if (gimple_call_lhs (stmt))
......
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> 2017-08-24 Steven Munroe <munroesj@gcc.gnu.org>
* gcc.target/powerpc/mmx-packuswb-1.c [NO_WARN_X86_INTRINSICS]: * gcc.target/powerpc/mmx-packuswb-1.c [NO_WARN_X86_INTRINSICS]:
......
/* 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" } } */
/* 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" } } */
/* 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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment