Index: gcc/doc/md.texi
===================================================================
--- gcc/doc/md.texi	2018-05-24 09:31:46.687834412 +0100
+++ gcc/doc/md.texi	2018-05-24 09:32:10.522816506 +0100
@@ -6349,13 +6349,21 @@ operand 0, otherwise (operand 2 + operan
 @itemx @samp{cond_smax@var{mode}}
 @itemx @samp{cond_umin@var{mode}}
 @itemx @samp{cond_umax@var{mode}}
-Perform an elementwise operation on vector operands 2 and 3,
-under the control of the vector mask in operand 1, and store the result
-in operand 0.  This is equivalent to:
+When operand 1 is true, perform an operation on operands 2 and 3 and
+store the result in operand 0, otherwise store operand 4 in operand 0.
+The operation works elementwise if the operands are vectors.
+
+The scalar case is equivalent to:
+
+@smallexample
+op0 = op1 ? op2 @var{op} op3 : op4;
+@end smallexample
+
+while the vector case is equivalent to:
 
 @smallexample
-for (i = 0; i < GET_MODE_NUNITS (@var{n}); i++)
-  op0[i] = op1[i] ? op2[i] @var{op} op3[i] : op2[i];
+for (i = 0; i < GET_MODE_NUNITS (@var{m}); i++)
+  op0[i] = op1[i] ? op2[i] @var{op} op3[i] : op4[i];
 @end smallexample
 
 where, for example, @var{op} is @code{+} for @samp{cond_add@var{mode}}.
@@ -6364,8 +6372,9 @@ When defined for floating-point modes, t
 are not interpreted if @var{op1[i]} is false, just like they would not
 be in a normal C @samp{?:} condition.
 
-Operands 0, 2 and 3 all have mode @var{m}, while operand 1 has the mode
-returned by @code{TARGET_VECTORIZE_GET_MASK_MODE}.
+Operands 0, 2, 3 and 4 all have mode @var{m}.  Operand 1 is a scalar
+integer if @var{m} is scalar, otherwise it has the mode returned by
+@code{TARGET_VECTORIZE_GET_MASK_MODE}.
 
 @cindex @code{neg@var{mode}cc} instruction pattern
 @item @samp{neg@var{mode}cc}
Index: gcc/internal-fn.def
===================================================================
--- gcc/internal-fn.def	2018-05-24 09:31:46.687834412 +0100
+++ gcc/internal-fn.def	2018-05-24 09:32:10.522816506 +0100
@@ -173,7 +173,7 @@ DEF_INTERNAL_OPTAB_FN (REDUC_XOR, ECF_CO
 
 /* Extract the last active element from a vector.  */
 DEF_INTERNAL_OPTAB_FN (EXTRACT_LAST, ECF_CONST | ECF_NOTHROW,
-		       extract_last, cond_unary)
+		       extract_last, fold_left)
 
 /* Same, but return the first argument if no elements are active.  */
 DEF_INTERNAL_OPTAB_FN (FOLD_EXTRACT_LAST, ECF_CONST | ECF_NOTHROW,
Index: gcc/internal-fn.c
===================================================================
--- gcc/internal-fn.c	2018-05-24 09:31:46.687834412 +0100
+++ gcc/internal-fn.c	2018-05-24 09:32:10.522816506 +0100
@@ -2988,10 +2988,10 @@ #define expand_ternary_optab_fn(FN, STMT
   expand_direct_optab_fn (FN, STMT, OPTAB, 3)
 
 #define expand_cond_unary_optab_fn(FN, STMT, OPTAB) \
-  expand_direct_optab_fn (FN, STMT, OPTAB, 2)
+  expand_direct_optab_fn (FN, STMT, OPTAB, 3)
 
 #define expand_cond_binary_optab_fn(FN, STMT, OPTAB) \
-  expand_direct_optab_fn (FN, STMT, OPTAB, 3)
+  expand_direct_optab_fn (FN, STMT, OPTAB, 4)
 
 #define expand_fold_extract_optab_fn(FN, STMT, OPTAB) \
   expand_direct_optab_fn (FN, STMT, OPTAB, 3)
@@ -3219,12 +3219,19 @@ #define DEF_INTERNAL_FN(CODE, FLAGS, FNS
   0
 };
 
-/* Return a function that performs the conditional form of CODE, i.e.:
+/* Return a function that only performs CODE when a certain condition is met
+   and that uses a given fallback value otherwise.  For example, if CODE is
+   a binary operation associated with conditional function FN:
+
+     LHS = FN (COND, A, B, ELSE)
+
+   is equivalent to the C expression:
+
+     LHS = COND ? A CODE B : ELSE;
 
-     LHS = RHS1 ? RHS2 CODE RHS3 : RHS2
+   operating elementwise if the operands are vectors.
 
-   (operating elementwise if the operands are vectors).  Return IFN_LAST
-   if no such function exists.  */
+   Return IFN_LAST if no such function exists.  */
 
 internal_fn
 get_conditional_internal_fn (tree_code code)
Index: gcc/tree-vect-loop.c
===================================================================
--- gcc/tree-vect-loop.c	2018-05-24 09:31:46.687834412 +0100
+++ gcc/tree-vect-loop.c	2018-05-24 09:32:10.523816456 +0100
@@ -7222,8 +7222,9 @@ vectorizable_reduction (gimple *stmt, gi
 		}
 	      tree mask = vect_get_loop_mask (gsi, masks, vec_num * ncopies,
 					      vectype_in, i * ncopies + j);
-	      gcall *call = gimple_build_call_internal (cond_fn, 3, mask,
-							vop[0], vop[1]);
+	      gcall *call = gimple_build_call_internal (cond_fn, 4, mask,
+							vop[0], vop[1],
+							vop[0]);
 	      new_temp = make_ssa_name (vec_dest, call);
 	      gimple_call_set_lhs (call, new_temp);
 	      gimple_call_set_nothrow (call, true);
Index: gcc/config/aarch64/aarch64-sve.md
===================================================================
--- gcc/config/aarch64/aarch64-sve.md	2018-05-24 09:32:03.433159783 +0100
+++ gcc/config/aarch64/aarch64-sve.md	2018-05-24 09:32:10.521816556 +0100
@@ -1787,14 +1787,31 @@ (define_insn "*<maxmin_uns><mode>3"
   "<maxmin_uns_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
 )
 
+;; Predicated integer operations with select.
+(define_expand "cond_<optab><mode>"
+  [(set (match_operand:SVE_I 0 "register_operand")
+	(unspec:SVE_I
+	  [(match_operand:<VPRED> 1 "register_operand")
+	   (SVE_INT_BINARY:SVE_I
+	     (match_operand:SVE_I 2 "register_operand")
+	     (match_operand:SVE_I 3 "register_operand"))
+	   (match_operand:SVE_I 4 "register_operand")]
+	  UNSPEC_SEL))]
+  "TARGET_SVE"
+{
+  gcc_assert (rtx_equal_p (operands[2], operands[4]));
+})
+
 ;; Predicated integer operations.
-(define_insn "cond_<optab><mode>"
+(define_insn "*cond_<optab><mode>"
   [(set (match_operand:SVE_I 0 "register_operand" "=w")
 	(unspec:SVE_I
 	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
-	   (match_operand:SVE_I 2 "register_operand" "0")
-	   (match_operand:SVE_I 3 "register_operand" "w")]
-	  SVE_COND_INT_OP))]
+	   (SVE_INT_BINARY:SVE_I
+	     (match_operand:SVE_I 2 "register_operand" "0")
+	     (match_operand:SVE_I 3 "register_operand" "w"))
+	   (match_dup 2)]
+	  UNSPEC_SEL))]
   "TARGET_SVE"
   "<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
 )
