Index: ChangeLog
===================================================================
--- ChangeLog	(revision 198706)
+++ ChangeLog	(working copy)
@@ -1,3 +1,15 @@
+2013-05-08  Sofiane Naci  <sofiane.naci@arm.com>
+
+	* config/aarch64/aarch64-simd.md (aarch64_simd_mov_to_<mode>low): Add w<-w
+	alternative.
+	(aarch64_simd_mov_to_<mode>high): Likewise.
+	(aarch64_combine<mode>): covert to split.
+	(aarch64_simd_combine<mode>): New instruction expansion.
+	* config/aarch64/aarch64-protos.h (aarch64_split_simd_combine): New
+	function prototype.
+	* config/aarch64/aarch64.c (aarch64_split_simd_combine): New function.
+	* config/aarch64/iterators.md (Vdbl): Add entry for DF.
+
 2013-05-08  Paolo Carlini  <paolo.carlini@oracle.com>
 
 	PR tree-optimization/57200
Index: config/aarch64/aarch64-simd.md
===================================================================
--- config/aarch64/aarch64-simd.md	(revision 198706)
+++ config/aarch64/aarch64-simd.md	(working copy)
@@ -516,28 +516,32 @@
 
 (define_insn "aarch64_simd_mov_to_<mode>low"
   [(set (zero_extract:VQ
-          (match_operand:VQ 0 "register_operand" "+w")
+          (match_operand:VQ 0 "register_operand" "+w,w")
           (const_int 64) (const_int 0))
         (vec_concat:VQ
-          (match_operand:<VHALF> 1 "register_operand" "r")
+          (match_operand:<VHALF> 1 "register_operand" "r,w")
           (vec_duplicate:<VHALF> (const_int 0))))]
   "TARGET_SIMD && reload_completed"
-  "ins\t%0.d[0], %1"
-  [(set_attr "simd_type" "simd_move")
+  "@
+   ins\t%0.d[0], %1
+   dup\t%d0, %1.d[0]"
+  [(set_attr "simd_type" "simd_move,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")
+          (match_operand:VQ 0 "register_operand" "+w,w")
           (const_int 64) (const_int 64))
         (vec_concat:VQ
-          (match_operand:<VHALF> 1 "register_operand" "r")
+          (match_operand:<VHALF> 1 "register_operand" "r,w")
           (vec_duplicate:<VHALF> (const_int 0))))]
   "TARGET_SIMD && reload_completed"
-  "ins\t%0.d[1], %1"
-  [(set_attr "simd_type" "simd_move")
+  "@
+   ins\t%0.d[1], %1
+   ins\t%0.d[1], %1.d[0]"
+  [(set_attr "simd_type" "simd_move,simd_move")
    (set_attr "simd_mode" "<MODE>")
    (set_attr "length" "4")
   ])
@@ -2223,15 +2227,29 @@
    (set_attr "simd_mode" "<MODE>")]
 )
 
-(define_insn "aarch64_combine<mode>"
+(define_insn_and_split "aarch64_combine<mode>"
   [(set (match_operand:<VDBL> 0 "register_operand" "=&w")
         (vec_concat:<VDBL> (match_operand:VDC 1 "register_operand" "w")
 			   (match_operand:VDC 2 "register_operand" "w")))]
   "TARGET_SIMD"
-  "mov\\t%0.d[0], %1.d[0]\;ins\\t%0.d[1], %2.d[0]"
-  [(set_attr "simd_type" "simd_ins")
-   (set_attr "simd_mode" "<MODE>")]
-)
+  "#"
+  "&& reload_completed"
+  [(const_int 0)]
+{
+  aarch64_split_simd_combine (operands[0], operands[1], operands[2]);
+  DONE;
+})
+
+(define_expand "aarch64_simd_combine<mode>"
+  [(set (match_operand:<VDBL> 0 "register_operand" "=&w")
+        (vec_concat:<VDBL> (match_operand:VDC 1 "register_operand" "w")
+  (match_operand:VDC 2 "register_operand" "w")))]
+  "TARGET_SIMD"
+  {
+    emit_insn (gen_aarch64_simd_mov_to_<Vdbl>low (operands[0], operands[1]));
+    emit_insn (gen_aarch64_simd_mov_to_<Vdbl>high (operands[0], operands[2]));
+    DONE;
+  })
 
 ;; <su><addsub>l<q>.
 
Index: config/aarch64/aarch64-protos.h
===================================================================
--- config/aarch64/aarch64-protos.h	(revision 198706)
+++ config/aarch64/aarch64-protos.h	(working copy)
@@ -219,6 +219,8 @@ void aarch64_split_128bit_move (rtx, rtx
 
 bool aarch64_split_128bit_move_p (rtx, rtx);
 
+void aarch64_split_simd_combine (rtx, rtx, rtx);
+
 void aarch64_split_simd_move (rtx, rtx);
 
 /* Check for a legitimate floating point constant for FMOV.  */
Index: config/aarch64/aarch64.c
===================================================================
--- config/aarch64/aarch64.c	(revision 198706)
+++ config/aarch64/aarch64.c	(working copy)
@@ -656,6 +656,45 @@ aarch64_split_128bit_move_p (rtx dst, rt
 	  || ! (FP_REGNUM_P (REGNO (dst)) && FP_REGNUM_P (REGNO (src))));
 }
 
+/* Split a complex SIMD combine.  */
+
+void
+aarch64_split_simd_combine (rtx dst, rtx src1, rtx src2)
+{
+  enum machine_mode src_mode = GET_MODE (src1);
+  enum machine_mode dst_mode = GET_MODE (dst);
+
+  gcc_assert (VECTOR_MODE_P (dst_mode));
+
+  if (REG_P (dst) && REG_P (src1) && REG_P (src2))
+    {
+      switch (src_mode)
+	{
+	case V8QImode:
+	  emit_insn (gen_aarch64_simd_combinev8qi (dst, src1, src2));
+	  break;
+	case V4HImode:
+	  emit_insn (gen_aarch64_simd_combinev4hi (dst, src1, src2));
+	  break;
+	case V2SImode:
+	  emit_insn (gen_aarch64_simd_combinev2si (dst, src1, src2));
+	  break;
+	case V2SFmode:
+	  emit_insn (gen_aarch64_simd_combinev2sf (dst, src1, src2));
+	  break;
+	case DImode:
+	  emit_insn (gen_aarch64_simd_combinedi (dst, src1, src2));
+	  break;
+	case DFmode:
+	  emit_insn (gen_aarch64_simd_combinedf (dst, src1, src2));
+	  break;
+	default:
+	  gcc_unreachable ();
+	}
+      return;
+    }
+}
+
 /* Split a complex SIMD move.  */
 
 void
Index: config/aarch64/iterators.md
===================================================================
--- config/aarch64/iterators.md	(revision 198706)
+++ config/aarch64/iterators.md	(working copy)
@@ -382,7 +382,8 @@
 ;; Double modes of vector modes (lower case).
 (define_mode_attr Vdbl [(V8QI "v16qi") (V4HI "v8hi")
 			(V2SI "v4si")  (V2SF "v4sf")
-			(SI   "v2si")  (DI   "v2di")])
+			(SI   "v2si")  (DI   "v2di")
+			(DF   "v2df")])
 
 ;; Narrowed modes for VDN.
 (define_mode_attr VNARROWD [(V4HI "V8QI") (V2SI "V4HI")
