@@ -4517,6 +4517,12 @@ expand_builtin_bswap (enum machine_mode target_mode, tree exp, rtx target,
if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
return NULL_RTX;
+ if (!target
+ && (GET_MODE_PRECISION (word_mode)
+ > TYPE_PRECISION (TREE_TYPE (exp))))
+ target = gen_lowpart_SUBREG (TYPE_MODE (TREE_TYPE (exp)),
+ gen_reg_rtx (word_mode));
+
arg = CALL_EXPR_ARG (exp, 0);
op0 = expand_expr (arg,
subtarget && GET_MODE (subtarget) == target_mode
@@ -4528,8 +4534,13 @@ expand_builtin_bswap (enum machine_mode target_mode, tree exp, rtx target,
target = expand_unop (target_mode, bswap_optab, op0, target, 1);
gcc_assert (target);
-
- return convert_to_mode (target_mode, target, 1);
+ target = convert_to_mode (target_mode, target, 1);
+ if (GET_CODE (target) == SUBREG)
+ {
+ SUBREG_PROMOTED_VAR_P (target) = 1;
+ SUBREG_PROMOTED_SET (target, SRP_UNSIGNED);
+ }
+ return target;
}
/* Expand a call to a unary builtin in EXP.
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-times "uxt" 0 } } */
+
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+
+uint16_t s16 (uint16_t v)
+{
+ return v >> 8 | v << 8;
+}
+
+uint16_t _s16 (uint16_t v)
+{
+ return __builtin_bswap16 (v);
+}
+
+uint32_t s32 (uint32_t v)
+{
+ return __builtin_bswap32 (v);
+}