RISC-V: Add saturating Addition && Subtraction C/C++ Support

Message ID 20230205014738.8722-1-juzhe.zhong@rivai.ai
State Committed
Commit 7ad729a0df05938fc36c3c0b0c4dd6fa4fcd5eb1
Headers
Series RISC-V: Add saturating Addition && Subtraction C/C++ Support |

Commit Message

juzhe.zhong@rivai.ai Feb. 5, 2023, 1:47 a.m. UTC
  From: Ju-Zhe Zhong <juzhe.zhong@rivai.ai>

gcc/ChangeLog:

        * config/riscv/iterators.md: Add saturating Addition && Subtraction.
        * config/riscv/riscv-v.cc (has_vi_variant_p): Ditto.
        * config/riscv/riscv-vector-builtins-bases.cc (BASE): Ditto. 
        * config/riscv/riscv-vector-builtins-bases.h: Ditto.
        * config/riscv/riscv-vector-builtins-functions.def (vsadd): New def.
        (vssub): Ditto.
        (vsaddu): Ditto.
        (vssubu): Ditto.
        * config/riscv/vector-iterators.md (sll.vi): Adjust for Saturating support.
        (sll.vv): Ditto.
        (%3,%v4): Ditto.
        (%3,%4): Ditto.
        * config/riscv/vector.md (@pred_<optab><mode>): New pattern.
        (@pred_<optab><mode>_scalar): New pattern.
        (*pred_<optab><mode>_scalar): New pattern.
        (*pred_<optab><mode>_extended_scalar): New pattern.

---
 gcc/config/riscv/iterators.md                 |  12 +-
 gcc/config/riscv/riscv-v.cc                   |   5 +-
 .../riscv/riscv-vector-builtins-bases.cc      |   8 +
 .../riscv/riscv-vector-builtins-bases.h       |   4 +
 .../riscv/riscv-vector-builtins-functions.def |   9 +
 gcc/config/riscv/vector-iterators.md          |  52 +++-
 gcc/config/riscv/vector.md                    | 250 +++++++++++++++++-
 7 files changed, 320 insertions(+), 20 deletions(-)
  

Patch

diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md
index 6013f58db6e..7e5415cc80b 100644
--- a/gcc/config/riscv/iterators.md
+++ b/gcc/config/riscv/iterators.md
@@ -203,7 +203,11 @@ 
 			 (umax "umax")
 			 (mult "mul")
 			 (not "one_cmpl")
-			 (neg "neg")])
+			 (neg "neg")
+			 (ss_plus "ssadd")
+			 (us_plus "usadd")
+			 (ss_minus "sssub")
+			 (us_minus "ussub")])
 
 ;; <or_optab> code attributes
 (define_code_attr or_optab [(ior "ior")
@@ -228,7 +232,11 @@ 
 			(umax "maxu")
 			(mult "mul")
 			(not "not")
-			(neg "neg")])
+			(neg "neg")
+			(ss_plus "sadd")
+			(us_plus "saddu")
+			(ss_minus "ssub")
+			(us_minus "ssubu")])
 
 ; atomics code attribute
 (define_code_attr atomic_optab
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 3bc1ee36e5a..df89c9be308 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -427,8 +427,9 @@  neg_simm5_p (rtx x)
 bool
 has_vi_variant_p (rtx_code code, rtx x)
 {
-  if (code != PLUS && code != MINUS && code != AND && code != IOR
-      && code != XOR)
+  if (code != PLUS && code != MINUS && code != AND && code != IOR && code != XOR
+      && code != SS_PLUS && code != SS_MINUS && code != US_PLUS
+      && code != US_MINUS)
     return false;
   return simm5_p (x);
 }
diff --git a/gcc/config/riscv/riscv-vector-builtins-bases.cc b/gcc/config/riscv/riscv-vector-builtins-bases.cc
index 0d86bbcd6b1..7e6ee1d7b53 100644
--- a/gcc/config/riscv/riscv-vector-builtins-bases.cc
+++ b/gcc/config/riscv/riscv-vector-builtins-bases.cc
@@ -241,6 +241,10 @@  static CONSTEXPR const binop<UDIV> vdivu_obj;
 static CONSTEXPR const binop<UMOD> vremu_obj;
 static CONSTEXPR const unop<NEG> vneg_obj;
 static CONSTEXPR const unop<NOT> vnot_obj;
+static CONSTEXPR const binop<SS_PLUS> vsadd_obj;
+static CONSTEXPR const binop<SS_MINUS> vssub_obj;
+static CONSTEXPR const binop<US_PLUS> vsaddu_obj;
+static CONSTEXPR const binop<US_MINUS> vssubu_obj;
 
 /* Declare the function base NAME, pointing it to an instance
    of class <NAME>_obj.  */
@@ -291,5 +295,9 @@  BASE (vdivu)
 BASE (vremu)
 BASE (vneg)
 BASE (vnot)
+BASE (vsadd)
+BASE (vssub)
+BASE (vsaddu)
+BASE (vssubu)
 
 } // end namespace riscv_vector
