machmode.h (bitwise_mode_for_mode): Declare.

gcc/
	* machmode.h (bitwise_mode_for_mode): Declare.
	* stor-layout.h (bitwise_type_for_mode): Likewise.
	* stor-layout.c (bitwise_mode_for_mode): New function.
	(bitwise_type_for_mode): Likewise.
	* builtins.c (fold_builtin_memory_op): Use it instead of
	int_mode_for_mode and build_nonstandard_integer_type.

gcc/testsuite/
	* gcc.dg/memcpy-5.c: New test.

From-SVN: r209622
This commit is contained in:
Richard Sandiford 2014-04-22 12:46:07 +00:00 committed by Richard Sandiford
parent d9f069ab4f
commit dbf23a7900
7 changed files with 113 additions and 20 deletions

View file

@ -1,3 +1,12 @@
2014-04-22 Richard Sandiford <rdsandiford@googlemail.com>
* machmode.h (bitwise_mode_for_mode): Declare.
* stor-layout.h (bitwise_type_for_mode): Likewise.
* stor-layout.c (bitwise_mode_for_mode): New function.
(bitwise_type_for_mode): Likewise.
* builtins.c (fold_builtin_memory_op): Use it instead of
int_mode_for_mode and build_nonstandard_integer_type.
2014-04-22 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* config.gcc (enable_obsolete): Remove *-*-solaris2.9*.

View file

@ -8921,29 +8921,11 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src,
if (FLOAT_MODE_P (TYPE_MODE (desttype))
|| TREE_CODE (desttype) == BOOLEAN_TYPE
|| TREE_CODE (desttype) == ENUMERAL_TYPE)
{
/* A more suitable int_mode_for_mode would return a vector
integer mode for a vector float mode or a integer complex
mode for a float complex mode if there isn't a regular
integer mode covering the mode of desttype. */
enum machine_mode mode = int_mode_for_mode (TYPE_MODE (desttype));
if (mode == BLKmode)
desttype = NULL_TREE;
else
desttype = build_nonstandard_integer_type (GET_MODE_BITSIZE (mode),
1);
}
desttype = bitwise_type_for_mode (TYPE_MODE (desttype));
if (FLOAT_MODE_P (TYPE_MODE (srctype))
|| TREE_CODE (srctype) == BOOLEAN_TYPE
|| TREE_CODE (srctype) == ENUMERAL_TYPE)
{
enum machine_mode mode = int_mode_for_mode (TYPE_MODE (srctype));
if (mode == BLKmode)
srctype = NULL_TREE;
else
srctype = build_nonstandard_integer_type (GET_MODE_BITSIZE (mode),
1);
}
srctype = bitwise_type_for_mode (TYPE_MODE (srctype));
if (!srctype)
srctype = desttype;
if (!desttype)

View file

