--- c-family/c-common.c (revision 186176)
+++ c-family/c-common.c (working copy)
@@ -4991,7 +4991,7 @@ c_common_nodes_and_builtins (void)
uint8_type_node =
TREE_TYPE (identifier_global_value (c_get_ident (UINT8_TYPE)));
if (UINT16_TYPE)
- uint16_type_node =
+ c_uint16_type_node =
TREE_TYPE (identifier_global_value (c_get_ident (UINT16_TYPE)));
if (UINT32_TYPE)
c_uint32_type_node =
--- c-family/c-common.h (revision 186176)
+++ c-family/c-common.h (working copy)
@@ -390,7 +390,7 @@ extern const unsigned int num_c_common_r
#define int32_type_node c_global_trees[CTI_INT32_TYPE]
#define int64_type_node c_global_trees[CTI_INT64_TYPE]
#define uint8_type_node c_global_trees[CTI_UINT8_TYPE]
-#define uint16_type_node c_global_trees[CTI_UINT16_TYPE]
+#define c_uint16_type_node c_global_trees[CTI_UINT16_TYPE]
#define c_uint32_type_node c_global_trees[CTI_UINT32_TYPE]
#define c_uint64_type_node c_global_trees[CTI_UINT64_TYPE]
#define int_least8_type_node c_global_trees[CTI_INT_LEAST8_TYPE]
--- c-family/c-cppbuiltin.c (revision 186176)
+++ c-family/c-cppbuiltin.c (working copy)
@@ -448,8 +448,8 @@ builtin_define_stdint_macros (void)
builtin_define_type_max ("__INT64_MAX__", int64_type_node);
if (uint8_type_node)
builtin_define_type_max ("__UINT8_MAX__", uint8_type_node);
- if (uint16_type_node)
- builtin_define_type_max ("__UINT16_MAX__", uint16_type_node);
+ if (c_uint16_type_node)
+ builtin_define_type_max ("__UINT16_MAX__", c_uint16_type_node);
if (c_uint32_type_node)
builtin_define_type_max ("__UINT32_MAX__", c_uint32_type_node);
if (c_uint64_type_node)
--- optabs.c (revision 186176)
+++ optabs.c (working copy)
@@ -3030,6 +3030,47 @@ expand_unop (enum machine_mode mode, opt
/* Widening (or narrowing) bswap needs special treatment. */
if (unoptab == bswap_optab)
{
+ /* HImode is special because in this mode BSWAP is equivalent to ROTATE
+ or ROTATERT. First try these directly; if this fails, then try the
+ obvious pair of shifts with allowed widening, as this will probably
+ be always more efficient than the other fallback methods. */
+ if (mode == HImode)
+ {
+ rtx last, temp1, temp2;
+
+ if (optab_handler (rotl_optab, mode) != CODE_FOR_nothing)
+ {
+ temp = expand_binop (mode, rotl_optab, op0, GEN_INT (8), target,
+ unsignedp, OPTAB_DIRECT);
+ if (temp)
+ return temp;
+ }
+
+ if (optab_handler (rotr_optab, mode) != CODE_FOR_nothing)
+ {
+ temp = expand_binop (mode, rotr_optab, op0, GEN_INT (8), target,
+ unsignedp, OPTAB_DIRECT);
+ if (temp)
+ return temp;
+ }
+
+ last = get_last_insn ();
+
+ temp1 = expand_binop (mode, ashl_optab, op0, GEN_INT (8), NULL_RTX,
+ unsignedp, OPTAB_WIDEN);
+ temp2 = expand_binop (mode, lshr_optab, op0, GEN_INT (8), NULL_RTX,
+ unsignedp, OPTAB_WIDEN);
+ if (temp1 && temp2)
+ {
+ temp = expand_binop (mode, ior_optab, temp1, temp2, target,
+ unsignedp, OPTAB_WIDEN);
+ if (temp)
+ return temp;
+ }
+
+ delete_insns_since (last);
+ }
+
temp = widen_bswap (mode, op0, target);
if (temp)
return temp;
@@ -3222,10 +3263,10 @@ expand_unop (enum machine_mode mode, opt
/* For certain operations, we need not actually extend
the narrow operand, as long as we will truncate the
results to the same narrowness. */
-
xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
(unoptab == neg_optab
- || unoptab == one_cmpl_optab)
+ || unoptab == one_cmpl_optab
+ || unoptab == bswap_optab)
&& mclass == MODE_INT);
temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
@@ -3240,6 +3281,20 @@ expand_unop (enum machine_mode mode, opt
- GET_MODE_PRECISION (mode)),
target, true, OPTAB_DIRECT);
+ /* Likewise for bswap. */
+ if (unoptab == bswap_optab && temp != 0)
+ {
+ gcc_assert (GET_MODE_PRECISION (wider_mode)
+ == GET_MODE_BITSIZE (wider_mode)
+ && GET_MODE_PRECISION (mode)
+ == GET_MODE_BITSIZE (mode));
+
+ temp = expand_shift (RSHIFT_EXPR, wider_mode, temp,
+ GET_MODE_BITSIZE (wider_mode)
+ - GET_MODE_BITSIZE (mode),
+ NULL_RTX, true);
+ }
+
if (temp)
{
if (mclass != MODE_INT)
--- tree.c (revision 186176)
+++ tree.c (working copy)
@@ -9388,6 +9388,7 @@ build_common_tree_nodes (bool signed_cha
integer_ptr_type_node = build_pointer_type (integer_type_node);
/* Fixed size integer types. */
+ uint16_type_node = build_nonstandard_integer_type (16, true);
uint32_type_node = build_nonstandard_integer_type (32, true);
uint64_type_node = build_nonstandard_integer_type (64, true);
--- tree.h (revision 186176)
+++ tree.h (working copy)
@@ -3747,6 +3747,7 @@ enum tree_index
TI_UINTDI_TYPE,
TI_UINTTI_TYPE,
+ TI_UINT16_TYPE,
TI_UINT32_TYPE,
TI_UINT64_TYPE,
@@ -3902,6 +3903,7 @@ extern GTY(()) tree global_trees[TI_MAX]
#define unsigned_intDI_type_node global_trees[TI_UINTDI_TYPE]
#define unsigned_intTI_type_node global_trees[TI_UINTTI_TYPE]
+#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]
--- builtins.c (revision 186176)
+++ builtins.c (working copy)
@@ -4626,13 +4626,15 @@ expand_builtin_alloca (tree exp, bool ca
return result;
}
-/* Expand a call to a bswap builtin with argument ARG0. MODE
- is the mode to expand with. */
+/* Expand a call to bswap builtin in EXP.
+ Return NULL_RTX if a normal call should be emitted rather than expanding the
+ function in-line. If convenient, the result should be placed in TARGET.
+ SUBTARGET may be used as the target for computing one of EXP's operands. */
static rtx
-expand_builtin_bswap (tree exp, rtx target, rtx subtarget)
+expand_builtin_bswap (enum machine_mode target_mode, tree exp, rtx target,
+ rtx subtarget)
{
- enum machine_mode mode;
tree arg;
rtx op0;
@@ -4640,14 +4642,18 @@ expand_builtin_bswap (tree exp, rtx targ
return NULL_RTX;
arg = CALL_EXPR_ARG (exp, 0);
- mode = TYPE_MODE (TREE_TYPE (arg));
- op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
+ op0 = expand_expr (arg,
+ subtarget && GET_MODE (subtarget) == target_mode
+ ? subtarget : NULL_RTX,
+ target_mode, EXPAND_NORMAL);
+ if (GET_MODE (op0) != target_mode)
+ op0 = convert_to_mode (target_mode, op0, 1);
- target = expand_unop (mode, bswap_optab, op0, target, 1);
+ target = expand_unop (target_mode, bswap_optab, op0, target, 1);
gcc_assert (target);
- return convert_to_mode (mode, target, 0);
+ return convert_to_mode (target_mode, target, 1);
}
/* Expand a call to a unary builtin in EXP.
@@ -6077,10 +6083,10 @@ expand_builtin (tree exp, rtx target, rt
expand_stack_restore (CALL_EXPR_ARG (exp, 0));
return const0_rtx;
+ case BUILT_IN_BSWAP16:
case BUILT_IN_BSWAP32:
case BUILT_IN_BSWAP64:
- target = expand_builtin_bswap (exp, target, subtarget);
-
+ target = expand_builtin_bswap (target_mode, exp, target, subtarget);
if (target)
return target;
break;
--- builtin-types.def (revision 186176)
+++ builtin-types.def (working copy)
@@ -76,6 +76,7 @@ DEF_PRIMITIVE_TYPE (BT_INT128, int128_in
DEF_PRIMITIVE_TYPE (BT_UINT128, int128_unsigned_type_node)
DEF_PRIMITIVE_TYPE (BT_INTMAX, intmax_type_node)
DEF_PRIMITIVE_TYPE (BT_UINTMAX, uintmax_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_WORD, (*lang_hooks.types.type_for_mode) (word_mode, 1))
@@ -226,6 +227,7 @@ DEF_FUNCTION_TYPE_1 (BT_FN_VOID_PTRPTR,
DEF_FUNCTION_TYPE_1 (BT_FN_UINT_UINT, BT_UINT, BT_UINT)
DEF_FUNCTION_TYPE_1 (BT_FN_ULONG_ULONG, BT_ULONG, BT_ULONG)
DEF_FUNCTION_TYPE_1 (BT_FN_ULONGLONG_ULONGLONG, BT_ULONGLONG, BT_ULONGLONG)
+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)
--- builtins.def (revision 186176)
+++ builtins.def (working copy)
@@ -628,6 +628,7 @@ DEF_GCC_BUILTIN (BUILT_IN_AGGREGA
DEF_EXT_LIB_BUILTIN (BUILT_IN_ALLOCA, "alloca", BT_FN_PTR_SIZE, ATTR_MALLOC_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_APPLY, "apply", BT_FN_PTR_PTR_FN_VOID_VAR_PTR_SIZE, ATTR_NULL)
DEF_GCC_BUILTIN (BUILT_IN_APPLY_ARGS, "apply_args", BT_FN_PTR_VAR, ATTR_LEAF_LIST)
+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_EXT_LIB_BUILTIN (BUILT_IN_CLEAR_CACHE, "__clear_cache", BT_FN_VOID_PTR_PTR, ATTR_NOTHROW_LEAF_LIST)