]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
RISC-V: Keep vlmax vector operators in simple form until split1 pass
authorLehua Ding <lehua.ding@rivai.ai>
Mon, 4 Sep 2023 09:15:08 +0000 (17:15 +0800)
committerLehua Ding <lehua.ding@rivai.ai>
Wed, 6 Sep 2023 09:55:24 +0000 (17:55 +0800)
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.

gcc/config/riscv/autovec-opt.md
gcc/config/riscv/autovec.md
gcc/testsuite/gcc.target/riscv/rvv/autovec/pr111232.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen-4.c
gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen-complicate-4.c

index d9863c76654e00603396b677d2b2135e5edcca48..3aaee54f02a3aaccf32655e490e1cceb9d6b1fd7 100644 (file)
 ;; 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;
+})
index c220fda312e8431e8d423afa856ca4388e1d68c7..98cd0c07625bb2ed42cebcdb72259f0a9ff87aa3 100644 (file)
 ;; - 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);
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 (file)
index 0000000..de815c5
--- /dev/null
@@ -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]+} } }  */
index c29a74c4f8ba7df08a6bbb6c3870cffe411e7a95..26f27ea62836c0a76444e477d6ec0204efb5d4bb 100644 (file)
 #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 } } */
index 15fdefc550bbd37be12809f7b7d9cf469e151283..aeac4cb79c2c8ac525981fd451e185a4e98df31d 100644 (file)
 #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} } } */