diff --git a/gcc/config/riscv/riscv-vector-builtins-bases.h b/gcc/config/riscv/riscv-vector-builtins-bases.h
index 72ee25655b2..a59fd918af8 100644
--- a/gcc/config/riscv/riscv-vector-builtins-bases.h
+++ b/gcc/config/riscv/riscv-vector-builtins-bases.h
@@ -68,6 +68,10 @@  extern const function_base *const vdivu;
 extern const function_base *const vremu;
 extern const function_base *const vneg;
 extern const function_base *const vnot;
+extern const function_base *const vsadd;
+extern const function_base *const vssub;
+extern const function_base *const vsaddu;
+extern const function_base *const vssubu;
 }
 
 } // end namespace riscv_vector
diff --git a/gcc/config/riscv/riscv-vector-builtins-functions.def b/gcc/config/riscv/riscv-vector-builtins-functions.def
index b94e780e916..74a1864b725 100644
--- a/gcc/config/riscv/riscv-vector-builtins-functions.def
+++ b/gcc/config/riscv/riscv-vector-builtins-functions.def
@@ -100,5 +100,14 @@  DEF_RVV_FUNCTION (vdivu, alu, full_preds, u_vvx_ops)
 DEF_RVV_FUNCTION (vremu, alu, full_preds, u_vvx_ops)
 DEF_RVV_FUNCTION (vneg, alu, full_preds, iu_v_ops)
 DEF_RVV_FUNCTION (vnot, alu, full_preds, iu_v_ops)
+/* 12. Vector Fixed-Point Arithmetic Instructions. */
+DEF_RVV_FUNCTION (vsadd, alu, full_preds, i_vvv_ops)
+DEF_RVV_FUNCTION (vssub, alu, full_preds, i_vvv_ops)
+DEF_RVV_FUNCTION (vsaddu, alu, full_preds, u_vvv_ops)
+DEF_RVV_FUNCTION (vssubu, alu, full_preds, u_vvv_ops)
+DEF_RVV_FUNCTION (vsadd, alu, full_preds, i_vvx_ops)
+DEF_RVV_FUNCTION (vssub, alu, full_preds, i_vvx_ops)
+DEF_RVV_FUNCTION (vsaddu, alu, full_preds, u_vvx_ops)
+DEF_RVV_FUNCTION (vssubu, alu, full_preds, u_vvx_ops)
 
 #undef DEF_RVV_FUNCTION
diff --git a/gcc/config/riscv/vector-iterators.md b/gcc/config/riscv/vector-iterators.md
index 9cc60da91f4..2460ed670c0 100644
--- a/gcc/config/riscv/vector-iterators.md
+++ b/gcc/config/riscv/vector-iterators.md
@@ -217,6 +217,10 @@ 
 
 (define_code_iterator any_non_commutative_binop [minus div udiv mod umod])
 
