gimple-fold: Use bitwise vector types rather than barely supported huge integral types in memcpy etc. folding [PR113988]
The following patch changes the memcpy etc. folding to use bitwise vector types rather than huge INTEGER_TYPEs for copying of > MAX_FIXED_MODE_SIZE lengths. The problem with the huge INTEGER_TYPEs is that they aren't supported very much, usually there are just optabs to handle moves of them, perhaps misaligned moves and that is it, so they pose problems e.g. to BITINT_TYPE lowering. 2024-02-28 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/113988 * stor-layout.h (bitwise_mode_for_size): Declare. * stor-layout.cc (bitwise_mode_for_size): New function. * gimple-fold.cc (gimple_fold_builtin_memory_op): Use it. Use bitwise_type_for_mode instead of build_nonstandard_integer_type. Use BITS_PER_UNIT instead of 8. * gcc.dg/bitint-91.c: New test.
This commit is contained in:
parent
dc30e24b76
commit
cc383e9702
4 changed files with 73 additions and 4 deletions
|
@ -995,9 +995,12 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
|
||||||
if (warning != OPT_Wrestrict)
|
if (warning != OPT_Wrestrict)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
scalar_int_mode mode;
|
scalar_int_mode imode;
|
||||||
if (int_mode_for_size (ilen * 8, 0).exists (&mode)
|
machine_mode mode;
|
||||||
&& GET_MODE_SIZE (mode) * BITS_PER_UNIT == ilen * 8
|
if (int_mode_for_size (ilen * BITS_PER_UNIT, 0).exists (&imode)
|
||||||
|
&& bitwise_mode_for_size (ilen
|
||||||
|
* BITS_PER_UNIT).exists (&mode)
|
||||||
|
&& known_eq (GET_MODE_BITSIZE (mode), ilen * BITS_PER_UNIT)
|
||||||
/* If the destination pointer is not aligned we must be able
|
/* If the destination pointer is not aligned we must be able
|
||||||
to emit an unaligned store. */
|
to emit an unaligned store. */
|
||||||
&& (dest_align >= GET_MODE_ALIGNMENT (mode)
|
&& (dest_align >= GET_MODE_ALIGNMENT (mode)
|
||||||
|
@ -1005,7 +1008,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
|
||||||
|| (optab_handler (movmisalign_optab, mode)
|
|| (optab_handler (movmisalign_optab, mode)
|
||||||
!= CODE_FOR_nothing)))
|
!= CODE_FOR_nothing)))
|
||||||
{
|
{
|
||||||
tree type = build_nonstandard_integer_type (ilen * 8, 1);
|
tree type = bitwise_type_for_mode (mode);
|
||||||
tree srctype = type;
|
tree srctype = type;
|
||||||
tree desttype = type;
|
tree desttype = type;
|
||||||
if (src_align < GET_MODE_ALIGNMENT (mode))
|
if (src_align < GET_MODE_ALIGNMENT (mode))
|
||||||
|
|
|
@ -476,6 +476,32 @@ bitwise_type_for_mode (machine_mode mode)
|
||||||
return inner_type;
|
return inner_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find a mode that can be used for efficient bitwise operations on SIZE
|
||||||
|
bits, if one exists. */
|
||||||
|
|
||||||
|
opt_machine_mode
|
||||||
|
bitwise_mode_for_size (poly_uint64 size)
|
||||||
|
{
|
||||||
|
if (known_le (size, (unsigned int) MAX_FIXED_MODE_SIZE))
|
||||||
|
return mode_for_size (size, MODE_INT, true);
|
||||||
|
|
||||||
|
machine_mode mode, ret = VOIDmode;
|
||||||
|
FOR_EACH_MODE_FROM (mode, MIN_MODE_VECTOR_INT)
|
||||||
|
if (known_eq (GET_MODE_BITSIZE (mode), size)
|
||||||
|
&& (ret == VOIDmode || GET_MODE_INNER (mode) == QImode)
|
||||||
|
&& have_regs_of_mode[mode]
|
||||||
|
&& targetm.vector_mode_supported_p (mode))
|
||||||
|
{
|
||||||
|
if (GET_MODE_INNER (mode) == QImode)
|
||||||
|
return mode;
|
||||||
|
else if (ret == VOIDmode)
|
||||||
|
ret = mode;
|
||||||
|
}
|
||||||
|
if (ret != VOIDmode)
|
||||||
|
return ret;
|
||||||
|
return opt_machine_mode ();
|
||||||
|
}
|
||||||
|
|
||||||
/* Find a mode that is suitable for representing a vector with NUNITS
|
/* Find a mode that is suitable for representing a vector with NUNITS
|
||||||
elements of mode INNERMODE, if one exists. The returned mode can be
|
elements of mode INNERMODE, if one exists. The returned mode can be
|
||||||
either an integer mode or a vector mode. */
|
either an integer mode or a vector mode. */
|
||||||
|
|
|
@ -102,6 +102,8 @@ extern opt_machine_mode mode_for_size_tree (const_tree, enum mode_class, int);
|
||||||
|
|
||||||
extern tree bitwise_type_for_mode (machine_mode);
|
extern tree bitwise_type_for_mode (machine_mode);
|
||||||
|
|
||||||
|
extern opt_machine_mode bitwise_mode_for_size (poly_uint64);
|
||||||
|
|
||||||
/* Given a VAR_DECL, PARM_DECL or RESULT_DECL, clears the results of
|
/* Given a VAR_DECL, PARM_DECL or RESULT_DECL, clears the results of
|
||||||
a previous call to layout_decl and calls it again. */
|
a previous call to layout_decl and calls it again. */
|
||||||
extern void relayout_decl (tree);
|
extern void relayout_decl (tree);
|
||||||
|
|
38
gcc/testsuite/gcc.dg/bitint-91.c
Normal file
38
gcc/testsuite/gcc.dg/bitint-91.c
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/* PR tree-optimization/113988 */
|
||||||
|
/* { dg-do compile { target bitint } } */
|
||||||
|
/* { dg-options "-O2" } */
|
||||||
|
/* { dg-additional-options "-mavx512f" { target i?86-*-* x86_64-*-* } } */
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
#if __BITINT_MAXWIDTH__ >= 256
|
||||||
|
void
|
||||||
|
foo (void *p, _BitInt(256) x)
|
||||||
|
{
|
||||||
|
__builtin_memcpy (p, &x, sizeof x);
|
||||||
|
}
|
||||||
|
|
||||||
|
_BitInt(256)
|
||||||
|
bar (void *p, _BitInt(256) x)
|
||||||
|
{
|
||||||
|
_BitInt(246) y = x + 1;
|
||||||
|
__builtin_memcpy (p, &y, sizeof y);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __BITINT_MAXWIDTH__ >= 512
|
||||||
|
void
|
||||||
|
baz (void *p, _BitInt(512) x)
|
||||||
|
{
|
||||||
|
__builtin_memcpy (p, &x, sizeof x);
|
||||||
|
}
|
||||||
|
|
||||||
|
_BitInt(512)
|
||||||
|
qux (void *p, _BitInt(512) x)
|
||||||
|
{
|
||||||
|
_BitInt(512) y = x + 1;
|
||||||
|
__builtin_memcpy (p, &y, sizeof y);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
#endif
|
Loading…
Add table
Reference in a new issue