@ -271,6 +271,8 @@ extern enum machine_mode smallest_mode_for_size (unsigned int,
extern enum machine_mode int_mode_for_mode (enum machine_mode);
extern enum machine_mode bitwise_mode_for_mode (enum machine_mode);
/* Return a mode that is suitable for representing a vector,
or BLKmode on failure. */

View file

@ -403,6 +403,73 @@ int_mode_for_mode (enum machine_mode mode)
return mode;
}
/* Find a mode that can be used for efficient bitwise operations on MODE.
Return BLKmode if no such mode exists. */
enum machine_mode
bitwise_mode_for_mode (enum machine_mode mode)
{
/* Quick exit if we already have a suitable mode. */
unsigned int bitsize = GET_MODE_BITSIZE (mode);
if (SCALAR_INT_MODE_P (mode) && bitsize <= MAX_FIXED_MODE_SIZE)
return mode;
/* Reuse the sanity checks from int_mode_for_mode. */
gcc_checking_assert ((int_mode_for_mode (mode), true));
/* Try to replace complex modes with complex modes. In general we
expect both components to be processed independently, so we only
care whether there is a register for the inner mode. */
if (COMPLEX_MODE_P (mode))
{
enum machine_mode trial = mode;
if (GET_MODE_CLASS (mode) != MODE_COMPLEX_INT)
trial = mode_for_size (bitsize, MODE_COMPLEX_INT, false);
if (trial != BLKmode
&& have_regs_of_mode[GET_MODE_INNER (trial)])
return trial;
}
/* Try to replace vector modes with vector modes. Also try using vector
modes if an integer mode would be too big. */
if (VECTOR_MODE_P (mode) || bitsize > MAX_FIXED_MODE_SIZE)
{
enum machine_mode trial = mode;
if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
trial = mode_for_size (bitsize, MODE_VECTOR_INT, 0);
if (trial != BLKmode
&& have_regs_of_mode[trial]
&& targetm.vector_mode_supported_p (trial))
return trial;
}
/* Otherwise fall back on integers while honoring MAX_FIXED_MODE_SIZE. */
return mode_for_size (bitsize, MODE_INT, true);
}
/* Find a type that can be used for efficient bitwise operations on MODE.
Return null if no such mode exists. */
tree
bitwise_type_for_mode (enum machine_mode mode)
{
mode = bitwise_mode_for_mode (mode);
if (mode == BLKmode)
return NULL_TREE;
unsigned int inner_size = GET_MODE_UNIT_BITSIZE (mode);
tree inner_type = build_nonstandard_integer_type (inner_size, true);
if (VECTOR_MODE_P (mode))
return build_vector_type_for_mode (inner_type, mode);
if (COMPLEX_MODE_P (mode))
return build_complex_type (inner_type);
gcc_checking_assert (GET_MODE_INNER (mode) == VOIDmode);
return inner_type;
}
/* Find a mode that is suitable for representing a vector with
NUNITS elements of mode INNERMODE. Returns BLKmode if there
is no suitable mode. */

View file

@ -98,6 +98,8 @@ extern tree make_unsigned_type (int);
mode_for_size, but is passed a tree. */
extern enum machine_mode mode_for_size_tree (const_tree, enum mode_class, int);
extern tree bitwise_type_for_mode (enum machine_mode);
/* Given a VAR_DECL, PARM_DECL or RESULT_DECL, clears the results of
a previous call to layout_decl and calls it again. */
extern void relayout_decl (tree);

View file

@ -1,3 +1,7 @@
2014-04-22 Richard Sandiford <rdsandiford@googlemail.com>
* gcc.dg/memcpy-5.c: New test.
2014-04-22 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* gcc.c-torture/compile/pr28865.c: Remove dg-xfail-if.

View file

@ -0,0 +1,27 @@
/* { dg-options "-O -fdump-tree-optimized" } */
extern void *memcpy (void *, const void *, __SIZE_TYPE__);
#define TEST(NAME, TYPE) \
TYPE NAME##x; \
char NAME##y[sizeof (NAME##x)] __attribute__((aligned (__alignof__ (NAME##x)))); \
void NAME (void) { memcpy (&NAME##x, &NAME##y, sizeof (NAME##x)); }
TEST (f, float);
TEST (d, double);
TEST (ld, long double);
TEST (cf, _Complex float);
TEST (cd, _Complex double);
TEST (cld, _Complex long double);
TEST (d8f, float __attribute__((vector_size (8))));
TEST (d16f, float __attribute__((vector_size (16))));
TEST (d32f, float __attribute__((vector_size (32))));
TEST (d64f, float __attribute__((vector_size (64))));
TEST (d128f, float __attribute__((vector_size (128))));
TEST (d16d, double __attribute__((vector_size (16))));
TEST (d32d, double __attribute__((vector_size (32))));
TEST (d64d, double __attribute__((vector_size (64))));
TEST (d128d, double __attribute__((vector_size (128))));
/* { dg-final { scan-tree-dump-not "memcpy" "optimized" { target x86_64-*-* } } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */