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))
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)
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;
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:
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)
@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
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;
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;
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)
--- /dev/null
+/* { dg-do compile { target { ilp32 } } } */
+/* { dg-options "" } */
+/* { dg-final { scan-assembler "__builtin_" } } */
+
+int foo (int x)
+{
+ return __builtin_bswap128 (x); /* { dg-warning "implicit declaration" } */
+}
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-require-effective-target int128 } */
+/* { dg-final { scan-assembler-not "call" } } */
+
+__uint128_t foo (__uint128_t x)
+{
+ return __builtin_bswap128 (x);
+}
TI_UINT16_TYPE,
TI_UINT32_TYPE,
TI_UINT64_TYPE,
+ TI_UINT128_TYPE,
TI_VOID,
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;
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,
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
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 ())
#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]