diff options
author | Yvan Roux <yvan.roux@linaro.org> | 2017-09-13 16:54:08 +0200 |
---|---|---|
committer | Yvan Roux <yvan.roux@linaro.org> | 2017-09-13 19:57:27 +0000 |
commit | b637432f10f34af6d5680363f853f929d0472652 (patch) | |
tree | cba9ba53164e13288cc2a4cebf07f5019a2d2150 | |
parent | 5e7382e1b6c14e9ded79cac2c600e00c433206d5 (diff) |
gcc/
Backport from trunk r250672.
2017-07-28 Tamar Christina <tamar.christina@arm.com>
* config/aarch64/aarch64.c
(aarch64_simd_container_mode): Add prototype.
(aarch64_expand_mov_immediate): Add HI support.
(aarch64_reinterpret_float_as_int, aarch64_float_const_rtx_p: New.
(aarch64_can_const_movi_rtx_p): New.
(aarch64_preferred_reload_class):
Remove restrictions of using FP registers for certain SIMD operations.
(aarch64_rtx_costs): Added new cost for CONST_DOUBLE moves.
(aarch64_valid_floating_const): Add integer move validation.
(aarch64_simd_imm_scalar_p): Remove.
(aarch64_output_scalar_simd_mov_immediate): Generalize function.
(aarch64_legitimate_constant_p): Expand list of supported cases.
* config/aarch64/aarch64-protos.h
(aarch64_float_const_rtx_p, aarch64_can_const_movi_rtx_p): New.
(aarch64_reinterpret_float_as_int): New.
(aarch64_simd_imm_scalar_p): Remove.
* config/aarch64/constraints.md (Uvi): New.
(Dd): Split into Ds and new Dd.
* config/aarch64/aarch64.md (*movsi_aarch64):
Add SIMD mov case.
(*movdi_aarch64): Add SIMD mov case.
gcc/
Backport from trunk r250673.
2017-07-28 Tamar Christina <tamar.christina@arm.com>
Richard Sandiford <richard.sandiford@linaro.org>
* config/aarch64/aarch64.md (mov<mode>): Generalize.
(*movhf_aarch64, *movsf_aarch64, *movdf_aarch64):
Add integer and movi cases.
(movi-split-hf-df-sf split, fp16): New.
(enabled): Added TARGET_FP_F16INST.
* config/aarch64/iterators.md (GPF_HF): New.
* config/aarch64/predicates.md (aarch64_reg_or_fp_float): New.
gcc/testsuite/
Backport from trunk r250674.
2017-07-28 Tamar Christina <tamar.christina@arm.com>
Bilyan Borisov <bilyan.borisov@arm.com>
* gcc.target/aarch64/dbl_mov_immediate_1.c: New.
* gcc.target/aarch64/flt_mov_immediate_1.c: New.
* gcc.target/aarch64/f16_mov_immediate_1.c: New.
* gcc.target/aarch64/f16_mov_immediate_2.c: New.
* gcc.target/aarch64/pr63304_1.c: Changed to double.
gcc/
Backport from trunk r250680.
2017-07-28 Tamar Christina <tamar.christina@arm.com>
* config/aarch64/aarch64.c
(aarch64_internal_mov_immediate): Add new special pattern.
* config/aarch64/aarch64.md (*movdi_aarch64):
Add reg/32bit const mov case.
gcc/testsuite/
Backport from trunk r250680.
2017-07-28 Tamar Christina <tamar.christina@arm.com>
* gcc.target/aarch64/int_mov_immediate_1.c: New.
gcc/
Backport from trunk r250766.
2017-08-01 Tamar Christina <tamar.christina@arm.com>
* config/aarch64/aarch64.c
(aarch64_can_const_movi_rtx_p): Move 0 check.
gcc/
Backport from trunk r250818.
2017-08-02 Tamar Christina <tamar.christina@arm.com>
* config/aarch64/aarch64.c (aarch64_reinterpret_float_as_int):
Correct endianness.
gcc/
Backport from trunk r251051.
2017-08-11 Tamar Christina <tamar.christina@arm.com>
* config/aarch64/aarch64.md (mov<mode>): Change.
(*movhf_aarch64, *movsf_aarch64, *movdf_aarch64):
aarch64_reg_or_fp_float into aarch64_reg_or_fp_zero.
* config/aarch64/predicates.md (aarch64_reg_or_fp_float): Removed.
gcc/testsuite/
Backport from trunk r251086.
2017-08-14 Szabolcs Nagy <szabolcs.nagy@arm.com>
* gcc.target/aarch64/dbl_mov_immediate_1.c: Add
-mno-pc-relative-literal-loads.
Change-Id: Ie7203aca0b4c436af3d4625e79b296ab8212040c
-rw-r--r-- | gcc/config/aarch64/aarch64-protos.h | 4 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.c | 221 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.md | 112 | ||||
-rw-r--r-- | gcc/config/aarch64/constraints.md | 18 | ||||
-rw-r--r-- | gcc/config/aarch64/iterators.md | 3 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/dbl_mov_immediate_1.c | 53 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_1.c | 49 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_2.c | 45 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/flt_mov_immediate_1.c | 52 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/int_mov_immediate_1.c | 59 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/pr63304_1.c | 18 |
11 files changed, 550 insertions, 84 deletions
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index bfe44a75e12..397ff7fb50c 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -319,6 +319,7 @@ unsigned HOST_WIDE_INT aarch64_and_split_imm2 (HOST_WIDE_INT val_in); bool aarch64_and_bitmask_imm (unsigned HOST_WIDE_INT val_in, machine_mode mode); int aarch64_branch_cost (bool, bool); enum aarch64_symbol_type aarch64_classify_symbolic_expression (rtx); +bool aarch64_can_const_movi_rtx_p (rtx x, machine_mode mode); bool aarch64_const_vec_all_same_int_p (rtx, HOST_WIDE_INT); bool aarch64_constant_address_p (rtx); bool aarch64_emit_approx_div (rtx, rtx, rtx); @@ -326,6 +327,7 @@ bool aarch64_emit_approx_sqrt (rtx, rtx, bool); void aarch64_expand_call (rtx, rtx, bool); bool aarch64_expand_movmem (rtx *); bool aarch64_float_const_zero_rtx_p (rtx); +bool aarch64_float_const_rtx_p (rtx); bool aarch64_function_arg_regno_p (unsigned); bool aarch64_fusion_enabled_p (enum aarch64_fusion_pairs); bool aarch64_gen_movmemqi (rtx *); @@ -351,9 +353,9 @@ bool aarch64_pad_arg_upward (machine_mode, const_tree); bool aarch64_pad_reg_upward (machine_mode, const_tree, bool); bool aarch64_regno_ok_for_base_p (int, bool); bool aarch64_regno_ok_for_index_p (int, bool); +bool aarch64_reinterpret_float_as_int (rtx value, unsigned HOST_WIDE_INT *fail); bool aarch64_simd_check_vect_par_cnst_half (rtx op, machine_mode mode, bool high); -bool aarch64_simd_imm_scalar_p (rtx x, machine_mode mode); bool aarch64_simd_imm_zero_p (rtx, machine_mode); bool aarch64_simd_scalar_immediate_valid_for_move (rtx, machine_mode); bool aarch64_simd_shift_imm_p (rtx, machine_mode, bool); diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index ebb1e73213d..f8b2f83e189 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -147,6 +147,8 @@ static bool aarch64_builtin_support_vector_misalignment (machine_mode mode, const_tree type, int misalignment, bool is_packed); +static machine_mode +aarch64_simd_container_mode (machine_mode mode, unsigned width); /* Major revision number of the ARM Architecture implemented by the target. */ unsigned aarch64_architecture_version; @@ -1876,6 +1878,31 @@ aarch64_internal_mov_immediate (rtx dest, rtx imm, bool generate, return 1; } + /* Check to see if the low 32 bits are either 0xffffXXXX or 0xXXXXffff + (with XXXX non-zero). In that case check to see if the move can be done in + a smaller mode. */ + val2 = val & 0xffffffff; + if (mode == DImode + && aarch64_move_imm (val2, SImode) + && (((val >> 32) & 0xffff) == 0 || (val >> 48) == 0)) + { + if (generate) + emit_insn (gen_rtx_SET (dest, GEN_INT (val2))); + + /* Check if we have to emit a second instruction by checking to see + if any of the upper 32 bits of the original DI mode value is set. */ + if (val == val2) + return 1; + + i = (val >> 48) ? 48 : 32; + + if (generate) + emit_insn (gen_insv_immdi (dest, GEN_INT (i), + GEN_INT ((val >> i) & 0xffff))); + + return 2; + } + if ((val >> 32) == 0 || mode == SImode) { if (generate) @@ -4723,6 +4750,74 @@ aarch64_legitimize_address_displacement (rtx *disp, rtx *off, machine_mode mode) return true; } +/* Return the binary representation of floating point constant VALUE in INTVAL. + If the value cannot be converted, return false without setting INTVAL. + The conversion is done in the given MODE. */ +bool +aarch64_reinterpret_float_as_int (rtx value, unsigned HOST_WIDE_INT *intval) +{ + + /* We make a general exception for 0. */ + if (aarch64_float_const_zero_rtx_p (value)) + { + *intval = 0; + return true; + } + + machine_mode mode = GET_MODE (value); + if (GET_CODE (value) != CONST_DOUBLE + || !SCALAR_FLOAT_MODE_P (mode) + || GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT + /* Only support up to DF mode. */ + || GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (DFmode)) + return false; + + unsigned HOST_WIDE_INT ival = 0; + + long res[2]; + real_to_target (res, + CONST_DOUBLE_REAL_VALUE (value), + REAL_MODE_FORMAT (mode)); + + if (mode == DFmode) + { + int order = BYTES_BIG_ENDIAN ? 1 : 0; + ival = zext_hwi (res[order], 32); + ival |= (zext_hwi (res[1 - order], 32) << 32); + } + else + ival = zext_hwi (res[0], 32); + + *intval = ival; + return true; +} + +/* Return TRUE if rtx X is an immediate constant that can be moved using a + single MOV(+MOVK) followed by an FMOV. */ +bool +aarch64_float_const_rtx_p (rtx x) +{ + machine_mode mode = GET_MODE (x); + if (mode == VOIDmode) + return false; + + /* Determine whether it's cheaper to write float constants as + mov/movk pairs over ldr/adrp pairs. */ + unsigned HOST_WIDE_INT ival; + + if (GET_CODE (x) == CONST_DOUBLE + && SCALAR_FLOAT_MODE_P (mode) + && aarch64_reinterpret_float_as_int (x, &ival)) + { + machine_mode imode = mode == HFmode ? SImode : int_mode_for_mode (mode); + int num_instr = aarch64_internal_mov_immediate + (NULL_RTX, gen_int_mode (ival, imode), false, imode); + return num_instr < 3; + } + + return false; +} + /* Return TRUE if rtx X is immediate constant 0.0 */ bool aarch64_float_const_zero_rtx_p (rtx x) @@ -4735,6 +4830,49 @@ aarch64_float_const_zero_rtx_p (rtx x) return real_equal (CONST_DOUBLE_REAL_VALUE (x), &dconst0); } +/* Return TRUE if rtx X is immediate constant that fits in a single + MOVI immediate operation. */ +bool +aarch64_can_const_movi_rtx_p (rtx x, machine_mode mode) +{ + if (!TARGET_SIMD) + return false; + + machine_mode vmode, imode; + unsigned HOST_WIDE_INT ival; + + if (GET_CODE (x) == CONST_DOUBLE + && SCALAR_FLOAT_MODE_P (mode)) + { + if (!aarch64_reinterpret_float_as_int (x, &ival)) + return false; + + /* We make a general exception for 0. */ + if (aarch64_float_const_zero_rtx_p (x)) + return true; + + imode = int_mode_for_mode (mode); + } + else if (GET_CODE (x) == CONST_INT + && SCALAR_INT_MODE_P (mode)) + { + imode = mode; + ival = INTVAL (x); + } + else + return false; + + /* use a 64 bit mode for everything except for DI/DF mode, where we use + a 128 bit vector mode. */ + int width = GET_MODE_BITSIZE (mode) == 64 ? 128 : 64; + + vmode = aarch64_simd_container_mode (imode, width); + rtx v_op = aarch64_simd_gen_const_vector_dup (vmode, ival); + + return aarch64_simd_valid_immediate (v_op, vmode, false, NULL); +} + + /* Return the fixed registers used for condition codes. */ static bool @@ -5914,12 +6052,6 @@ aarch64_preferred_reload_class (rtx x, reg_class_t regclass) return NO_REGS; } - /* If it's an integer immediate that MOVI can't handle, then - FP_REGS is not an option, so we return NO_REGS instead. */ - if (CONST_INT_P (x) && reg_class_subset_p (regclass, FP_REGS) - && !aarch64_simd_imm_scalar_p (x, GET_MODE (x))) - return NO_REGS; - /* Register eliminiation can result in a request for SP+constant->FP_REGS. We cannot support such operations which use SP as source and an FP_REG as destination, so reject out @@ -6869,6 +7001,25 @@ aarch64_rtx_costs (rtx x, machine_mode mode, int outer ATTRIBUTE_UNUSED, return true; case CONST_DOUBLE: + + /* First determine number of instructions to do the move + as an integer constant. */ + if (!aarch64_float_const_representable_p (x) + && !aarch64_can_const_movi_rtx_p (x, mode) + && aarch64_float_const_rtx_p (x)) + { + unsigned HOST_WIDE_INT ival; + bool succeed = aarch64_reinterpret_float_as_int (x, &ival); + gcc_assert (succeed); + + machine_mode imode = mode == HFmode ? SImode + : int_mode_for_mode (mode); + int ncost = aarch64_internal_mov_immediate + (NULL_RTX, gen_int_mode (ival, imode), false, imode); + *cost += COSTS_N_INSNS (ncost); + return true; + } + if (speed) { /* mov[df,sf]_aarch64. */ @@ -10191,18 +10342,16 @@ aarch64_legitimate_pic_operand_p (rtx x) /* Return true if X holds either a quarter-precision or floating-point +0.0 constant. */ static bool -aarch64_valid_floating_const (machine_mode mode, rtx x) +aarch64_valid_floating_const (rtx x) { if (!CONST_DOUBLE_P (x)) return false; - if (aarch64_float_const_zero_rtx_p (x)) + /* This call determines which constants can be used in mov<mode> + as integer moves instead of constant loads. */ + if (aarch64_float_const_rtx_p (x)) return true; - /* We only handle moving 0.0 to a TFmode register. */ - if (!(mode == SFmode || mode == DFmode)) - return false; - return aarch64_float_const_representable_p (x); } @@ -10214,11 +10363,15 @@ aarch64_legitimate_constant_p (machine_mode mode, rtx x) if (TARGET_SIMD && aarch64_vect_struct_mode_p (mode)) return false; - /* This could probably go away because - we now decompose CONST_INTs according to expand_mov_immediate. */ + /* For these cases we never want to use a literal load. + As such we have to prevent the compiler from forcing these + to memory. */ if ((GET_CODE (x) == CONST_VECTOR && aarch64_simd_valid_immediate (x, mode, false, NULL)) - || CONST_INT_P (x) || aarch64_valid_floating_const (mode, x)) + || CONST_INT_P (x) + || aarch64_valid_floating_const (x) + || aarch64_can_const_movi_rtx_p (x, mode) + || aarch64_float_const_rtx_p (x)) return !targetm.cannot_force_const_mem (mode, x); if (GET_CODE (x) == HIGH @@ -11496,23 +11649,6 @@ aarch64_mask_from_zextract_ops (rtx width, rtx pos) } bool -aarch64_simd_imm_scalar_p (rtx x, machine_mode mode ATTRIBUTE_UNUSED) -{ - HOST_WIDE_INT imm = INTVAL (x); - int i; - - for (i = 0; i < 8; i++) - { - unsigned int byte = imm & 0xff; - if (byte != 0xff && byte != 0) - return false; - imm >>= 8; - } - - return true; -} - -bool aarch64_mov_operand_p (rtx x, machine_mode mode) { if (GET_CODE (x) == HIGH @@ -12905,15 +13041,28 @@ aarch64_output_simd_mov_immediate (rtx const_vector, } char* -aarch64_output_scalar_simd_mov_immediate (rtx immediate, - machine_mode mode) +aarch64_output_scalar_simd_mov_immediate (rtx immediate, machine_mode mode) { + + /* If a floating point number was passed and we desire to use it in an + integer mode do the conversion to integer. */ + if (CONST_DOUBLE_P (immediate) && GET_MODE_CLASS (mode) == MODE_INT) + { + unsigned HOST_WIDE_INT ival; + if (!aarch64_reinterpret_float_as_int (immediate, &ival)) + gcc_unreachable (); + immediate = gen_int_mode (ival, mode); + } + machine_mode vmode; + /* use a 64 bit mode for everything except for DI/DF mode, where we use + a 128 bit vector mode. */ + int width = GET_MODE_BITSIZE (mode) == 64 ? 128 : 64; gcc_assert (!VECTOR_MODE_P (mode)); - vmode = aarch64_simd_container_mode (mode, 64); + vmode = aarch64_simd_container_mode (mode, width); rtx v_op = aarch64_simd_gen_const_vector_dup (vmode, INTVAL (immediate)); - return aarch64_output_simd_mov_immediate (v_op, vmode, 64); + return aarch64_output_simd_mov_immediate (v_op, vmode, width); } /* Split operands into moves from op[1] + op[2] into op[0]. */ diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 12f29ada904..e17d9e9645b 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -181,6 +181,11 @@ ;; will be disabled when !TARGET_FLOAT. (define_attr "fp" "no,yes" (const_string "no")) +;; Attribute that specifies whether or not the instruction touches half +;; precision fp registers. When this is set to yes for an alternative, +;; that alternative will be disabled when !TARGET_FP_F16INST. +(define_attr "fp16" "no,yes" (const_string "no")) + ;; Attribute that specifies whether or not the instruction touches simd ;; registers. When this is set to yes for an alternative, that alternative ;; will be disabled when !TARGET_SIMD. @@ -194,11 +199,14 @@ ;; registers when -mgeneral-regs-only is specified. (define_attr "enabled" "no,yes" (cond [(ior - (and (eq_attr "fp" "yes") - (eq (symbol_ref "TARGET_FLOAT") (const_int 0))) - (and (eq_attr "simd" "yes") - (eq (symbol_ref "TARGET_SIMD") (const_int 0)))) - (const_string "no") + (ior + (and (eq_attr "fp" "yes") + (eq (symbol_ref "TARGET_FLOAT") (const_int 0))) + (and (eq_attr "simd" "yes") + (eq (symbol_ref "TARGET_SIMD") (const_int 0)))) + (and (eq_attr "fp16" "yes") + (eq (symbol_ref "TARGET_FP_F16INST") (const_int 0)))) + (const_string "no") ] (const_string "yes"))) ;; Attribute that specifies whether we are dealing with a branch to a @@ -920,8 +928,8 @@ ) (define_insn_and_split "*movsi_aarch64" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m, m,r,r ,*w,r,*w") - (match_operand:SI 1 "aarch64_mov_operand" " r,r,k,M,n,m, m,rZ,*w,Usa,Ush,rZ,w,*w"))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m, m,r,r ,*w, r,*w,w") + (match_operand:SI 1 "aarch64_mov_operand" " r,r,k,M,n,m, m,rZ,*w,Usa,Ush,rZ,w,*w,Ds"))] "(register_operand (operands[0], SImode) || aarch64_reg_or_zero (operands[1], SImode))" "@ @@ -938,8 +946,9 @@ adrp\\t%x0, %A1 fmov\\t%s0, %w1 fmov\\t%w0, %s1 - fmov\\t%s0, %s1" - "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode) + fmov\\t%s0, %s1 + * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);" + "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode) && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))" [(const_int 0)] "{ @@ -947,13 +956,14 @@ DONE; }" [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\ - adr,adr,f_mcr,f_mrc,fmov") - (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes")] + adr,adr,f_mcr,f_mrc,fmov,neon_move") + (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*") + (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")] ) (define_insn_and_split "*movdi_aarch64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m, m,r,r, *w,r,*w,w") - (match_operand:DI 1 "aarch64_mov_operand" " r,r,k,N,n,m, m,rZ,*w,Usa,Ush,rZ,w,*w,Dd"))] + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,r,*w,m, m,r,r, *w,r,*w,w") + (match_operand:DI 1 "aarch64_mov_operand" " r,r,k,N,M,n,m, m,rZ,*w,Usa,Ush,rZ,w,*w,Dd"))] "(register_operand (operands[0], DImode) || aarch64_reg_or_zero (operands[1], DImode))" "@ @@ -961,6 +971,7 @@ mov\\t%0, %x1 mov\\t%x0, %1 mov\\t%x0, %1 + mov\\t%w0, %1 # ldr\\t%x0, %1 ldr\\t%d0, %1 @@ -971,7 +982,7 @@ fmov\\t%d0, %x1 fmov\\t%x0, %d1 fmov\\t%d0, %d1 - movi\\t%d0, %1" + * return aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);" "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode)) && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))" [(const_int 0)] @@ -979,10 +990,10 @@ aarch64_expand_mov_immediate (operands[0], operands[1]); DONE; }" - [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\ - adr,adr,f_mcr,f_mrc,fmov,neon_move") - (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*") - (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")] + [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,load1,\ + load1,store1,store1,adr,adr,f_mcr,f_mrc,fmov,neon_move") + (set_attr "fp" "*,*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*") + (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")] ) (define_insn "insv_imm<mode>" @@ -1062,28 +1073,31 @@ ) (define_insn "*movhf_aarch64" - [(set (match_operand:HF 0 "nonimmediate_operand" "=w,w ,?r,w,w,m,r,m ,r") - (match_operand:HF 1 "general_operand" "Y ,?rY, w,w,m,w,m,rY,r"))] + [(set (match_operand:HF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w ,w,m,r,m ,r") + (match_operand:HF 1 "general_operand" "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r"))] "TARGET_FLOAT && (register_operand (operands[0], HFmode) || aarch64_reg_or_fp_zero (operands[1], HFmode))" "@ movi\\t%0.4h, #0 - mov\\t%0.h[0], %w1 + fmov\\t%h0, %w1 umov\\t%w0, %1.h[0] mov\\t%0.h[0], %1.h[0] + fmov\\t%h0, %1 + * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode); ldr\\t%h0, %1 str\\t%h1, %0 ldrh\\t%w0, %1 strh\\t%w1, %0 mov\\t%w0, %w1" - [(set_attr "type" "neon_move,neon_from_gp,neon_to_gp,neon_move,\ - f_loads,f_stores,load1,store1,mov_reg") - (set_attr "simd" "yes,yes,yes,yes,*,*,*,*,*")] + [(set_attr "type" "neon_move,f_mcr,neon_to_gp,neon_move,fconsts, \ + neon_move,f_loads,f_stores,load1,store1,mov_reg") + (set_attr "simd" "yes,*,yes,yes,*,yes,*,*,*,*,*") + (set_attr "fp16" "*,yes,*,*,yes,*,*,*,*,*,*")] ) (define_insn "*movsf_aarch64" - [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w,m,r,m ,r") - (match_operand:SF 1 "general_operand" "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))] + [(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))" "@ @@ -1092,19 +1106,22 @@ fmov\\t%w0, %s1 fmov\\t%s0, %s1 fmov\\t%s0, %1 + * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode); ldr\\t%s0, %1 str\\t%s1, %0 ldr\\t%w0, %1 str\\t%w1, %0 - mov\\t%w0, %w1" - [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,\ - f_loads,f_stores,load1,store1,mov_reg") - (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")] + mov\\t%w0, %w1 + mov\\t%w0, %1" + [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,neon_move,\ + f_loads,f_stores,load1,store1,mov_reg,\ + fconsts") + (set_attr "simd" "yes,*,*,*,*,yes,*,*,*,*,*,*")] ) (define_insn "*movdf_aarch64" - [(set (match_operand:DF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w,m,r,m ,r") - (match_operand:DF 1 "general_operand" "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))] + [(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))" "@ @@ -1113,14 +1130,37 @@ fmov\\t%x0, %d1 fmov\\t%d0, %d1 fmov\\t%d0, %1 + * return aarch64_output_scalar_simd_mov_immediate (operands[1], DImode); ldr\\t%d0, %1 str\\t%d1, %0 ldr\\t%x0, %1 str\\t%x1, %0 - mov\\t%x0, %x1" - [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,\ - f_loadd,f_stored,load1,store1,mov_reg") - (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")] + mov\\t%x0, %x1 + mov\\t%x0, %1" + [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,neon_move,\ + f_loadd,f_stored,load1,store1,mov_reg,\ + fconstd") + (set_attr "simd" "yes,*,*,*,*,yes,*,*,*,*,*,*")] +) + +(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" diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md index 88e840f2898..9ce3d4efaf3 100644 --- a/gcc/config/aarch64/constraints.md +++ b/gcc/config/aarch64/constraints.md @@ -176,6 +176,12 @@ (and (match_code "const_double") (match_test "aarch64_float_const_representable_p (op)"))) +(define_constraint "Uvi" + "A floating point constant which can be used with a\ + MOVI immediate operation." + (and (match_code "const_double") + (match_test "aarch64_can_const_movi_rtx_p (op, GET_MODE (op))"))) + (define_constraint "Dn" "@internal A constraint that matches vector of immediates." @@ -220,9 +226,17 @@ (define_constraint "Dd" "@internal - A constraint that matches an immediate operand valid for AdvSIMD scalar." + A constraint that matches an integer immediate operand valid\ + for AdvSIMD scalar operations in DImode." + (and (match_code "const_int") + (match_test "aarch64_can_const_movi_rtx_p (op, DImode)"))) + +(define_constraint "Ds" + "@internal + A constraint that matches an integer immediate operand valid\ + for AdvSIMD scalar operations in SImode." (and (match_code "const_int") - (match_test "aarch64_simd_imm_scalar_p (op, GET_MODE (op))"))) + (match_test "aarch64_can_const_movi_rtx_p (op, SImode)"))) (define_address_constraint "Dp" "@internal diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md index 43be7fd3611..067cef78533 100644 --- a/gcc/config/aarch64/iterators.md +++ b/gcc/config/aarch64/iterators.md @@ -44,6 +44,9 @@ ;; Iterator for all scalar floating point modes (HF, SF, DF) (define_mode_iterator GPF_F16 [(HF "AARCH64_ISA_F16") SF DF]) +;; Iterator for all scalar floating point modes (HF, SF, DF) +(define_mode_iterator GPF_HF [HF SF DF]) + ;; Iterator for all scalar floating point modes (HF, SF, DF and TF) (define_mode_iterator GPF_TF_F16 [HF SF DF TF]) diff --git a/gcc/testsuite/gcc.target/aarch64/dbl_mov_immediate_1.c b/gcc/testsuite/gcc.target/aarch64/dbl_mov_immediate_1.c new file mode 100644 index 00000000000..ba6a230457b --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/dbl_mov_immediate_1.c @@ -0,0 +1,53 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -mno-pc-relative-literal-loads" } */ +/* { dg-skip-if "Tiny model won't generate adrp" { *-*-* } { "-mcmodel=tiny" } { "" } } */ + +double d0(void) +{ + double x = 0.0d; + return x; +} + +double dn1(void) +{ + double x = -0.0d; + return x; +} + + +double d1(void) +{ + double x = 1.5d; + return x; +} + +double d2(void) +{ + double x = 123256.0d; + return x; +} + +double d3(void) +{ + double x = 123256123456.0d; + return x; +} + +double d4(void) +{ + double x = 123456123456123456.0d; + return x; +} + +/* { 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 } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_1.c b/gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_1.c new file mode 100644 index 00000000000..1ed3831e139 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_1.c @@ -0,0 +1,49 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ +/* { dg-require-effective-target arm_v8_2a_fp16_scalar_ok } */ +/* { dg-add-options arm_v8_2a_fp16_scalar } */ + +extern __fp16 foo (); +extern void bar (__fp16* x); + +void f1 () +{ + volatile __fp16 a = 17.0; +} + + +void f2 (__fp16 *a) +{ + *a = 17.0; +} + +void f3 () +{ + __fp16 b = foo (); + b = 17.0; + bar (&b); +} + +__fp16 f4 () +{ + __fp16 a = 0; + __fp16 b = 1; + __fp16 c = 2; + __fp16 d = 4; + + __fp16 z = a + b; + z = z + c; + z = z - d; + return z; +} + +__fp16 f5 () +{ + __fp16 a = 16; + bar (&a); + return a; +} + +/* { dg-final { scan-assembler-times "mov\tw\[0-9\]+, #?19520" 3 } } */ +/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.2s, 0xbc, lsl 8" 1 } } */ +/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.2s, 0x4c, lsl 8" 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_2.c b/gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_2.c new file mode 100644 index 00000000000..6f44821e9d0 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_2.c @@ -0,0 +1,45 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ +/* { dg-require-effective-target arm_v8_2a_fp16_scalar_ok } */ +/* { dg-add-options arm_v8_2a_fp16_scalar } */ + +#include <arm_fp16.h> + +float16_t f0(void) +{ + float16_t x = 0.0f; + return x; +} + +float16_t fn1(void) +{ + float16_t x = -0.0f; + return x; +} + +float16_t f1(void) +{ + float16_t x = 256.0f; + return x; +} + +float16_t f2(void) +{ + float16_t x = 123256.0f; + return x; +} + +float16_t f3(void) +{ + float16_t x = 17.0; + return x; +} + +/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.4h, ?#0" 1 } } */ +/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.2s, 0x80, lsl 8" 1 } } */ +/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.2s, 0x5c, lsl 8" 1 } } */ +/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.2s, 0x7c, lsl 8" 1 } } */ + +/* { dg-final { scan-assembler-times "mov\tw\[0-9\]+, 19520" 1 } } */ +/* { dg-final { scan-assembler-times "fmov\th\[0-9\], w\[0-9\]+" 1 } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/flt_mov_immediate_1.c b/gcc/testsuite/gcc.target/aarch64/flt_mov_immediate_1.c new file mode 100644 index 00000000000..7b92a5ae40f --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/flt_mov_immediate_1.c @@ -0,0 +1,52 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + +float f0(void) +{ + float x = 0.0f; + return x; +} + +float fn1(void) +{ + float x = -0.0f; + return x; +} + +float f1(void) +{ + float x = 256.0f; + return x; +} + +float f2(void) +{ + float x = 123256.0f; + return x; +} + +float f3(void) +{ + float x = 2.0f; + return x; +} + +float f4(void) +{ + float x = -20000.1; + return x; +} + + +/* { 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 } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/int_mov_immediate_1.c b/gcc/testsuite/gcc.target/aarch64/int_mov_immediate_1.c new file mode 100644 index 00000000000..6ac9065037f --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/int_mov_immediate_1.c @@ -0,0 +1,59 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target lp64 } */ +/* { dg-options "-O3" } */ + +long long f1(void) +{ + return 0xffff6666; +} + +int f3(void) +{ + return 0xffff6666; +} + + +long f2(void) +{ + return 0x11110000ffff6666; +} + +long f4(void) +{ + return 0x11110001ffff6666; +} + +long f5(void) +{ + return 0x111100001ff6666; +} + +long f6(void) +{ + return 0x00001111ffff6666; +} + +long f7(void) +{ + return 0x000011116666ffff; +} + +long f8(void) +{ + return 0x0f0011116666ffff; +} + +/* { dg-final { scan-assembler-times "mov\tw\[0-9\]+, -39322" 1 } } */ +/* { dg-final { scan-assembler-times "mov\tw\[0-9\]+, 4294927974" 3 } } */ +/* { dg-final { scan-assembler-times "mov\tw\[0-9\]+, 1718026239" 1 } } */ +/* { dg-final { scan-assembler-times "mov\tx\[0-9\]+, -2576941057" 1 } } */ +/* { dg-final { scan-assembler-times "mov\tx\[0-9\]+, -39322" 1 } } */ +/* { dg-final { scan-assembler-times "mov\tx\[0-9\]+, 26214" 1 } } */ +/* { dg-final { scan-assembler-times "movk\tx\[0-9\]+, 0xf00, lsl 48" 1 } } */ +/* { dg-final { scan-assembler-times "movk\tx\[0-9\]+, 0x1111, lsl 48" 2 } } */ +/* { dg-final { scan-assembler-times "movk\tx\[0-9\]+, 0x1000, lsl 32" 1 } } */ +/* { dg-final { scan-assembler-times "movk\tx\[0-9\]+, 0x1111, lsl 32" 3 } } */ +/* { dg-final { scan-assembler-times "movk\tx\[0-9\]+, 0x111, lsl 48" 1 } } */ +/* { dg-final { scan-assembler-times "movk\tx\[0-9\]+, 0x1ff, lsl 16" 1 } } */ +/* { dg-final { scan-assembler-times "movk\tx\[0-9\]+, 0x1, lsl 32" 1 } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/pr63304_1.c b/gcc/testsuite/gcc.target/aarch64/pr63304_1.c index c917f81c022..114d8c1a6c3 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr63304_1.c +++ b/gcc/testsuite/gcc.target/aarch64/pr63304_1.c @@ -4,10 +4,10 @@ #pragma GCC target ("+nothing+simd, cmodel=small") int -cal (float a) +cal (double a) { - float b = 1.2; - float c = 2.2; + double b = 3.2; + double c = 2.2; if ((a + b) != c) return 0; else @@ -19,11 +19,11 @@ cal (float a) #pragma GCC target ("cmodel=large") int -cal2 (float a) +cal2 (double a) { - float b = 1.2; - float c = 2.2; + double b = 3.2; + double c = 2.2; if ((a + b) != c) return 0; else @@ -33,11 +33,11 @@ cal2 (float a) #pragma GCC pop_options int -cal3 (float a) +cal3 (double a) { - float b = 1.2; - float c = 2.2; + double b = 3.2; + double c = 2.2; if ((a + b) != c) return 0; else |