diff options
author | Sofiane Naci <sofiane.naci@arm.com> | 2013-05-07 12:47:18 +0000 |
---|---|---|
committer | Sofiane Naci <sofiane@gcc.gnu.org> | 2013-05-07 12:47:18 +0000 |
commit | fd4842cd6793508d4cdf630ef8a3e406cff7b895 (patch) | |
tree | c6f19882066d21f8fb6c6cf9bbad1c36f01542c2 /gcc | |
parent | a7a7d10ed53c07e1ccfa6716c5bbc1dfd8bc05f9 (diff) | |
download | gcc-fd4842cd6793508d4cdf630ef8a3e406cff7b895.zip gcc-fd4842cd6793508d4cdf630ef8a3e406cff7b895.tar.gz gcc-fd4842cd6793508d4cdf630ef8a3e406cff7b895.tar.bz2 |
aarch64-simd.md (*aarch64_simd_mov<mode>): call splitter.
gcc/
* config/aarch64/aarch64-simd.md (*aarch64_simd_mov<mode>): call splitter.
(aarch64_simd_mov<mode>): New expander.
(aarch64_simd_mov_to_<mode>low): New instruction pattern.
(aarch64_simd_mov_to_<mode>high): Likewise.
(aarch64_simd_mov_from_<mode>low): Likewise.
(aarch64_simd_mov_from_<mode>high): Likewise.
(aarch64_dup_lane<mode>): Update.
(aarch64_dup_lanedi): New instruction pattern.
* config/aarch64/aarch64-protos.h (aarch64_split_simd_move): New prototype.
* config/aarch64/aarch64.c (aarch64_split_simd_move): New function.
testsuites/
* gcc.target/aarch64/scalar_intrinsics.c: Update.
From-SVN: r198680
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64-simd.md | 118 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.c | 41 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c | 2 |
6 files changed, 176 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c62833d..98e76ce 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2013-05-07 Sofiane Naci <sofiane.naci@arm.com> + + * config/aarch64/aarch64-simd.md (*aarch64_simd_mov<mode>): call splitter. + (aarch64_simd_mov<mode>): New expander. + (aarch64_simd_mov_to_<mode>low): New instruction pattern. + (aarch64_simd_mov_to_<mode>high): Likewise. + (aarch64_simd_mov_from_<mode>low): Likewise. + (aarch64_simd_mov_from_<mode>high): Likewise. + (aarch64_dup_lane<mode>): Update. + (aarch64_dup_lanedi): New instruction pattern. + * config/aarch64/aarch64-protos.h (aarch64_split_simd_move): New prototype. + * config/aarch64/aarch64.c (aarch64_split_simd_move): New function. + 2013-05-07 Bill Schmidt <wschmidt@linux.vnet.ibm.com> * gimple-ssa-strength-reduction.c (lazy_create_slsr_reg): Remove. diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index c09b227..001842e 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -219,6 +219,8 @@ void aarch64_split_128bit_move (rtx, rtx); bool aarch64_split_128bit_move_p (rtx, rtx); +void aarch64_split_simd_move (rtx, rtx); + /* Check for a legitimate floating point constant for FMOV. */ bool aarch64_float_const_representable_p (rtx); diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index 42320d4..5626b55 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -358,7 +358,7 @@ ) (define_insn "aarch64_dup_lane<mode>" - [(set (match_operand:SDQ_I 0 "register_operand" "=w") + [(set (match_operand:ALLX 0 "register_operand" "=w") (vec_select:<VEL> (match_operand:<VCON> 1 "register_operand" "w") (parallel [(match_operand:SI 2 "immediate_operand" "i")]) @@ -369,6 +369,19 @@ (set_attr "simd_mode" "<MODE>")] ) +(define_insn "aarch64_dup_lanedi" + [(set (match_operand:DI 0 "register_operand" "=w,r") + (vec_select:DI + (match_operand:V2DI 1 "register_operand" "w,w") + (parallel [(match_operand:SI 2 "immediate_operand" "i,i")])))] + "TARGET_SIMD" + "@ + dup\\t%<v>0<Vmtype>, %1.<Vetype>[%2] + umov\t%0, %1.d[%2]" + [(set_attr "simd_type" "simd_dup") + (set_attr "simd_mode" "DI")] +) + (define_insn "aarch64_simd_dup<mode>" [(set (match_operand:VDQF 0 "register_operand" "=w") (vec_duplicate:VDQF (match_operand:<VEL> 1 "register_operand" "w")))] @@ -419,8 +432,8 @@ case 0: return "ld1\t{%0.<Vtype>}, %1"; case 1: return "st1\t{%1.<Vtype>}, %0"; case 2: return "orr\t%0.<Vbtype>, %1.<Vbtype>, %1.<Vbtype>"; - case 3: return "umov\t%0, %1.d[0]\;umov\t%H0, %1.d[1]"; - case 4: return "ins\t%0.d[0], %1\;ins\t%0.d[1], %H1"; + case 3: return "#"; + case 4: return "#"; case 5: return "#"; case 6: return aarch64_output_simd_mov_immediate (&operands[1], @@ -454,6 +467,105 @@ aarch64_simd_disambiguate_copy (operands, dest, src, 2); }) +(define_split + [(set (match_operand:VQ 0 "register_operand" "") + (match_operand:VQ 1 "register_operand" ""))] + "TARGET_SIMD && reload_completed + && ((FP_REGNUM_P (REGNO (operands[0])) && GP_REGNUM_P (REGNO (operands[1]))) + || (GP_REGNUM_P (REGNO (operands[0])) && FP_REGNUM_P (REGNO (operands[1]))))" + [(const_int 0)] +{ + aarch64_split_simd_move (operands[0], operands[1]); + DONE; +}) + +(define_expand "aarch64_simd_mov<mode>" + [(set (match_operand:VQ 0) + (match_operand:VQ 1))] + "TARGET_SIMD" + { + rtx dst = operands[0]; + rtx src = operands[1]; + + if (GP_REGNUM_P (REGNO (src))) + { + rtx low_part = gen_lowpart (<VHALF>mode, src); + rtx high_part = gen_highpart (<VHALF>mode, src); + + emit_insn + (gen_aarch64_simd_mov_to_<mode>low (dst, low_part)); + emit_insn + (gen_aarch64_simd_mov_to_<mode>high (dst, high_part)); + } + + else + { + rtx low_half = aarch64_simd_vect_par_cnst_half (<MODE>mode, false); + rtx high_half = aarch64_simd_vect_par_cnst_half (<MODE>mode, true); + rtx low_part = gen_lowpart (<VHALF>mode, dst); + rtx high_part = gen_highpart (<VHALF>mode, dst); + + emit_insn + (gen_aarch64_simd_mov_from_<mode>low (low_part, src, low_half)); + emit_insn + (gen_aarch64_simd_mov_from_<mode>high (high_part, src, high_half)); + } + DONE; + } +) + +(define_insn "aarch64_simd_mov_to_<mode>low" + [(set (zero_extract:VQ + (match_operand:VQ 0 "register_operand" "+w") + (const_int 64) (const_int 0)) + (vec_concat:VQ + (match_operand:<VHALF> 1 "register_operand" "r") + (vec_duplicate:<VHALF> (const_int 0))))] + "TARGET_SIMD && reload_completed" + "ins\t%0.d[0], %1" + [(set_attr "simd_type" "simd_move") + (set_attr "simd_mode" "<MODE>") + (set_attr "length" "4") + ]) + +(define_insn "aarch64_simd_mov_to_<mode>high" + [(set (zero_extract:VQ + (match_operand:VQ 0 "register_operand" "+w") + (const_int 64) (const_int 64)) + (vec_concat:VQ + (match_operand:<VHALF> 1 "register_operand" "r") + (vec_duplicate:<VHALF> (const_int 0))))] + "TARGET_SIMD && reload_completed" + "ins\t%0.d[1], %1" + [(set_attr "simd_type" "simd_move") + (set_attr "simd_mode" "<MODE>") + (set_attr "length" "4") + ]) + +(define_insn "aarch64_simd_mov_from_<mode>low" + [(set (match_operand:<VHALF> 0 "register_operand" "=r") + (vec_select:<VHALF> + (match_operand:VQ 1 "register_operand" "w") + (match_operand:VQ 2 "vect_par_cnst_lo_half" "")))] + "TARGET_SIMD && reload_completed" + "umov\t%0, %1.d[0]" + [(set_attr "simd_type" "simd_move") + (set_attr "simd_mode" "<MODE>") + (set_attr "length" "4") + ]) + +(define_insn "aarch64_simd_mov_from_<mode>high" + [(set (match_operand:<VHALF> 0 "register_operand" "=r") + (vec_select:<VHALF> + (match_operand:VQ 1 "register_operand" "w") + (match_operand:VQ 2 "vect_par_cnst_hi_half" "")))] + "TARGET_SIMD && reload_completed" + "umov\t%0, %1.d[1]" + [(set_attr "simd_type" "simd_move") + (set_attr "simd_mode" "<MODE>") + (set_attr "length" "4") + ]) + (define_insn "orn<mode>3" [(set (match_operand:VDQ 0 "register_operand" "=w") (ior:VDQ (not:VDQ (match_operand:VDQ 1 "register_operand" "w")) diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index d2a495d..d32563d 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -656,6 +656,47 @@ aarch64_split_128bit_move_p (rtx dst, rtx src) || ! (FP_REGNUM_P (REGNO (dst)) && FP_REGNUM_P (REGNO (src)))); } +/* Split a complex SIMD move. */ + +void +aarch64_split_simd_move (rtx dst, rtx src) +{ + enum machine_mode src_mode = GET_MODE (src); + enum machine_mode dst_mode = GET_MODE (dst); + + gcc_assert (VECTOR_MODE_P (dst_mode)); + + if (REG_P (dst) && REG_P (src)) + { + gcc_assert (VECTOR_MODE_P (src_mode)); + + switch (src_mode) + { + case V16QImode: + emit_insn (gen_aarch64_simd_movv16qi (dst, src)); + break; + case V8HImode: + emit_insn (gen_aarch64_simd_movv8hi (dst, src)); + break; + case V4SImode: + emit_insn (gen_aarch64_simd_movv4si (dst, src)); + break; + case V2DImode: + emit_insn (gen_aarch64_simd_movv2di (dst, src)); + break; + case V4SFmode: + emit_insn (gen_aarch64_simd_movv4sf (dst, src)); + break; + case V2DFmode: + emit_insn (gen_aarch64_simd_movv2df (dst, src)); + break; + default: + gcc_unreachable (); + } + return; + } +} + static rtx aarch64_force_temporary (rtx x, rtx value) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d7c5046..2351411 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2013-05-07 Sofiane Naci <sofiane.naci@arm.com> + + * gcc.target/aarch64/scalar_intrinsics.c: Update. + 2013-05-07 Richard Biener <rguenther@suse.de> PR middle-end/57190 diff --git a/gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c b/gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c index e984b8e..7427c62 100644 --- a/gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c +++ b/gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c @@ -223,7 +223,7 @@ test_vdups_lane_u32 (uint32x4_t a) return vdups_lane_u32 (a, 2); } -/* { dg-final { scan-assembler-times "\\tdup\\td\[0-9\]+, v\[0-9\]+\.d" 2 } } */ +/* { dg-final { scan-assembler-times "\\tumov\\tx\[0-9\]+, v\[0-9\]+\.d" 2 } } */ int64x1_t test_vdupd_lane_s64 (int64x2_t a) |