@@ -2566,14 +2583,35 @@ (define_expand "vec_pack_<su>fix_trunc_v
   }
 )
 
+;; Predicated floating-point operations with select.
+(define_expand "cond_<optab><mode>"
+  [(set (match_operand:SVE_F 0 "register_operand")
+	(unspec:SVE_F
+	  [(match_operand:<VPRED> 1 "register_operand")
+	   (unspec:SVE_F
+	     [(match_dup 1)
+	      (match_operand:SVE_F 2 "register_operand")
+	      (match_operand:SVE_F 3 "register_operand")]
+	     SVE_COND_FP_BINARY)
+	   (match_operand:SVE_F 4 "register_operand")]
+	  UNSPEC_SEL))]
+  "TARGET_SVE"
+{
+  gcc_assert (rtx_equal_p (operands[2], operands[4]));
+})
+
 ;; Predicated floating-point operations.
-(define_insn "cond_<optab><mode>"
+(define_insn "*cond_<optab><mode>"
   [(set (match_operand:SVE_F 0 "register_operand" "=w")
 	(unspec:SVE_F
 	  [(match_operand:<VPRED> 1 "register_operand" "Upl")
-	   (match_operand:SVE_F 2 "register_operand" "0")
-	   (match_operand:SVE_F 3 "register_operand" "w")]
-	  SVE_COND_FP_OP))]
+	   (unspec:SVE_F
+	     [(match_dup 1)
+	      (match_operand:SVE_F 2 "register_operand" "0")
+	      (match_operand:SVE_F 3 "register_operand" "w")]
+	     SVE_COND_FP_BINARY)
+	   (match_dup 2)]
+	  UNSPEC_SEL))]
   "TARGET_SVE"
   "<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
 )
