diff --git a/gcc/config/riscv/autovec-opt.md b/gcc/config/riscv/autovec-opt.md
index d9863c76654..3aaee54f02a 100644
--- a/gcc/config/riscv/autovec-opt.md
+++ b/gcc/config/riscv/autovec-opt.md
@@ -18,67 +18,6 @@
;; along with GCC; see the file COPYING3. If not see
;; .
-;; 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"
- [(set (match_operand:VWEXTI 0 "register_operand" "=&vr,&vr")
- (if_then_else:VWEXTI
- (unspec:
- [(match_operand: 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: 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 (, mode);
- rtx tmp = gen_reg_rtx (mode);
- rtx ops[] = {tmp, operands[4]};
- riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ops);
-
- emit_insn (gen_pred (MULT, 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" "")])
-
-;; This pattern it to enchance the instruction combine optimizations for complicate
-;; sign and unsigned widening multiplication operations.
-(define_insn "*pred_widen_mulsu"
- [(set (match_operand:VWEXTI 0 "register_operand" "=&vr,&vr")
- (if_then_else:VWEXTI
- (unspec:
- [(match_operand: 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: 4 "register_operand" " vr, vr"))
- (sign_extend:VWEXTI
- (match_operand: 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" "")])
-
;; -----------------------------------------------------------------------------
;; ---- Integer Compare Instructions Simplification
;; -----------------------------------------------------------------------------
@@ -406,45 +345,6 @@
[(set_attr "type" "vimovvx")
(set_attr "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"
- [(set (match_operand:VWEXTF 0 "register_operand" "=&vr, &vr")
- (if_then_else:VWEXTF
- (unspec:
- [(match_operand: 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: 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);
- rtx tmp = gen_reg_rtx (mode);
- rtx ops[] = {tmp, operands[4]};
- riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ops);
-
- emit_insn (gen_pred (MULT, 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" "")])
-
;; -------------------------------------------------------------------------
;; ---- [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"
[(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_"
+ [(set (match_operand:VWEXTI 0 "register_operand")
+ (any_widen_binop:VWEXTI
+ (any_extend:VWEXTI
+ (match_operand: 1 "register_operand"))
+ (any_extend:VWEXTI
+ (match_operand: 2 "register_operand"))))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ insn_code icode = code_for_pred_dual_widen (,
+ ,
+ mode);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
+ DONE;
+})
+
+(define_insn_and_split "*single_widen_sub"
+ [(set (match_operand:VWEXTI 0 "register_operand")
+ (minus:VWEXTI
+ (match_operand:VWEXTI 1 "register_operand")
+ (any_extend:VWEXTI
+ (match_operand: 2 "register_operand"))))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ insn_code icode = code_for_pred_single_widen_sub (,
+ mode);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
+ DONE;
+})
+
+(define_insn_and_split "*single_widen_add"
+ [(set (match_operand:VWEXTI 0 "register_operand")
+ (plus:VWEXTI
+ (any_extend:VWEXTI
+ (match_operand: 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 (,
+ 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"
+ [(set (match_operand:VWEXTI 0 "register_operand")
+ (mult:VWEXTI
+ (any_extend:VWEXTI
+ (match_operand: 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 (, mode);
+ rtx tmp = gen_reg_rtx (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);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops);
+ DONE;
+})
+
+(define_insn_and_split "*dual_widen_mulsu"
+ [(set (match_operand:VWEXTI 0 "register_operand")
+ (mult:VWEXTI
+ (sign_extend:VWEXTI
+ (match_operand: 1 "register_operand"))
+ (zero_extend:VWEXTI
+ (match_operand: 2 "register_operand"))))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ insn_code icode = code_for_pred_widen_mulsu (mode);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
+ DONE;
+})
+
+(define_insn_and_split "*dual_widen_mulus"
+ [(set (match_operand:VWEXTI 0 "register_operand")
+ (mult:VWEXTI
+ (zero_extend:VWEXTI
+ (match_operand: 2 "register_operand"))
+ (sign_extend:VWEXTI
+ (match_operand: 1 "register_operand"))))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ insn_code icode = code_for_pred_widen_mulsu (mode);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
+ DONE;
+})
+
+(define_insn_and_split "*dual_widen_"
+ [(set (match_operand:VWEXTF 0 "register_operand")
+ (any_widen_binop:VWEXTF
+ (float_extend:VWEXTF
+ (match_operand: 1 "register_operand"))
+ (float_extend:VWEXTF
+ (match_operand: 2 "register_operand"))))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ insn_code icode = code_for_pred_dual_widen (, mode);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_FRM_DYN, operands);
+ DONE;
+})
+
+(define_insn_and_split "*single_widen_add"
+ [(set (match_operand:VWEXTF 0 "register_operand")
+ (plus:VWEXTF
+ (float_extend:VWEXTF
+ (match_operand: 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);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_FRM_DYN, operands);
+ DONE;
+})
+
+(define_insn_and_split "*single_widen_sub"
+ [(set (match_operand:VWEXTF 0 "register_operand")
+ (minus:VWEXTF
+ (match_operand:VWEXTF 1 "register_operand")
+ (float_extend:VWEXTF
+ (match_operand: 2 "register_operand"))))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ insn_code icode = code_for_pred_single_widen_sub (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"
+ [(set (match_operand:VWEXTF 0 "register_operand")
+ (mult:VWEXTF
+ (float_extend:VWEXTF
+ (match_operand: 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);
+ rtx tmp = gen_reg_rtx (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),
+ riscv_vector::BINARY_OP_FRM_DYN, ops);
+ DONE;
+})
diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index c220fda312e..98cd0c07625 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -419,12 +419,15 @@
;; - vadd.vi/vsub.vi/...
;; -------------------------------------------------------------------------
-(define_expand "3"
+(define_insn_and_split "3"
[(set (match_operand:VI 0 "register_operand")
(any_int_binop_no_shift:VI
(match_operand:VI 1 "")
(match_operand:VI 2 "")))]
- "TARGET_VECTOR"
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
{
riscv_vector::emit_vlmax_insn (code_for_pred (, mode),
riscv_vector::BINARY_OP, operands);
@@ -937,11 +940,14 @@
;; Includes:
;; - vneg.v/vnot.v
;; -------------------------------------------------------------------------------
-(define_expand "2"
+(define_insn_and_split "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 (, 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 "abs2"
+(define_insn_and_split "abs2"
[(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, GEN_INT (0));
machine_mode mask_mode = riscv_vector::get_mask_mode (mode);
@@ -1457,12 +1467,15 @@
;; - vfadd.vv/vfsub.vv/...
;; - vfadd.vf/vfsub.vf/...
;; -------------------------------------------------------------------------
-(define_expand "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 "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 (, mode),
riscv_vector::BINARY_OP_FRM_DYN, operands);
@@ -1474,12 +1487,15 @@
;; - vfmin.vv/vfmax.vv
;; - vfmin.vf/vfmax.vf
;; -------------------------------------------------------------------------
-(define_expand "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 "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 (, mode),
riscv_vector::BINARY_OP, operands);
@@ -1537,22 +1553,30 @@
;; - vmulhu.vv
;; -------------------------------------------------------------------------
-(define_expand "smul3_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 "smul3_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);
riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
DONE;
})
-(define_expand "umul3_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 "umul3_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);
riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr111232.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr111232.c
new file mode 100644
index 00000000000..de815c5fac9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr111232.c
@@ -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
+
+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]+} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen-4.c
index c29a74c4f8b..26f27ea6283 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen-4.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen-4.c
@@ -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 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen-complicate-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen-complicate-4.c
index 15fdefc550b..aeac4cb79c2 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen-complicate-4.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen-complicate-4.c
@@ -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} } } */