@@ -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
@@ -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);
}
@@ -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
@@ -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
@@ -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
@@ -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")
@@ -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
;; -------------------------------------------------------------------------------