Index: gcc/config/aarch64/iterators.md
===================================================================
--- gcc/config/aarch64/iterators.md	2018-05-24 09:32:03.433159783 +0100
+++ gcc/config/aarch64/iterators.md	2018-05-24 09:32:10.521816556 +0100
@@ -464,13 +464,6 @@ (define_c_enum "unspec"
     UNSPEC_UMUL_HIGHPART ; Used in aarch64-sve.md.
     UNSPEC_COND_ADD	; Used in aarch64-sve.md.
     UNSPEC_COND_SUB	; Used in aarch64-sve.md.
-    UNSPEC_COND_SMAX	; Used in aarch64-sve.md.
-    UNSPEC_COND_UMAX	; Used in aarch64-sve.md.
-    UNSPEC_COND_SMIN	; Used in aarch64-sve.md.
-    UNSPEC_COND_UMIN	; Used in aarch64-sve.md.
-    UNSPEC_COND_AND	; Used in aarch64-sve.md.
-    UNSPEC_COND_ORR	; Used in aarch64-sve.md.
-    UNSPEC_COND_EOR	; Used in aarch64-sve.md.
     UNSPEC_COND_LT	; Used in aarch64-sve.md.
     UNSPEC_COND_LE	; Used in aarch64-sve.md.
     UNSPEC_COND_EQ	; Used in aarch64-sve.md.
@@ -1207,6 +1200,9 @@ (define_code_iterator SVE_INT_UNARY [neg
 ;; SVE floating-point unary operations.
 (define_code_iterator SVE_FP_UNARY [neg abs sqrt])
 
+(define_code_iterator SVE_INT_BINARY [plus minus smax umax smin umin
+				      and ior xor])
+
 (define_code_iterator SVE_INT_BINARY_SD [div udiv])
 
 ;; SVE integer comparisons.
@@ -1381,6 +1377,7 @@ (define_mode_attr lconst_atomic [(QI "K"
 
 ;; The integer SVE instruction that implements an rtx code.
 (define_code_attr sve_int_op [(plus "add")
+			      (minus "sub")
 			      (div "sdiv")
 			      (udiv "udiv")
 			      (neg "neg")
@@ -1538,14 +1535,7 @@ (define_int_iterator UNPACK_UNSIGNED [UN
 
 (define_int_iterator MUL_HIGHPART [UNSPEC_SMUL_HIGHPART UNSPEC_UMUL_HIGHPART])
 
-(define_int_iterator SVE_COND_INT_OP [UNSPEC_COND_ADD UNSPEC_COND_SUB
-				      UNSPEC_COND_SMAX UNSPEC_COND_UMAX
-				      UNSPEC_COND_SMIN UNSPEC_COND_UMIN
-				      UNSPEC_COND_AND
-				      UNSPEC_COND_ORR
-				      UNSPEC_COND_EOR])
-
-(define_int_iterator SVE_COND_FP_OP [UNSPEC_COND_ADD UNSPEC_COND_SUB])
+(define_int_iterator SVE_COND_FP_BINARY [UNSPEC_COND_ADD UNSPEC_COND_SUB])
 
 (define_int_iterator SVE_COND_FP_CMP [UNSPEC_COND_LT UNSPEC_COND_LE
 				      UNSPEC_COND_EQ UNSPEC_COND_NE
@@ -1575,14 +1565,7 @@ (define_int_attr optab [(UNSPEC_ANDF "an
 			(UNSPEC_IORV "ior")
 			(UNSPEC_XORV "xor")
 			(UNSPEC_COND_ADD "add")
-			(UNSPEC_COND_SUB "sub")
-			(UNSPEC_COND_SMAX "smax")
-			(UNSPEC_COND_UMAX "umax")
-			(UNSPEC_COND_SMIN "smin")
-			(UNSPEC_COND_UMIN "umin")
-			(UNSPEC_COND_AND "and")
-			(UNSPEC_COND_ORR "ior")
-			(UNSPEC_COND_EOR "xor")])
+			(UNSPEC_COND_SUB "sub")])
 
 (define_int_attr  maxmin_uns [(UNSPEC_UMAXV "umax")
 			      (UNSPEC_UMINV "umin")
@@ -1793,15 +1776,5 @@ (define_int_attr cmp_op [(UNSPEC_COND_LT
 			 (UNSPEC_COND_GE "ge")
 			 (UNSPEC_COND_GT "gt")])
 
-(define_int_attr sve_int_op [(UNSPEC_COND_ADD "add")
-			     (UNSPEC_COND_SUB "sub")
-			     (UNSPEC_COND_SMAX "smax")
-			     (UNSPEC_COND_UMAX "umax")
-			     (UNSPEC_COND_SMIN "smin")
-			     (UNSPEC_COND_UMIN "umin")
-			     (UNSPEC_COND_AND "and")
-			     (UNSPEC_COND_ORR "orr")
-			     (UNSPEC_COND_EOR "eor")])
-
 (define_int_attr sve_fp_op [(UNSPEC_COND_ADD "fadd")
 			    (UNSPEC_COND_SUB "fsub")])
