aarch64-simd.md (*aarch64_simd_mov<mode>): call splitter.
authorSofiane Naci <sofiane.naci@arm.com>
Tue, 7 May 2013 12:47:18 +0000 (12:47 +0000)
committerSofiane Naci <sofiane@gcc.gnu.org>
Tue, 7 May 2013 12:47:18 +0000 (12:47 +0000)
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

gcc/ChangeLog
gcc/config/aarch64/aarch64-protos.h
gcc/config/aarch64/aarch64-simd.md
gcc/config/aarch64/aarch64.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c

index c62833d0e2471f5b5161cc57815d786e93bbfdf5..98e76ce27af4a6d764d38044ac76fac13f90d364 100644 (file)
@@ -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.
index c09b227f85a4ab03fd0c65b73d934eb5e67b1af6..001842e43b4cdb166f0b13fc0f74cec1f6f0e2f8 100644 (file)
@@ -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);
 
index 42320d4e06f50063201290e3f47402b9484c3cbe..5626b55ede5d21d4d8bf7784c18e37dace00260c 100644 (file)
 )
 
 (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")])
    (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")))]
     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],
   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"))
index d2a495dbc626bd3118c52980544157b4c8dfd5b4..d32563d3e738185f04ce9101d624591756adc23c 100644 (file)
@@ -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)
 {
index d7c5046e67ef9db01c1d0a9cc5640b85ec86af33..2351411254bcb1676def3dce6273324efef780ac 100644 (file)
@@ -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
index e984b8ec339a6a955e58c613e48575b995b60ac7..7427c6217f8ba5a4b87be71748433a2cb6d1e3e4 100644 (file)
@@ -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)