;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
-;; We don't have vwmul.wv instruction like vwadd.wv in RVV.
-;; This pattern is an intermediate RTL IR as a pseudo vwmul.wv to enhance
-;; optimization of instructions combine.
-(define_insn_and_split "@pred_single_widen_mul<any_extend:su><mode>"
- [(set (match_operand:VWEXTI 0 "register_operand" "=&vr,&vr")
- (if_then_else:VWEXTI
- (unspec:<VM>
- [(match_operand:<VM> 1 "vector_mask_operand" "vmWc1,vmWc1")
- (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)
- (mult:VWEXTI
- (any_extend:VWEXTI
- (match_operand:<V_DOUBLE_TRUNC> 4 "register_operand" " vr, vr"))
- (match_operand:VWEXTI 3 "register_operand" " vr, vr"))
- (match_operand:VWEXTI 2 "vector_merge_operand" " vu, 0")))]
- "TARGET_VECTOR && can_create_pseudo_p ()"
- "#"
- "&& 1"
- [(const_int 0)]
- {
- insn_code icode = code_for_pred_vf2 (<CODE>, <MODE>mode);
- rtx tmp = gen_reg_rtx (<MODE>mode);
- rtx ops[] = {tmp, operands[4]};
- riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ops);
-
- emit_insn (gen_pred (MULT, <MODE>mode, operands[0], operands[1], operands[2],
- operands[3], tmp, operands[5], operands[6],
- operands[7], operands[8]));
- DONE;
- }
- [(set_attr "type" "viwmul")
- (set_attr "mode" "<MODE>")])
-
-;; This pattern it to enchance the instruction combine optimizations for complicate
-;; sign and unsigned widening multiplication operations.
-(define_insn "*pred_widen_mulsu<mode>"
- [(set (match_operand:VWEXTI 0 "register_operand" "=&vr,&vr")
- (if_then_else:VWEXTI
- (unspec:<VM>
- [(match_operand:<VM> 1 "vector_mask_operand" "vmWc1,vmWc1")
- (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)
- (mult:VWEXTI
- (zero_extend:VWEXTI
- (match_operand:<V_DOUBLE_TRUNC> 4 "register_operand" " vr, vr"))
- (sign_extend:VWEXTI
- (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand" " vr, vr")))
- (match_operand:VWEXTI 2 "vector_merge_operand" " vu, 0")))]
- "TARGET_VECTOR"
- "vwmulsu.vv\t%0,%3,%4%p1"
- [(set_attr "type" "viwmul")
- (set_attr "mode" "<V_DOUBLE_TRUNC>")])
-
;; -----------------------------------------------------------------------------
;; ---- Integer Compare Instructions Simplification
;; -----------------------------------------------------------------------------
[(set_attr "type" "vimovvx")
(set_attr "mode" "<MODE>")])
-;; We don't have vfwmul.wv instruction like vfwadd.wv in RVV.
-;; This pattern is an intermediate RTL IR as a pseudo vfwmul.wv to enhance
-;; optimization of instructions combine.
-(define_insn_and_split "*pred_single_widen_mul<mode>"
- [(set (match_operand:VWEXTF 0 "register_operand" "=&vr, &vr")
- (if_then_else:VWEXTF
- (unspec:<VM>
- [(match_operand:<VM> 1 "vector_mask_operand" "vmWc1,vmWc1")
- (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")
- (match_operand 9 "const_int_operand" " i, i")
- (reg:SI VL_REGNUM)
- (reg:SI VTYPE_REGNUM)
- (reg:SI FRM_REGNUM)] UNSPEC_VPREDICATE)
- (mult:VWEXTF
- (float_extend:VWEXTF
- (match_operand:<V_DOUBLE_TRUNC> 4 "register_operand" " vr, vr"))
- (match_operand:VWEXTF 3 "register_operand" " vr, vr"))
- (match_operand:VWEXTF 2 "vector_merge_operand" " vu, 0")))]
- "TARGET_VECTOR && can_create_pseudo_p ()"
- "#"
- "&& 1"
- [(const_int 0)]
- {
- insn_code icode = code_for_pred_extend (<MODE>mode);
- rtx tmp = gen_reg_rtx (<MODE>mode);
- rtx ops[] = {tmp, operands[4]};
- riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ops);
-
- emit_insn (gen_pred (MULT, <MODE>mode, operands[0], operands[1], operands[2],
- operands[3], tmp, operands[5], operands[6],
- operands[7], operands[8], operands[9]));
- DONE;
- }
- [(set_attr "type" "vfwmul")
- (set_attr "mode" "<MODE>")])
-
;; -------------------------------------------------------------------------
;; ---- [FP] VFWMACC
;; -------------------------------------------------------------------------
DONE;
})
-;; Combine FP sign_extend/zero_extend(vf2) and vcond_mask
+;; Combine FP extend(vf2) and vcond_mask
(define_insn_and_split "*cond_extend<v_double_trunc><mode>"
[(set (match_operand:VWEXTF_ZVFHMIN 0 "register_operand")
(if_then_else:VWEXTF_ZVFHMIN
riscv_vector::expand_cond_len_unop (icode, ops);
DONE;
})
+
+;; =============================================================================
+;; Combine extend + binop to widen_binop
+;; =============================================================================
+
+(define_insn_and_split "*dual_widen_<any_widen_binop:optab><any_extend:su><mode>"
+ [(set (match_operand:VWEXTI 0 "register_operand")
+ (any_widen_binop:VWEXTI
+ (any_extend:VWEXTI
+ (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand"))
+ (any_extend:VWEXTI
+ (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ insn_code icode = code_for_pred_dual_widen (<any_widen_binop:CODE>,
+ <any_extend:CODE>,
+ <MODE>mode);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
+ DONE;
+})
+
+(define_insn_and_split "*single_widen_sub<any_extend:su><mode>"
+ [(set (match_operand:VWEXTI 0 "register_operand")
+ (minus:VWEXTI
+ (match_operand:VWEXTI 1 "register_operand")
+ (any_extend:VWEXTI
+ (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ insn_code icode = code_for_pred_single_widen_sub (<any_extend:CODE>,
+ <MODE>mode);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
+ DONE;
+})
+
+(define_insn_and_split "*single_widen_add<any_extend:su><mode>"
+ [(set (match_operand:VWEXTI 0 "register_operand")
+ (plus:VWEXTI
+ (any_extend:VWEXTI
+ (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
+ (match_operand:VWEXTI 1 "register_operand")))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ insn_code icode = code_for_pred_single_widen_add (<any_extend:CODE>,
+ <MODE>mode);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
+ DONE;
+})
+
+;; This combine pattern does not correspond to an single instruction,
+;; i.e. there is no vwmul.wv instruction. This is a temporary pattern
+;; produced by a combine pass and if there is no further combine into
+;; vwmul.vv pattern, then fall back to extend pattern and vmul.vv pattern.
+(define_insn_and_split "*single_widen_mult<any_extend:su><mode>"
+ [(set (match_operand:VWEXTI 0 "register_operand")
+ (mult:VWEXTI
+ (any_extend:VWEXTI
+ (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
+ (match_operand:VWEXTI 1 "register_operand")))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ insn_code extend_icode = code_for_pred_vf2 (<any_extend:CODE>, <MODE>mode);
+ rtx tmp = gen_reg_rtx (<MODE>mode);
+ rtx extend_ops[] = {tmp, operands[2]};
+ riscv_vector::emit_vlmax_insn (extend_icode, riscv_vector::UNARY_OP, extend_ops);
+
+ rtx ops[] = {operands[0], operands[1], tmp};
+ insn_code icode = code_for_pred (MULT, <MODE>mode);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops);
+ DONE;
+})
+
+(define_insn_and_split "*dual_widen_mulsu<mode>"
+ [(set (match_operand:VWEXTI 0 "register_operand")
+ (mult:VWEXTI
+ (sign_extend:VWEXTI
+ (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand"))
+ (zero_extend:VWEXTI
+ (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ insn_code icode = code_for_pred_widen_mulsu (<MODE>mode);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
+ DONE;
+})
+
+(define_insn_and_split "*dual_widen_mulus<mode>"
+ [(set (match_operand:VWEXTI 0 "register_operand")
+ (mult:VWEXTI
+ (zero_extend:VWEXTI
+ (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
+ (sign_extend:VWEXTI
+ (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand"))))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ insn_code icode = code_for_pred_widen_mulsu (<MODE>mode);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
+ DONE;
+})
+
+(define_insn_and_split "*dual_widen_<optab><mode>"
+ [(set (match_operand:VWEXTF 0 "register_operand")
+ (any_widen_binop:VWEXTF
+ (float_extend:VWEXTF
+ (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand"))
+ (float_extend:VWEXTF
+ (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ insn_code icode = code_for_pred_dual_widen (<CODE>, <MODE>mode);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_FRM_DYN, operands);
+ DONE;
+})
+
+(define_insn_and_split "*single_widen_add<mode>"
+ [(set (match_operand:VWEXTF 0 "register_operand")
+ (plus:VWEXTF
+ (float_extend:VWEXTF
+ (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
+ (match_operand:VWEXTF 1 "register_operand")))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ insn_code icode = code_for_pred_single_widen_add (<MODE>mode);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_FRM_DYN, operands);
+ DONE;
+})
+
+(define_insn_and_split "*single_widen_sub<mode>"
+ [(set (match_operand:VWEXTF 0 "register_operand")
+ (minus:VWEXTF
+ (match_operand:VWEXTF 1 "register_operand")
+ (float_extend:VWEXTF
+ (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ insn_code icode = code_for_pred_single_widen_sub (<MODE>mode);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_FRM_DYN, operands);
+ DONE;
+})
+
+;; This combine pattern does not correspond to an single instruction,
+;; i.e. there is no vfwmul.wv instruction. This is a temporary pattern
+;; produced by a combine pass and if there is no further combine into
+;; vfwmul.vv pattern, then fall back to extend pattern and vfmul.vv pattern.
+(define_insn_and_split "*single_widen_mult<mode>"
+ [(set (match_operand:VWEXTF 0 "register_operand")
+ (mult:VWEXTF
+ (float_extend:VWEXTF
+ (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
+ (match_operand:VWEXTF 1 "register_operand")))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ insn_code extend_icode = code_for_pred_extend (<MODE>mode);
+ rtx tmp = gen_reg_rtx (<MODE>mode);
+ rtx extend_ops[] = {tmp, operands[2]};
+ riscv_vector::emit_vlmax_insn (extend_icode, riscv_vector::UNARY_OP, extend_ops);
+
+ rtx ops[] = {operands[0], operands[1], tmp};
+ riscv_vector::emit_vlmax_insn (code_for_pred (MULT, <MODE>mode),
+ riscv_vector::BINARY_OP_FRM_DYN, ops);
+ DONE;
+})
;; - vadd.vi/vsub.vi/...
;; -------------------------------------------------------------------------
-(define_expand "<optab><mode>3"
+(define_insn_and_split "<optab><mode>3"
[(set (match_operand:VI 0 "register_operand")
(any_int_binop_no_shift:VI
(match_operand:VI 1 "<binop_rhs1_predicate>")
(match_operand:VI 2 "<binop_rhs2_predicate>")))]
- "TARGET_VECTOR"
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
{
riscv_vector::emit_vlmax_insn (code_for_pred (<CODE>, <MODE>mode),
riscv_vector::BINARY_OP, operands);
;; Includes:
;; - vneg.v/vnot.v
;; -------------------------------------------------------------------------------
-(define_expand "<optab><mode>2"
+(define_insn_and_split "<optab><mode>2"
[(set (match_operand:VI 0 "register_operand")
(any_int_unop:VI
(match_operand:VI 1 "register_operand")))]
- "TARGET_VECTOR"
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
{
insn_code icode = code_for_pred (<CODE>, <MODE>mode);
riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
;; - [INT] ABS expansion to vmslt and vneg.
;; -------------------------------------------------------------------------------
-(define_expand "abs<mode>2"
+(define_insn_and_split "abs<mode>2"
[(set (match_operand:VI 0 "register_operand")
- (match_operand:VI 1 "register_operand"))]
- "TARGET_VECTOR"
+ (abs:VI
+ (match_operand:VI 1 "register_operand")))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
{
rtx zero = gen_const_vec_duplicate (<MODE>mode, GEN_INT (0));
machine_mode mask_mode = riscv_vector::get_mask_mode (<MODE>mode);
;; - vfadd.vv/vfsub.vv/...
;; - vfadd.vf/vfsub.vf/...
;; -------------------------------------------------------------------------
-(define_expand "<optab><mode>3"
- [(match_operand:VF 0 "register_operand")
- (any_float_binop:VF
- (match_operand:VF 1 "register_operand")
- (match_operand:VF 2 "register_operand"))]
- "TARGET_VECTOR"
+(define_insn_and_split "<optab><mode>3"
+ [(set (match_operand:VF 0 "register_operand")
+ (any_float_binop:VF
+ (match_operand:VF 1 "register_operand")
+ (match_operand:VF 2 "register_operand")))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
{
riscv_vector::emit_vlmax_insn (code_for_pred (<CODE>, <MODE>mode),
riscv_vector::BINARY_OP_FRM_DYN, operands);
;; - vfmin.vv/vfmax.vv
;; - vfmin.vf/vfmax.vf
;; -------------------------------------------------------------------------
-(define_expand "<optab><mode>3"
- [(match_operand:VF 0 "register_operand")
- (any_float_binop_nofrm:VF
- (match_operand:VF 1 "register_operand")
- (match_operand:VF 2 "register_operand"))]
- "TARGET_VECTOR"
+(define_insn_and_split "<optab><mode>3"
+ [(set (match_operand:VF 0 "register_operand")
+ (any_float_binop_nofrm:VF
+ (match_operand:VF 1 "register_operand")
+ (match_operand:VF 2 "register_operand")))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
{
riscv_vector::emit_vlmax_insn (code_for_pred (<CODE>, <MODE>mode),
riscv_vector::BINARY_OP, operands);
;; - vmulhu.vv
;; -------------------------------------------------------------------------
-(define_expand "smul<mode>3_highpart"
- [(match_operand:VFULLI 0 "register_operand")
- (match_operand:VFULLI 1 "register_operand")
- (match_operand:VFULLI 2 "register_operand")]
- "TARGET_VECTOR"
+(define_insn_and_split "smul<mode>3_highpart"
+ [(set (match_operand:VFULLI 0 "register_operand")
+ (smul_highpart:VFULLI
+ (match_operand:VFULLI 1 "register_operand")
+ (match_operand:VFULLI 2 "register_operand")))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
{
insn_code icode = code_for_pred_mulh (UNSPEC_VMULHS, <MODE>mode);
riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
DONE;
})
-(define_expand "umul<mode>3_highpart"
- [(match_operand:VFULLI 0 "register_operand")
- (match_operand:VFULLI 1 "register_operand")
- (match_operand:VFULLI 2 "register_operand")]
- "TARGET_VECTOR"
+(define_insn_and_split "umul<mode>3_highpart"
+ [(set (match_operand:VFULLI 0 "register_operand")
+ (umul_highpart:VFULLI
+ (match_operand:VFULLI 1 "register_operand")
+ (match_operand:VFULLI 2 "register_operand")))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
{
insn_code icode = code_for_pred_mulh (UNSPEC_VMULHU, <MODE>mode);
riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);