(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")
(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")
(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")
(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")
(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")
(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")
(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")
(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")
"@
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>")])
[(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
;; -------------------------------------------------------------------------------