+(define_code_iterator any_sat_int_binop [ss_plus ss_minus us_plus us_minus])
+(define_code_iterator sat_int_plus_binop [ss_plus us_plus])
+(define_code_iterator sat_int_minus_binop [ss_minus us_minus])
+
 (define_code_attr binop_rhs1_predicate [
 			(plus "register_operand")
 			(minus "vector_arith_operand")
@@ -234,7 +238,11 @@ 
 			(div "register_operand")
 			(mod "register_operand")
 			(udiv "register_operand")
-			(umod "register_operand")])
+			(umod "register_operand")
+			(ss_plus "register_operand")
+			(us_plus "register_operand")
+			(ss_minus "register_operand")
+			(us_minus "register_operand")])
 
 (define_code_attr binop_rhs2_predicate [
 			(plus "vector_arith_operand")
@@ -253,7 +261,11 @@ 
 			(div "register_operand")
 			(mod "register_operand")
 			(udiv "register_operand")
-			(umod "register_operand")])
+			(umod "register_operand")
+			(ss_plus "vector_arith_operand")
+			(us_plus "vector_arith_operand")
+			(ss_minus "vector_neg_arith_operand")
+			(us_minus "register_operand")])
 
 (define_code_attr binop_rhs1_constraint [
 			(plus "vr,vr,vr,vr,vr,vr")
@@ -291,7 +303,11 @@ 
 			(div "vr,vr,vr,vr,vr,vr")
 			(mod "vr,vr,vr,vr,vr,vr")
 			(udiv "vr,vr,vr,vr,vr,vr")
-			(umod "vr,vr,vr,vr,vr,vr")])
+			(umod "vr,vr,vr,vr,vr,vr")
+			(ss_plus "vr,vr,vi,vi")
+			(us_plus "vr,vr,vi,vi")
+			(ss_minus "vr,vr,vj,vj")
+			(us_minus "vr,vr,vr,vr")])
 
 (define_code_attr int_binop_insn_type [
 			(plus "vialu")
@@ -310,11 +326,15 @@ 
 			(div "vidiv")
 			(mod "vidiv")
 			(udiv "vidiv")
-			(umod "vidiv")])
+			(umod "vidiv")
+			(ss_plus "vsalu")
+			(us_plus "vsalu")
+			(ss_minus "vsalu")
+			(us_minus "vsalu")])
 
-;; <binop_imm_rhs1_insn> expands to the insn name of binop matching constraint rhs1 is immediate.
+;; <binop_vi_variant_insn> expands to the insn name of binop matching constraint rhs1 is immediate.
 ;; minus is negated as vadd and ss_minus is negated as vsadd, others remain <insn>.
-(define_code_attr binop_imm_rhs1_insn [(ashift "sll.vi")
+(define_code_attr binop_vi_variant_insn [(ashift "sll.vi")
 			       (ashiftrt "sra.vi")
 			       (lshiftrt "srl.vi")
 			       (div "div.vv")
@@ -330,11 +350,15 @@ 
 			       (smax "max.vv")
 			       (umin "minu.vv")
 			       (umax "maxu.vv")
-			       (mult "mul.vv")])
+			       (mult "mul.vv")
+			       (ss_plus "sadd.vi")
+			       (us_plus "saddu.vi")
+			       (ss_minus "sadd.vi")
+			       (us_minus "ssubu.vv")])
 
-;; <binop_imm_rhs2_insn> expands to the insn name of binop matching constraint rhs2 is immediate.
+;; <binop_reverse_vi_variant_insn> expands to the insn name of binop matching constraint rhs2 is immediate.
 ;; minus is reversed as vrsub, others remain <insn>.
