Index: gcc/config/aarch64/iterators.md
===================================================================
--- gcc/config/aarch64/iterators.md	2019-08-14 09:34:05.509786440 +0100
+++ gcc/config/aarch64/iterators.md	2019-08-14 09:38:47.027705882 +0100
@@ -278,6 +278,10 @@ (define_mode_iterator VMUL_CHANGE_NLANES
 (define_mode_iterator SVE_ALL [VNx16QI VNx8HI VNx4SI VNx2DI
 			       VNx8HF VNx4SF VNx2DF])
 
+;; Iterators for single modes, for "@" patterns.
+(define_mode_iterator VNx4SI_ONLY [VNx4SI])
+(define_mode_iterator VNx2DF_ONLY [VNx2DF])
+
 ;; All SVE vector structure modes.
 (define_mode_iterator SVE_STRUCT [VNx32QI VNx16HI VNx8SI VNx4DI
 				  VNx16HF VNx8SF VNx4DF
@@ -292,15 +296,21 @@ (define_mode_iterator SVE_BH [VNx16QI VN
 ;; All SVE vector modes that have 8-bit, 16-bit or 32-bit elements.
 (define_mode_iterator SVE_BHS [VNx16QI VNx8HI VNx4SI VNx8HF VNx4SF])
 
-;; All SVE integer vector modes that have 8-bit, 16-bit or 32-bit elements.
+;; SVE integer vector modes that have 8-bit, 16-bit or 32-bit elements.
 (define_mode_iterator SVE_BHSI [VNx16QI VNx8HI VNx4SI])
 
-;; All SVE integer vector modes that have 16-bit, 32-bit or 64-bit elements.
-(define_mode_iterator SVE_HSDI [VNx16QI VNx8HI VNx4SI])
+;; SVE integer vector modes that have 16-bit, 32-bit or 64-bit elements.
+(define_mode_iterator SVE_HSDI [VNx8HI VNx4SI VNx2DI])
 
-;; All SVE floating-point vector modes that have 16-bit or 32-bit elements.
+;; SVE floating-point vector modes that have 16-bit or 32-bit elements.
 (define_mode_iterator SVE_HSF [VNx8HF VNx4SF])
 
+;; SVE integer vector modes that have 32-bit or 64-bit elements.
+(define_mode_iterator SVE_SDI [VNx4SI VNx2DI])
+
+;; SVE floating-point vector modes that have 32-bit or 64-bit elements.
+(define_mode_iterator SVE_SDF [VNx4SF VNx2DF])
+
 ;; All SVE vector modes that have 16-bit, 32-bit or 64-bit elements.
 (define_mode_iterator SVE_HSD [VNx8HI VNx4SI VNx2DI VNx8HF VNx4SF VNx2DF])
 
@@ -313,9 +323,6 @@ (define_mode_iterator SVE_S [VNx4SI VNx4
 ;; All SVE vector modes that have 64-bit elements.
 (define_mode_iterator SVE_D [VNx2DI VNx2DF])
 
-;; All SVE integer vector modes that have 32-bit or 64-bit elements.
-(define_mode_iterator SVE_SDI [VNx4SI VNx2DI])
-
 ;; All SVE integer vector modes.
 (define_mode_iterator SVE_I [VNx16QI VNx8HI VNx4SI VNx2DI])
 
@@ -629,6 +636,11 @@ (define_mode_attr sizen [(QI "8") (HI "1
 (define_mode_attr sizem1 [(QI "#7") (HI "#15") (SI "#31") (DI "#63")
 			  (HF "#15") (SF "#31") (DF "#63")])
 
+;; The number of bits in a vector element, or controlled by a predicate
+;; element.
+(define_mode_attr elem_bits [(VNx8HI "16") (VNx4SI "32") (VNx2DI "64")
+			     (VNx8HF "16") (VNx4SF "32") (VNx2DF "64")])
+
 ;; Attribute to describe constants acceptable in logical operations
 (define_mode_attr lconst [(SI "K") (DI "L")])
 
@@ -1647,6 +1659,7 @@ (define_int_iterator SVE_COND_FP_UNARY [
 					UNSPEC_COND_FRINTZ
 					UNSPEC_COND_FSQRT])
 
+(define_int_iterator SVE_COND_FCVT [UNSPEC_COND_FCVT])
 (define_int_iterator SVE_COND_FCVTI [UNSPEC_COND_FCVTZS UNSPEC_COND_FCVTZU])
 (define_int_iterator SVE_COND_ICVTF [UNSPEC_COND_SCVTF UNSPEC_COND_UCVTF])
 
Index: gcc/config/aarch64/aarch64-sve.md
===================================================================
--- gcc/config/aarch64/aarch64-sve.md	2019-08-14 09:34:05.505786467 +0100
+++ gcc/config/aarch64/aarch64-sve.md	2019-08-14 09:38:47.027705882 +0100
@@ -3656,40 +3656,28 @@ (define_expand "<optab><mode><v_int_equi
   }
 )
 
-;; Conversion of SF to DI, SI or HI, predicated with a PTRUE.
-(define_insn "*<optab>v16hsf<mode>2"
+;; Predicated float-to-integer conversion, either to the same width or wider.
+(define_insn "*aarch64_sve_<optab>_nontrunc<SVE_F:mode><SVE_HSDI:mode>"
   [(set (match_operand:SVE_HSDI 0 "register_operand" "=w")
 	(unspec:SVE_HSDI
-	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
+	  [(match_operand:<SVE_HSDI:VPRED> 1 "register_operand" "Upl")
 	   (match_operand:SI 3 "aarch64_sve_gp_strictness")
-	   (match_operand:VNx8HF 2 "register_operand" "w")]
+	   (match_operand:SVE_F 2 "register_operand" "w")]
 	  SVE_COND_FCVTI))]
-  "TARGET_SVE"
-  "fcvtz<su>\t%0.<Vetype>, %1/m, %2.h"
-)
-
-;; Conversion of SF to DI or SI, predicated with a PTRUE.
-(define_insn "*<optab>vnx4sf<mode>2"
-  [(set (match_operand:SVE_SDI 0 "register_operand" "=w")
-	(unspec:SVE_SDI
-	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
-	   (match_operand:SI 3 "aarch64_sve_gp_strictness")
-	   (match_operand:VNx4SF 2 "register_operand" "w")]
-	  SVE_COND_FCVTI))]
-  "TARGET_SVE"
-  "fcvtz<su>\t%0.<Vetype>, %1/m, %2.s"
+  "TARGET_SVE && <SVE_HSDI:elem_bits> >= <SVE_F:elem_bits>"
+  "fcvtz<su>\t%0.<SVE_HSDI:Vetype>, %1/m, %2.<SVE_F:Vetype>"
 )
 
-;; Conversion of DF to DI or SI, predicated with a PTRUE.
-(define_insn "*<optab>vnx2df<mode>2"
-  [(set (match_operand:SVE_SDI 0 "register_operand" "=w")
-	(unspec:SVE_SDI
+;; Predicated narrowing float-to-integer conversion.
+(define_insn "*aarch64_sve_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>"
+  [(set (match_operand:VNx4SI_ONLY 0 "register_operand" "=w")
+	(unspec:VNx4SI_ONLY
 	  [(match_operand:VNx2BI 1 "register_operand" "Upl")
 	   (match_operand:SI 3 "aarch64_sve_gp_strictness")
-	   (match_operand:VNx2DF 2 "register_operand" "w")]
+	   (match_operand:VNx2DF_ONLY 2 "register_operand" "w")]
 	  SVE_COND_FCVTI))]
   "TARGET_SVE"
-  "fcvtz<su>\t%0.<Vetype>, %1/m, %2.d"
+  "fcvtz<su>\t%0.<VNx4SI_ONLY:Vetype>, %1/m, %2.<VNx2DF_ONLY:Vetype>"
 )
 
 ;; -------------------------------------------------------------------------
@@ -3751,41 +3739,29 @@ (define_expand "<optab><v_int_equiv><mod
   }
 )
 
-;; Conversion of DI, SI or HI to the same number of HFs, predicated
-;; with a PTRUE.
-(define_insn "*<optab><mode>vnx8hf2"
-  [(set (match_operand:VNx8HF 0 "register_operand" "=w")
-	(unspec:VNx8HF
-	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
+;; Predicated integer-to-float conversion, either to the same width or
+;; narrower.
+(define_insn "*aarch64_sve_<optab>_nonextend<SVE_HSDI:mode><SVE_F:mode>"
+  [(set (match_operand:SVE_F 0 "register_operand" "=w")
+	(unspec:SVE_F
+	  [(match_operand:<SVE_HSDI:VPRED> 1 "register_operand" "Upl")
 	   (match_operand:SI 3 "aarch64_sve_gp_strictness")
 	   (match_operand:SVE_HSDI 2 "register_operand" "w")]
 	  SVE_COND_ICVTF))]
-  "TARGET_SVE"
-  "<su>cvtf\t%0.h, %1/m, %2.<Vetype>"
+  "TARGET_SVE && <SVE_HSDI:elem_bits> >= <SVE_F:elem_bits>"
+  "<su>cvtf\t%0.<SVE_F:Vetype>, %1/m, %2.<SVE_HSDI:Vetype>"
 )
 
-;; Conversion of DI or SI to the same number of SFs, predicated with a PTRUE.
-(define_insn "*<optab><mode>vnx4sf2"
-  [(set (match_operand:VNx4SF 0 "register_operand" "=w")
-	(unspec:VNx4SF
-	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
-	   (match_operand:SI 3 "aarch64_sve_gp_strictness")
-	   (match_operand:SVE_SDI 2 "register_operand" "w")]
-	  SVE_COND_ICVTF))]
-  "TARGET_SVE"
-  "<su>cvtf\t%0.s, %1/m, %2.<Vetype>"
-)
-
-;; Conversion of DI or SI to DF, predicated with a PTRUE.
-(define_insn "aarch64_sve_<optab><mode>vnx2df2"
-  [(set (match_operand:VNx2DF 0 "register_operand" "=w")
-	(unspec:VNx2DF
+;; Predicated widening integer-to-float conversion.
+(define_insn "aarch64_sve_<optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>"
+  [(set (match_operand:VNx2DF_ONLY 0 "register_operand" "=w")
+	(unspec:VNx2DF_ONLY
 	  [(match_operand:VNx2BI 1 "register_operand" "Upl")
 	   (match_operand:SI 3 "aarch64_sve_gp_strictness")
-	   (match_operand:SVE_SDI 2 "register_operand" "w")]
+	   (match_operand:VNx4SI_ONLY 2 "register_operand" "w")]
 	  SVE_COND_ICVTF))]
   "TARGET_SVE"
-  "<su>cvtf\t%0.d, %1/m, %2.<Vetype>"
+  "<su>cvtf\t%0.<VNx2DF_ONLY:Vetype>, %1/m, %2.<VNx4SI_ONLY:Vetype>"
 )
 
 ;; -------------------------------------------------------------------------
@@ -3821,7 +3797,7 @@ (define_expand "vec_unpack<su_optab>_flo
 	       (temp, operands[1], operands[1]));
     rtx ptrue = aarch64_ptrue_reg (VNx2BImode);
     rtx strictness = gen_int_mode (SVE_RELAXED_GP, SImode);
-    emit_insn (gen_aarch64_sve_<FLOATUORS:optab>vnx4sivnx2df2
+    emit_insn (gen_aarch64_sve_<FLOATUORS:optab>_extendvnx4sivnx2df
 	       (operands[0], ptrue, temp, strictness));
     DONE;
   }
@@ -3859,17 +3835,16 @@ (define_expand "vec_pack_trunc_<Vwide>"
   }
 )
 
-;; Conversion of DFs to the same number of SFs, or SFs to the same number
-;; of HFs.
-(define_insn "*trunc<Vwide><mode>2"
+;; Predicated float-to-float truncation.
+(define_insn "*aarch64_sve_<optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>"
   [(set (match_operand:SVE_HSF 0 "register_operand" "=w")
 	(unspec:SVE_HSF
-	  [(match_operand:<VWIDE_PRED> 1 "register_operand" "Upl")
+	  [(match_operand:<SVE_SDF:VPRED> 1 "register_operand" "Upl")
 	   (match_operand:SI 3 "aarch64_sve_gp_strictness")
-	   (match_operand:<VWIDE> 2 "register_operand" "w")]
-	  UNSPEC_COND_FCVT))]
-  "TARGET_SVE"
-  "fcvt\t%0.<Vetype>, %1/m, %2.<Vewtype>"
+	   (match_operand:SVE_SDF 2 "register_operand" "w")]
+	  SVE_COND_FCVT))]
+  "TARGET_SVE && <SVE_SDF:elem_bits> > <SVE_HSF:elem_bits>"
+  "fcvt\t%0.<SVE_HSF:Vetype>, %1/m, %2.<SVE_SDF:Vetype>"
 )
 
 ;; -------------------------------------------------------------------------
@@ -3899,23 +3874,22 @@ (define_expand "vec_unpacks_<perm_hilo>_
 		(temp, operands[1], operands[1]));
     rtx ptrue = aarch64_ptrue_reg (<VWIDE_PRED>mode);
     rtx strictness = gen_int_mode (SVE_RELAXED_GP, SImode);
-    emit_insn (gen_aarch64_sve_extend<mode><Vwide>2
+    emit_insn (gen_aarch64_sve_fcvt_nontrunc<mode><Vwide>
 	       (operands[0], ptrue, temp, strictness));
     DONE;
   }
 )
 
-;; Conversion of SFs to the same number of DFs, or HFs to the same number
-;; of SFs.
-(define_insn "aarch64_sve_extend<mode><Vwide>2"
-  [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
-	(unspec:<VWIDE>
-	  [(match_operand:<VWIDE_PRED> 1 "register_operand" "Upl")
+;; Predicated float-to-float extension.
+(define_insn "aarch64_sve_<optab>_nontrunc<SVE_HSF:mode><SVE_SDF:mode>"
+  [(set (match_operand:SVE_SDF 0 "register_operand" "=w")
+	(unspec:SVE_SDF
+	  [(match_operand:<SVE_SDF:VPRED> 1 "register_operand" "Upl")
 	   (match_operand:SI 3 "aarch64_sve_gp_strictness")
 	   (match_operand:SVE_HSF 2 "register_operand" "w")]
-	  UNSPEC_COND_FCVT))]
-  "TARGET_SVE"
-  "fcvt\t%0.<Vewtype>, %1/m, %2.<Vetype>"
+	  SVE_COND_FCVT))]
+  "TARGET_SVE && <SVE_SDF:elem_bits> > <SVE_HSF:elem_bits>"
+  "fcvt\t%0.<SVE_SDF:Vetype>, %1/m, %2.<SVE_HSF:Vetype>"
 )
 
 ;; -------------------------------------------------------------------------
