mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-19 22:21:32 +08:00
Add support for __builtin_bswap128
This patch introduces a new builtin named __builtin_bswap128 on targets where TImode is supported, i.e. 64-bit targets only in practice. The implementation simply reuses the existing double word path in optab, so no routine is added to libgcc (which means that you get two calls to _bswapdi2 in the worst case). gcc/ChangeLog: * builtin-types.def (BT_UINT128): New primitive type. (BT_FN_UINT128_UINT128): New function type. * builtins.def (BUILT_IN_BSWAP128): New GCC builtin. * doc/extend.texi (__builtin_bswap128): Document it. * builtins.c (expand_builtin): Deal with BUILT_IN_BSWAP128. (is_inexpensive_builtin): Likewise. * fold-const-call.c (fold_const_call_ss): Likewise. * fold-const.c (tree_call_nonnegative_warnv_p): Likewise. * tree-ssa-ccp.c (evaluate_stmt): Likewise. * tree-vect-stmts.c (vect_get_data_ptr_increment): Likewise. (vectorizable_call): Likewise. * optabs.c (expand_unop): Always use the double word path for it. * tree-core.h (enum tree_index): Add TI_UINT128_TYPE. * tree.h (uint128_type_node): New global type. * tree.c (build_common_tree_nodes): Build it if TImode is supported. gcc/testsuite/ChangeLog: * gcc.dg/builtin-bswap-10.c: New test. * gcc.dg/builtin-bswap-11.c: Likewise. * gcc.dg/builtin-bswap-12.c: Likewise. * gcc.target/i386/builtin-bswap-5.c: Likewise.
This commit is contained in:
parent
bbaec68c86
commit
fe7ebef7fe
@ -73,6 +73,9 @@ DEF_PRIMITIVE_TYPE (BT_UINT8, unsigned_char_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_UINT16, uint16_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_UINT32, uint32_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_UINT64, uint64_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_UINT128, uint128_type_node
|
||||
? uint128_type_node
|
||||
: error_mark_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_WORD, (*lang_hooks.types.type_for_mode) (word_mode, 1))
|
||||
DEF_PRIMITIVE_TYPE (BT_UNWINDWORD, (*lang_hooks.types.type_for_mode)
|
||||
(targetm.unwind_word_mode (), 1))
|
||||
@ -300,6 +303,7 @@ DEF_FUNCTION_TYPE_1 (BT_FN_UINT8_FLOAT, BT_UINT8, BT_FLOAT)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_UINT16_UINT16, BT_UINT16, BT_UINT16)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_UINT32_UINT32, BT_UINT32, BT_UINT32)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_UINT64_UINT64, BT_UINT64, BT_UINT64)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_UINT128_UINT128, BT_UINT128, BT_UINT128)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_UINT64_FLOAT, BT_UINT64, BT_FLOAT)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_BOOL_INT, BT_BOOL, BT_INT)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_BOOL_PTR, BT_BOOL, BT_PTR)
|
||||
|
@ -7988,6 +7988,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
|
||||
case BUILT_IN_BSWAP16:
|
||||
case BUILT_IN_BSWAP32:
|
||||
case BUILT_IN_BSWAP64:
|
||||
case BUILT_IN_BSWAP128:
|
||||
target = expand_builtin_bswap (target_mode, exp, target, subtarget);
|
||||
if (target)
|
||||
return target;
|
||||
@ -11704,6 +11705,7 @@ is_inexpensive_builtin (tree decl)
|
||||
case BUILT_IN_BSWAP16:
|
||||
case BUILT_IN_BSWAP32:
|
||||
case BUILT_IN_BSWAP64:
|
||||
case BUILT_IN_BSWAP128:
|
||||
case BUILT_IN_CLZ:
|
||||
case BUILT_IN_CLZIMAX:
|
||||
case BUILT_IN_CLZL:
|
||||
|
@ -834,6 +834,8 @@ DEF_GCC_BUILTIN (BUILT_IN_APPLY_ARGS, "apply_args", BT_FN_PTR_VAR, ATTR_L
|
||||
DEF_GCC_BUILTIN (BUILT_IN_BSWAP16, "bswap16", BT_FN_UINT16_UINT16, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_BSWAP32, "bswap32", BT_FN_UINT32_UINT32, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_BSWAP64, "bswap64", BT_FN_UINT64_UINT64, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_BSWAP128, "bswap128", BT_FN_UINT128_UINT128, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_CLEAR_CACHE, "__clear_cache", BT_FN_VOID_PTR_PTR, ATTR_NOTHROW_LEAF_LIST)
|
||||
/* [trans-mem]: Adjust BUILT_IN_TM_CALLOC if BUILT_IN_CALLOC is changed. */
|
||||
DEF_LIB_BUILTIN (BUILT_IN_CALLOC, "calloc", BT_FN_PTR_SIZE_SIZE, ATTR_MALLOC_WARN_UNUSED_RESULT_SIZE_1_2_NOTHROW_LEAF_LIST)
|
||||
|
@ -13784,14 +13784,20 @@ exactly 8 bits.
|
||||
|
||||
@deftypefn {Built-in Function} uint32_t __builtin_bswap32 (uint32_t x)
|
||||
Similar to @code{__builtin_bswap16}, except the argument and return types
|
||||
are 32 bit.
|
||||
are 32-bit.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Built-in Function} uint64_t __builtin_bswap64 (uint64_t x)
|
||||
Similar to @code{__builtin_bswap32}, except the argument and return types
|
||||
are 64 bit.
|
||||
are 64-bit.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Built-in Function} uint128_t __builtin_bswap128 (uint128_t x)
|
||||
Similar to @code{__builtin_bswap64}, except the argument and return types
|
||||
are 128-bit. Only supported on targets when 128-bit types are supported.
|
||||
@end deftypefn
|
||||
|
||||
|
||||
@deftypefn {Built-in Function} Pmode __builtin_extend_pointer (void * x)
|
||||
On targets where the user visible pointer size is smaller than the size
|
||||
of an actual hardware address this function returns the extended user
|
||||
|
@ -1033,6 +1033,7 @@ fold_const_call_ss (wide_int *result, combined_fn fn, const wide_int_ref &arg,
|
||||
case CFN_BUILT_IN_BSWAP16:
|
||||
case CFN_BUILT_IN_BSWAP32:
|
||||
case CFN_BUILT_IN_BSWAP64:
|
||||
case CFN_BUILT_IN_BSWAP128:
|
||||
*result = wide_int::from (arg, precision, TYPE_SIGN (arg_type)).bswap ();
|
||||
return true;
|
||||
|
||||
|
@ -13794,8 +13794,10 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1,
|
||||
CASE_CFN_POPCOUNT:
|
||||
CASE_CFN_CLZ:
|
||||
CASE_CFN_CLRSB:
|
||||
case CFN_BUILT_IN_BSWAP16:
|
||||
case CFN_BUILT_IN_BSWAP32:
|
||||
case CFN_BUILT_IN_BSWAP64:
|
||||
case CFN_BUILT_IN_BSWAP128:
|
||||
/* Always true. */
|
||||
return true;
|
||||
|
||||
|
@ -2889,8 +2889,11 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target,
|
||||
if (temp)
|
||||
return temp;
|
||||
|
||||
/* We do not provide a 128-bit bswap in libgcc so force the use of
|
||||
a double bswap for 64-bit targets. */
|
||||
if (GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
|
||||
&& optab_handler (unoptab, word_mode) != CODE_FOR_nothing)
|
||||
&& (UNITS_PER_WORD == 64
|
||||
|| optab_handler (unoptab, word_mode) != CODE_FOR_nothing))
|
||||
{
|
||||
temp = expand_doubleword_bswap (mode, op0, target);
|
||||
if (temp)
|
||||
|
8
gcc/testsuite/gcc.dg/builtin-bswap-10.c
Normal file
8
gcc/testsuite/gcc.dg/builtin-bswap-10.c
Normal file
@ -0,0 +1,8 @@
|
||||
/* { dg-do compile { target { ilp32 } } } */
|
||||
/* { dg-options "" } */
|
||||
/* { dg-final { scan-assembler "__builtin_" } } */
|
||||
|
||||
int foo (int x)
|
||||
{
|
||||
return __builtin_bswap128 (x); /* { dg-warning "implicit declaration" } */
|
||||
}
|
51
gcc/testsuite/gcc.dg/builtin-bswap-11.c
Normal file
51
gcc/testsuite/gcc.dg/builtin-bswap-11.c
Normal file
@ -0,0 +1,51 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-require-effective-target int128 } */
|
||||
/* { dg-require-effective-target stdint_types } */
|
||||
/* { dg-options "-Wall" } */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define MAKE_FUN(suffix, type) \
|
||||
type my_bswap##suffix(type x) { \
|
||||
type result = 0; \
|
||||
int shift; \
|
||||
for (shift = 0; shift < 8 * sizeof (type); shift += 8) \
|
||||
{ \
|
||||
result <<= 8; \
|
||||
result |= (x >> shift) & 0xff; \
|
||||
} \
|
||||
return result; \
|
||||
} \
|
||||
|
||||
MAKE_FUN(128, __uint128_t);
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct { uint64_t lo; uint64_t hi; } s;
|
||||
__uint128_t n;
|
||||
} u;
|
||||
|
||||
#define NUMS128 \
|
||||
{ \
|
||||
{ .s = { 0x0000000000000000ULL, 0x1122334455667788ULL } }, \
|
||||
{ .s = { 0x1122334455667788ULL, 0xffffffffffffffffULL } }, \
|
||||
{ .s = { 0xffffffffffffffffULL, 0x0000000000000000ULL } } \
|
||||
}
|
||||
|
||||
u uint128_ts[] = NUMS128;
|
||||
|
||||
#define N(table) (sizeof (table) / sizeof (table[0]))
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < N(uint128_ts); i++)
|
||||
if (__builtin_bswap128 (uint128_ts[i].n) != my_bswap128 (uint128_ts[i].n))
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
27
gcc/testsuite/gcc.dg/builtin-bswap-12.c
Normal file
27
gcc/testsuite/gcc.dg/builtin-bswap-12.c
Normal file
@ -0,0 +1,27 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-require-effective-target int128 } */
|
||||
/* { dg-require-effective-target stdint_types } */
|
||||
/* { dg-options "-O" } */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct { uint64_t lo; uint64_t hi; } s;
|
||||
__uint128_t n;
|
||||
} u;
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
/* Test constant folding. */
|
||||
extern void link_error (void);
|
||||
|
||||
const u U1 = { .s = { 0x1122334455667788ULL, 0xffffffffffffffffULL } };
|
||||
const u U2 = { .s = { 0xffffffffffffffffULL, 0x8877665544332211ULL } };
|
||||
|
||||
if (__builtin_bswap128 (U1.n) != U2.n)
|
||||
link_error ();
|
||||
|
||||
return 0;
|
||||
}
|
8
gcc/testsuite/gcc.target/i386/builtin-bswap-5.c
Normal file
8
gcc/testsuite/gcc.target/i386/builtin-bswap-5.c
Normal file
@ -0,0 +1,8 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target int128 } */
|
||||
/* { dg-final { scan-assembler-not "call" } } */
|
||||
|
||||
__uint128_t foo (__uint128_t x)
|
||||
{
|
||||
return __builtin_bswap128 (x);
|
||||
}
|
@ -600,6 +600,7 @@ enum tree_index {
|
||||
TI_UINT16_TYPE,
|
||||
TI_UINT32_TYPE,
|
||||
TI_UINT64_TYPE,
|
||||
TI_UINT128_TYPE,
|
||||
|
||||
TI_VOID,
|
||||
|
||||
|
@ -2002,6 +2002,7 @@ evaluate_stmt (gimple *stmt)
|
||||
case BUILT_IN_BSWAP16:
|
||||
case BUILT_IN_BSWAP32:
|
||||
case BUILT_IN_BSWAP64:
|
||||
case BUILT_IN_BSWAP128:
|
||||
val = get_value_for_expr (gimple_call_arg (stmt, 0), true);
|
||||
if (val.lattice_val == UNDEFINED)
|
||||
break;
|
||||
|
@ -3003,7 +3003,7 @@ vect_get_data_ptr_increment (vec_info *vinfo,
|
||||
return iv_step;
|
||||
}
|
||||
|
||||
/* Check and perform vectorization of BUILT_IN_BSWAP{16,32,64}. */
|
||||
/* Check and perform vectorization of BUILT_IN_BSWAP{16,32,64,128}. */
|
||||
|
||||
static bool
|
||||
vectorizable_bswap (vec_info *vinfo,
|
||||
@ -3385,7 +3385,8 @@ vectorizable_call (vec_info *vinfo,
|
||||
else if (modifier == NONE
|
||||
&& (gimple_call_builtin_p (stmt, BUILT_IN_BSWAP16)
|
||||
|| gimple_call_builtin_p (stmt, BUILT_IN_BSWAP32)
|
||||
|| gimple_call_builtin_p (stmt, BUILT_IN_BSWAP64)))
|
||||
|| gimple_call_builtin_p (stmt, BUILT_IN_BSWAP64)
|
||||
|| gimple_call_builtin_p (stmt, BUILT_IN_BSWAP128)))
|
||||
return vectorizable_bswap (vinfo, stmt_info, gsi, vec_stmt, slp_node,
|
||||
slp_op, vectype_in, cost_vec);
|
||||
else
|
||||
|
@ -10350,6 +10350,8 @@ build_common_tree_nodes (bool signed_char)
|
||||
uint16_type_node = make_or_reuse_type (16, 1);
|
||||
uint32_type_node = make_or_reuse_type (32, 1);
|
||||
uint64_type_node = make_or_reuse_type (64, 1);
|
||||
if (targetm.scalar_mode_supported_p (TImode))
|
||||
uint128_type_node = make_or_reuse_type (128, 1);
|
||||
|
||||
/* Decimal float types. */
|
||||
if (targetm.decimal_float_supported_p ())
|
||||
|
@ -4037,6 +4037,7 @@ tree_strip_any_location_wrapper (tree exp)
|
||||
#define uint16_type_node global_trees[TI_UINT16_TYPE]
|
||||
#define uint32_type_node global_trees[TI_UINT32_TYPE]
|
||||
#define uint64_type_node global_trees[TI_UINT64_TYPE]
|
||||
#define uint128_type_node global_trees[TI_UINT128_TYPE]
|
||||
|
||||
#define void_node global_trees[TI_VOID]
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user