-(define_code_attr binop_imm_rhs2_insn [(ashift "sll.vv")
+(define_code_attr binop_reverse_vi_variant_insn [(ashift "sll.vv")
 			       (ashiftrt "sra.vv")
 			       (lshiftrt "srl.vv")
 			       (div "div.vv")
@@ -352,7 +376,7 @@ 
 			       (umax "maxu.vv")
 			       (mult "mul.vv")])
 
-(define_code_attr binop_imm_rhs1_op [(ashift "%3,%v4")
+(define_code_attr binop_vi_variant_op [(ashift "%3,%v4")
 			     (ashiftrt "%3,%v4")
 			     (lshiftrt "%3,%v4")
 			     (div "%3,%4")
@@ -368,9 +392,13 @@ 
 			     (smax "%3,%4")
 			     (umin "%3,%4")
 			     (umax "%3,%4")
-			     (mult "%3,%4")])
+			     (mult "%3,%4")
+			     (ss_plus "%3,%v4")
+			     (us_plus "%3,%v4")
+			     (ss_minus "%3,%V4")
+			     (us_minus "%3,%4")])
 
-(define_code_attr binop_imm_rhs2_op [(ashift "%3,%4")
+(define_code_attr binop_reverse_vi_variant_op [(ashift "%3,%4")
 			      (ashiftrt "%3,%4")
 			      (lshiftrt "%3,%4")
 			      (div "%3,%4")
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 73c839f45c3..44584e17105 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -1170,10 +1170,10 @@ 
   "@
    v<insn>.vv\t%0,%3,%4%p1
    v<insn>.vv\t%0,%3,%4%p1
-   v<binop_imm_rhs1_insn>\t%0,<binop_imm_rhs1_op>%p1
-   v<binop_imm_rhs1_insn>\t%0,<binop_imm_rhs1_op>%p1
-   v<binop_imm_rhs2_insn>\t%0,<binop_imm_rhs2_op>%p1
-   v<binop_imm_rhs2_insn>\t%0,<binop_imm_rhs2_op>%p1"
+   v<binop_vi_variant_insn>\t%0,<binop_vi_variant_op>%p1
+   v<binop_vi_variant_insn>\t%0,<binop_vi_variant_op>%p1
+   v<binop_reverse_vi_variant_insn>\t%0,<binop_reverse_vi_variant_op>%p1
+   v<binop_reverse_vi_variant_insn>\t%0,<binop_reverse_vi_variant_op>%p1"
   [(set_attr "type" "<int_binop_insn_type>")
    (set_attr "mode" "<MODE>")])
 
@@ -1532,6 +1532,248 @@ 
   [(set_attr "type" "vialu")
    (set_attr "mode" "<MODE>")])
 
+;; Saturating Add and Subtract
+(define_insn "@pred_<optab><mode>"
+  [(set (match_operand:VI 0 "register_operand"                   "=vd, vr, vd, vr")
+	(if_then_else:VI
+	  (unspec:<VM>
+	    [(match_operand:<VM> 1 "vector_mask_operand"         " vm,Wc1, vm,Wc1")
+	     (match_operand 5 "vector_length_operand"            " rK, rK, rK, rK")
+	     (match_operand 6 "const_int_operand"                "  i,  i,  i,  i")
+	     (match_operand 7 "const_int_operand"                "  i,  i,  i,  i")
+	     (match_operand 8 "const_int_operand"                "  i,  i,  i,  i")
+	     (reg:SI VL_REGNUM)
+	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+	  (any_sat_int_binop:VI
+	    (match_operand:VI 3 "<binop_rhs1_predicate>"         " vr, vr, vr, vr")
+	    (match_operand:VI 4 "<binop_rhs2_predicate>" "<binop_rhs2_constraint>"))
+	  (match_operand:VI 2 "vector_merge_operand"             "0vu,0vu,0vu,0vu")))]
+  "TARGET_VECTOR"
+  "@
+   v<insn>.vv\t%0,%3,%4%p1
+   v<insn>.vv\t%0,%3,%4%p1
+   v<binop_vi_variant_insn>\t%0,<binop_vi_variant_op>%p1
+   v<binop_vi_variant_insn>\t%0,<binop_vi_variant_op>%p1"
+  [(set_attr "type" "<int_binop_insn_type>")
+   (set_attr "mode" "<MODE>")])
+
+;; Handle GET_MODE_INNER (mode) = QImode, HImode, SImode.
+(define_insn "@pred_<optab><mode>_scalar"
+  [(set (match_operand:VI_QHS 0 "register_operand"       "=vd, vr")
+	(if_then_else:VI_QHS
+	  (unspec:<VM>
+	    [(match_operand:<VM> 1 "vector_mask_operand" " vm,Wc1")
+	     (match_operand 5 "vector_length_operand"    " rK, rK")
+	     (match_operand 6 "const_int_operand"        "  i,  i")
+	     (match_operand 7 "const_int_operand"        "  i,  i")
+	     (match_operand 8 "const_int_operand"        "  i,  i")
+	     (reg:SI VL_REGNUM)
+	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+	  (sat_int_plus_binop:VI_QHS
+	    (vec_duplicate:VI_QHS
+	      (match_operand:<VEL> 4 "register_operand"  "  r,  r"))
+	    (match_operand:VI_QHS 3 "register_operand"   " vr, vr"))
+	  (match_operand:VI_QHS 2 "vector_merge_operand" "0vu,0vu")))]
+  "TARGET_VECTOR"
+  "v<insn>.vx\t%0,%3,%4%p1"
+  [(set_attr "type" "<int_binop_insn_type>")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "@pred_<optab><mode>_scalar"
+  [(set (match_operand:VI_QHS 0 "register_operand"       "=vd, vr")
+	(if_then_else:VI_QHS
+	  (unspec:<VM>
+	    [(match_operand:<VM> 1 "vector_mask_operand" " vm,Wc1")
+	     (match_operand 5 "vector_length_operand"    " rK, rK")
+	     (match_operand 6 "const_int_operand"        "  i,  i")
+	     (match_operand 7 "const_int_operand"        "  i,  i")
+	     (match_operand 8 "const_int_operand"        "  i,  i")
+	     (reg:SI VL_REGNUM)
+	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+	  (sat_int_minus_binop:VI_QHS
+	    (match_operand:VI_QHS 3 "register_operand"   " vr, vr")
+	    (vec_duplicate:VI_QHS
+	      (match_operand:<VEL> 4 "register_operand"  "  r,  r")))
+	  (match_operand:VI_QHS 2 "vector_merge_operand" "0vu,0vu")))]
+  "TARGET_VECTOR"
+  "v<insn>.vx\t%0,%3,%4%p1"
+  [(set_attr "type" "<int_binop_insn_type>")
+   (set_attr "mode" "<MODE>")])
+
+(define_expand "@pred_<optab><mode>_scalar"
+  [(set (match_operand:VI_D 0 "register_operand")
+	(if_then_else:VI_D
+	  (unspec:<VM>
+	    [(match_operand:<VM> 1 "vector_mask_operand")
+	     (match_operand 5 "vector_length_operand")
+	     (match_operand 6 "const_int_operand")
+	     (match_operand 7 "const_int_operand")
+	     (match_operand 8 "const_int_operand")
+	     (reg:SI VL_REGNUM)
+	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+	  (sat_int_plus_binop:VI_D
+	    (vec_duplicate:VI_D
+	      (match_operand:<VEL> 4 "reg_or_int_operand"))
+	    (match_operand:VI_D 3 "register_operand"))
+	  (match_operand:VI_D 2 "vector_merge_operand")))]
+  "TARGET_VECTOR"
+  {
+    if (riscv_vector::has_vi_variant_p (<CODE>, operands[4]))
+      operands[4] = force_reg (<VEL>mode, operands[4]);
+    else if (!TARGET_64BIT)
+      {
+	rtx v = gen_reg_rtx (<MODE>mode);
+
+	if (riscv_vector::simm32_p (operands[4]))
+	  operands[4] = gen_rtx_SIGN_EXTEND (<VEL>mode,
+		force_reg (Pmode, operands[4]));
+	else
+	  {
+	    if (CONST_INT_P (operands[4]))
+	      operands[4] = force_reg (<VEL>mode, operands[4]);
+
+	    riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
+			v, operands[4], operands[5], <VM>mode);
+	    emit_insn (gen_pred_<optab><mode> (operands[0], operands[1],
+			operands[2], operands[3], v, operands[5],
+			operands[6], operands[7], operands[8]));
+	    DONE;
+	  }
+      }
+    else
+      operands[4] = force_reg (<VEL>mode, operands[4]);
+  })
+
+(define_insn "*pred_<optab><mode>_scalar"
+  [(set (match_operand:VI_D 0 "register_operand"         "=vd, vr")
+	(if_then_else:VI_D
+	  (unspec:<VM>
+	    [(match_operand:<VM> 1 "vector_mask_operand" " vm,Wc1")
+	     (match_operand 5 "vector_length_operand"    " rK, rK")
+	     (match_operand 6 "const_int_operand"        "  i,  i")
+	     (match_operand 7 "const_int_operand"        "  i,  i")
+	     (match_operand 8 "const_int_operand"        "  i,  i")
+	     (reg:SI VL_REGNUM)
+	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+	  (sat_int_plus_binop:VI_D
+	    (vec_duplicate:VI_D
+	      (match_operand:<VEL> 4 "register_operand"  "  r,  r"))
+	    (match_operand:VI_D 3 "register_operand"     " vr, vr"))
+	  (match_operand:VI_D 2 "vector_merge_operand"   "0vu,0vu")))]
+  "TARGET_VECTOR"
+  "v<insn>.vx\t%0,%3,%4%p1"
+  [(set_attr "type" "<int_binop_insn_type>")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "*pred_<optab><mode>_extended_scalar"
+  [(set (match_operand:VI_D 0 "register_operand"             "=vd, vr")
+	(if_then_else:VI_D
+	  (unspec:<VM>
+	    [(match_operand:<VM> 1 "vector_mask_operand"     " vm,Wc1")
+	     (match_operand 5 "vector_length_operand"        " rK, rK")
+	     (match_operand 6 "const_int_operand"            "  i,  i")
+	     (match_operand 7 "const_int_operand"            "  i,  i")
+	     (match_operand 8 "const_int_operand"            "  i,  i")
+	     (reg:SI VL_REGNUM)
+	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+	  (sat_int_plus_binop:VI_D
+	    (vec_duplicate:VI_D
+	      (sign_extend:<VEL>
+	        (match_operand:<VSUBEL> 4 "register_operand" "  r,  r")))
+	    (match_operand:VI_D 3 "register_operand"         " vr, vr"))
+	  (match_operand:VI_D 2 "vector_merge_operand"       "0vu,0vu")))]
+  "TARGET_VECTOR"
+  "v<insn>.vx\t%0,%3,%4%p1"
+  [(set_attr "type" "<int_binop_insn_type>")
+   (set_attr "mode" "<MODE>")])
+
+(define_expand "@pred_<optab><mode>_scalar"
+  [(set (match_operand:VI_D 0 "register_operand")
+	(if_then_else:VI_D
+	  (unspec:<VM>
+	    [(match_operand:<VM> 1 "vector_mask_operand")
+	     (match_operand 5 "vector_length_operand")
+	     (match_operand 6 "const_int_operand")
+	     (match_operand 7 "const_int_operand")
+	     (match_operand 8 "const_int_operand")
+	     (reg:SI VL_REGNUM)
+	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+	  (sat_int_minus_binop:VI_D
+	    (match_operand:VI_D 3 "register_operand")
+	    (vec_duplicate:VI_D
+	      (match_operand:<VEL> 4 "reg_or_int_operand")))
+	  (match_operand:VI_D 2 "vector_merge_operand")))]
+  "TARGET_VECTOR"
+  {
+    if (riscv_vector::has_vi_variant_p (<CODE>, operands[4]))
+      operands[4] = force_reg (<VEL>mode, operands[4]);
+    else if (!TARGET_64BIT)
+      {
+	rtx v = gen_reg_rtx (<MODE>mode);
+
+	if (riscv_vector::simm32_p (operands[4]))
+	  operands[4] = gen_rtx_SIGN_EXTEND (<VEL>mode,
+		force_reg (Pmode, operands[4]));
+	else
+	  {
+	    if (CONST_INT_P (operands[4]))
+	      operands[4] = force_reg (<VEL>mode, operands[4]);
+
+	    riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
+			v, operands[4], operands[5], <VM>mode);
+	    emit_insn (gen_pred_<optab><mode> (operands[0], operands[1],
+			operands[2], operands[3], v, operands[5],
+			operands[6], operands[7], operands[8]));
+	    DONE;
+	  }
+      }
+    else
+      operands[4] = force_reg (<VEL>mode, operands[4]);
+  })
+
+(define_insn "*pred_<optab><mode>_scalar"
+  [(set (match_operand:VI_D 0 "register_operand"         "=vd, vr")
+	(if_then_else:VI_D
+	  (unspec:<VM>
+	    [(match_operand:<VM> 1 "vector_mask_operand" " vm,Wc1")
+	     (match_operand 5 "vector_length_operand"    " rK, rK")
+	     (match_operand 6 "const_int_operand"        "  i,  i")
+	     (match_operand 7 "const_int_operand"        "  i,  i")
+	     (match_operand 8 "const_int_operand"        "  i,  i")
+	     (reg:SI VL_REGNUM)
+	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+	  (sat_int_minus_binop:VI_D
+	    (match_operand:VI_D 3 "register_operand"     " vr, vr")
+	    (vec_duplicate:VI_D
+	      (match_operand:<VEL> 4 "register_operand"  "  r,  r")))
+	  (match_operand:VI_D 2 "vector_merge_operand"   "0vu,0vu")))]
+  "TARGET_VECTOR"
+  "v<insn>.vx\t%0,%3,%4%p1"
+  [(set_attr "type" "<int_binop_insn_type>")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "*pred_<optab><mode>_extended_scalar"
+  [(set (match_operand:VI_D 0 "register_operand"             "=vd, vr")
+	(if_then_else:VI_D
+	  (unspec:<VM>
+	    [(match_operand:<VM> 1 "vector_mask_operand"     " vm,Wc1")
+	     (match_operand 5 "vector_length_operand"        " rK, rK")
+	     (match_operand 6 "const_int_operand"            "  i,  i")
+	     (match_operand 7 "const_int_operand"            "  i,  i")
+	     (match_operand 8 "const_int_operand"            "  i,  i")
+	     (reg:SI VL_REGNUM)
+	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+	  (sat_int_minus_binop:VI_D
+	    (match_operand:VI_D 3 "register_operand"         " vr, vr")
+	    (vec_duplicate:VI_D
+	      (sign_extend:<VEL>
+	        (match_operand:<VSUBEL> 4 "register_operand" "  r,  r"))))
+	  (match_operand:VI_D 2 "vector_merge_operand"       "0vu,0vu")))]
+  "TARGET_VECTOR"
+  "v<insn>.vx\t%0,%3,%4%p1"
+  [(set_attr "type" "<int_binop_insn_type>")
+   (set_attr "mode" "<MODE>")])
+
 ;; -------------------------------------------------------------------------------
 ;; ---- Predicated integer unary operations
 ;; -------------------------------------------------------------------------------