===================================================================
@@ -519,6 +519,7 @@ const char * aarch64_output_probe_stack_
const char * aarch64_output_probe_sve_stack_clash (rtx, rtx, rtx, rtx);
void aarch64_err_no_fpadvsimd (machine_mode);
void aarch64_expand_epilogue (bool);
+bool aarch64_move_float_via_int_p (rtx);
void aarch64_expand_mov_immediate (rtx, rtx, rtx (*) (rtx, rtx) = 0);
rtx aarch64_ptrue_reg (machine_mode);
rtx aarch64_pfalse_reg (machine_mode);
===================================================================
@@ -3278,6 +3278,22 @@ aarch64_expand_sve_const_vector (rtx des
gcc_assert (vectors[0] == dest);
}
+/* Return true if floating-point value SRC should be moved into an
+ integer register first and then moved into a floating-point register.
+ This means that SRC is a constant that cannot be moved directly into
+ floating-point registers but assembling it in integer registers is
+ better than forcing it to memory. */
+bool
+aarch64_move_float_via_int_p (rtx src)
+{
+ return (GET_MODE (src) != TFmode
+ && GET_CODE (src) == CONST_DOUBLE
+ && can_create_pseudo_p ()
+ && !aarch64_can_const_movi_rtx_p (src, GET_MODE (src))
+ && !aarch64_float_const_representable_p (src)
+ && aarch64_float_const_rtx_p (src));
+}
+
/* Set DEST to immediate IMM. For SVE vector modes, GEN_VEC_DUPLICATE
is a pattern that can be used to set DEST to a replicated scalar
element. */
===================================================================
@@ -1249,14 +1249,24 @@ (define_expand "mov<mode>"
&& ! (GET_CODE (operands[1]) == CONST_DOUBLE
&& aarch64_float_const_zero_rtx_p (operands[1])))
operands[1] = force_reg (<MODE>mode, operands[1]);
+
+ if (aarch64_move_float_via_int_p (operands[1]))
+ {
+ rtx imm = simplify_gen_subreg (<FCVT_TARGET>mode, operands[1],
+ <MODE>mode, 0);
+ rtx tmp = force_reg (<FCVT_TARGET>mode, imm);
+ operands[1] = gen_lowpart (<MODE>mode, tmp);
+ }
}
)
(define_insn "*movhf_aarch64"
[(set (match_operand:HF 0 "nonimmediate_operand" "=w,w , w,?r,w,w ,w ,w,m,r,m ,r")
(match_operand:HF 1 "general_operand" "Y ,?rY,?r, w,w,Ufc,Uvi,m,w,m,rY,r"))]
- "TARGET_FLOAT && (register_operand (operands[0], HFmode)
- || aarch64_reg_or_fp_zero (operands[1], HFmode))"
+ "TARGET_FLOAT
+ && (register_operand (operands[0], HFmode)
+ || aarch64_reg_or_fp_zero (operands[1], HFmode))
+ && !aarch64_move_float_via_int_p (operands[1])"
"@
movi\\t%0.4h, #0
fmov\\t%h0, %w1
@@ -1278,8 +1288,10 @@ (define_insn "*movhf_aarch64"
(define_insn "*movsf_aarch64"
[(set (match_operand:SF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w ,w,m,r,m ,r,r")
(match_operand:SF 1 "general_operand" "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
- "TARGET_FLOAT && (register_operand (operands[0], SFmode)
- || aarch64_reg_or_fp_zero (operands[1], SFmode))"
+ "TARGET_FLOAT
+ && (register_operand (operands[0], SFmode)
+ || aarch64_reg_or_fp_zero (operands[1], SFmode))
+ && !aarch64_move_float_via_int_p (operands[1])"
"@
movi\\t%0.2s, #0
fmov\\t%s0, %w1
@@ -1302,8 +1314,10 @@ (define_insn "*movsf_aarch64"
(define_insn "*movdf_aarch64"
[(set (match_operand:DF 0 "nonimmediate_operand" "=w, w ,?r,w,w ,w ,w,m,r,m ,r,r")
(match_operand:DF 1 "general_operand" "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
- "TARGET_FLOAT && (register_operand (operands[0], DFmode)
- || aarch64_reg_or_fp_zero (operands[1], DFmode))"
+ "TARGET_FLOAT
+ && (register_operand (operands[0], DFmode)
+ || aarch64_reg_or_fp_zero (operands[1], DFmode))
+ && !aarch64_move_float_via_int_p (operands[1])"
"@
movi\\t%d0, #0
fmov\\t%d0, %x1
@@ -1323,26 +1337,6 @@ (define_insn "*movdf_aarch64"
(set_attr "arch" "simd,*,*,*,*,simd,*,*,*,*,*,*")]
)
-(define_split
- [(set (match_operand:GPF_HF 0 "nonimmediate_operand")
- (match_operand:GPF_HF 1 "general_operand"))]
- "can_create_pseudo_p ()
- && !aarch64_can_const_movi_rtx_p (operands[1], <MODE>mode)
- && !aarch64_float_const_representable_p (operands[1])
- && aarch64_float_const_rtx_p (operands[1])"
- [(const_int 0)]
- {
- unsigned HOST_WIDE_INT ival;
- if (!aarch64_reinterpret_float_as_int (operands[1], &ival))
- FAIL;
-
- rtx tmp = gen_reg_rtx (<FCVT_TARGET>mode);
- emit_move_insn (tmp, gen_int_mode (ival, <FCVT_TARGET>mode));
- emit_move_insn (operands[0], gen_lowpart (<MODE>mode, tmp));
- DONE;
- }
-)
-
(define_insn "*movtf_aarch64"
[(set (match_operand:TF 0
"nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r,m ,m")
===================================================================
@@ -960,12 +960,14 @@ (define_mode_attr fcvt_target [(V2DF "v2
(V2DI "v2df") (V4SI "v4sf") (V2SI "v2sf")
(SF "si") (DF "di") (SI "sf") (DI "df")
(V4HF "v4hi") (V8HF "v8hi") (V4HI "v4hf")
- (V8HI "v8hf") (HF "hi") (HI "hf")])
+ (V8HI "v8hf") (HF "hi") (HI "hf")
+ (TI "tf") (TF "ti")])
(define_mode_attr FCVT_TARGET [(V2DF "V2DI") (V4SF "V4SI") (V2SF "V2SI")
(V2DI "V2DF") (V4SI "V4SF") (V2SI "V2SF")
(SF "SI") (DF "DI") (SI "SF") (DI "DF")
(V4HF "V4HI") (V8HF "V8HI") (V4HI "V4HF")
- (V8HI "V8HF") (HF "HI") (HI "HF")])
+ (V8HI "V8HF") (HF "HI") (HI "HF")
+ (TI "TF") (TF "TI")])
;; for the inequal width integer to fp conversions
===================================================================
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O -mno-pc-relative-literal-loads" } */
+/* { dg-skip-if "Tiny model won't generate adrp" { *-*-* } { "-mcmodel=tiny" } { "" } } */
+
+#include "dbl_mov_immediate_1.c"
+
+/* { dg-final { scan-assembler-times "movi\td\[0-9\]+, #?0" 1 } } */
+
+/* { dg-final { scan-assembler-times "adrp\tx\[0-9\]+, \.LC\[0-9\]" 2 } } */
+/* { dg-final { scan-assembler-times "ldr\td\[0-9\]+, \\\[x\[0-9\], #:lo12:\.LC\[0-9\]\\\]" 2 } } */
+
+/* { dg-final { scan-assembler-times "fmov\td\[0-9\]+, 1\\\.5e\\\+0" 1 } } */
+
+/* { dg-final { scan-assembler-times "mov\tx\[0-9\]+, 25838523252736" 1 } } */
+/* { dg-final { scan-assembler-times "movk\tx\[0-9\]+, 0x40fe, lsl 48" 1 } } */
+/* { dg-final { scan-assembler-times "mov\tx\[0-9\]+, -9223372036854775808" 1 } } */
+/* { dg-final { scan-assembler-times "fmov\td\[0-9\]+, x\[0-9\]+" 2 } } */
+
===================================================================
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+/* { dg-require-effective-target arm_v8_2a_fp16_scalar_ok } */
+/* { dg-add-options arm_v8_2a_fp16_scalar } */
+
+#include "f16_mov_immediate_2.c"
+
+/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.4h, ?#0" 1 } } */
+/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.4h, 0x80, lsl 8" 1 } } */
+/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.4h, 0x5c, lsl 8" 1 } } */
+/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.4h, 0x7c, lsl 8" 1 } } */
+
+/* { dg-final { scan-assembler-times {fmov\th[0-9]+, #?1.7e\+1} 1 } } */
===================================================================
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+#include "flt_mov_immediate_1.c"
+
+/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.2s, ?#0" 1 } } */
+/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.2s, 0x80, lsl 24" 1 } } */
+/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.2s, 0x80, lsl 24" 1 } } */
+
+/* { dg-final { scan-assembler-times "mov\tw\[0-9\]+, 48128" 1 } } */
+/* { dg-final { scan-assembler-times "movk\tw\[0-9\]+, 0x47f0, lsl 16" 1 } } */
+
+/* { dg-final { scan-assembler-times "fmov\ts\[0-9\]+, 2\\\.0e\\\+0" 1 } } */
+
+/* { dg-final { scan-assembler-times "mov\tw\[0-9\]+, 16435" 1 } } */
+/* { dg-final { scan-assembler-times "movk\tw\[0-9\]+, 0xc69c, lsl 16" 1 } } */