RISC-V: Keep vlmax vector operators in simple form until split1 pass
This patch keep vlmax vector pattern in simple before split1 pass which will allow more optimization (e.g. combine) before split1 pass. This patch changes the vlmax pattern in autovec.md to define_insn_and_split as much as possible and clean up some combine patterns that are no longer needed. This patch also fixed PR111232 bug which was caused by a combined failed. PR target/111232 gcc/ChangeLog: * config/riscv/autovec-opt.md (@pred_single_widen_mul<any_extend:su><mode>): Delete. (*pred_widen_mulsu<mode>): Delete. (*pred_single_widen_mul<mode>): Delete. (*dual_widen_<any_widen_binop:optab><any_extend:su><mode>): Add new combine patterns. (*single_widen_sub<any_extend:su><mode>): Ditto. (*single_widen_add<any_extend:su><mode>): Ditto. (*single_widen_mult<any_extend:su><mode>): Ditto. (*dual_widen_mulsu<mode>): Ditto. (*dual_widen_mulus<mode>): Ditto. (*dual_widen_<optab><mode>): Ditto. (*single_widen_add<mode>): Ditto. (*single_widen_sub<mode>): Ditto. (*single_widen_mult<mode>): Ditto. * config/riscv/autovec.md (<optab><mode>3): Change define_expand to define_insn_and_split. (<optab><mode>2): Ditto. (abs<mode>2): Ditto. (smul<mode>3_highpart): Ditto. (umul<mode>3_highpart): Ditto. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/autovec/widen/widen-4.c: Add more testcases. * gcc.target/riscv/rvv/autovec/widen/widen-complicate-4.c: Ditto. * gcc.target/riscv/rvv/autovec/pr111232.c: New test.
This commit is contained in:
parent
4abcc5009c
commit
9ee40b9a7b
5 changed files with 276 additions and 136 deletions
|
@ -18,67 +18,6 @@
|
|||
;; 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
|
||||
;; -----------------------------------------------------------------------------
|
||||
|
@ -406,45 +345,6 @@
|
|||
[(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
|
||||
;; -------------------------------------------------------------------------
|
||||
|
@ -845,7 +745,7 @@
|
|||
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
|
||||
|
@ -1003,3 +903,195 @@
|
|||
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;
|
||||
})
|
||||
|
|
|
@ -419,12 +419,15 @@
|
|||
;; - 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);
|
||||
|
@ -937,11 +940,14 @@
|
|||
;; 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);
|
||||
|
@ -952,10 +958,14 @@
|
|||
;; - [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);
|
||||
|
@ -1457,12 +1467,15 @@
|
|||
;; - 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);
|
||||
|
@ -1474,12 +1487,15 @@
|
|||
;; - 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);
|
||||
|
@ -1537,22 +1553,30 @@
|
|||
;; - 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);
|
||||
|
|
18
gcc/testsuite/gcc.target/riscv/rvv/autovec/pr111232.c
Normal file
18
gcc/testsuite/gcc.target/riscv/rvv/autovec/pr111232.c
Normal file
|
@ -0,0 +1,18 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=scalable -Ofast -fno-schedule-insns -fno-schedule-insns2" } */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int16_t
|
||||
foo (int8_t *restrict x, int8_t *restrict y, int n)
|
||||
{
|
||||
int16_t result = 0;
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
result += (x[i] * y[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler {\tvwmacc\.vv\tv[0-9]+,v[0-9]+,v[0-9]+} } } */
|
|
@ -16,8 +16,11 @@
|
|||
#define TEST_ALL() \
|
||||
TEST_TYPE (int16_t, int8_t, uint8_t) \
|
||||
TEST_TYPE (int32_t, int16_t, uint16_t) \
|
||||
TEST_TYPE (int64_t, int32_t, uint32_t)
|
||||
TEST_TYPE (int64_t, int32_t, uint32_t) \
|
||||
TEST_TYPE (int16_t, uint8_t, int8_t) \
|
||||
TEST_TYPE (int32_t, uint16_t, int16_t) \
|
||||
TEST_TYPE (int64_t, uint32_t, int32_t)
|
||||
|
||||
TEST_ALL ()
|
||||
|
||||
/* { dg-final { scan-assembler-times {\tvwmulsu\.vv} 3 } } */
|
||||
/* { dg-final { scan-assembler-times {\tvwmulsu\.vv} 6 } } */
|
||||
|
|
|
@ -21,11 +21,14 @@
|
|||
#define TEST_ALL() \
|
||||
TEST_TYPE (int16_t, int8_t, uint8_t) \
|
||||
TEST_TYPE (int32_t, int16_t, uint16_t) \
|
||||
TEST_TYPE (int64_t, int32_t, uint32_t)
|
||||
TEST_TYPE (int64_t, int32_t, uint32_t) \
|
||||
TEST_TYPE (int16_t, uint8_t, int8_t) \
|
||||
TEST_TYPE (int32_t, uint16_t, int16_t) \
|
||||
TEST_TYPE (int64_t, uint32_t, int32_t)
|
||||
|
||||
TEST_ALL ()
|
||||
|
||||
/* { dg-final { scan-assembler-times {\tvwmulsu\.vv} 6 } } */
|
||||
/* { dg-final { scan-assembler-times {\tvwmul\.vv} 3 } } */
|
||||
/* { dg-final { scan-assembler-times {\tvwmulu\.vv} 3 } } */
|
||||
/* { dg-final { scan-assembler-times {\tvwmulsu\.vv} 12 } } */
|
||||
/* { dg-final { scan-assembler-times {\tvwmul\.vv} 6 } } */
|
||||
/* { dg-final { scan-assembler-times {\tvwmulu\.vv} 6 } } */
|
||||
/* { dg-final { scan-assembler-not {\tvmul} } } */
|
||||
|
|
Loading…
Add table
Reference in a new issue