RISC-V: Add duplicate vector support.
authorJu-Zhe Zhong <juzhe.zhong@rivai.ai>
Fri, 25 Nov 2022 16:06:39 +0000 (00:06 +0800)
committerKito Cheng <kito.cheng@sifive.com>
Thu, 1 Dec 2022 16:11:52 +0000 (00:11 +0800)
gcc/ChangeLog:

* config/riscv/constraints.md (Wdm): New constraint.
* config/riscv/predicates.md (direct_broadcast_operand): New predicate.
* config/riscv/riscv-protos.h (RVV_VLMAX): New macro.
(emit_pred_op): Refine function.
* config/riscv/riscv-selftests.cc (run_const_vector_selftests): New function.
(run_broadcast_selftests): Ditto.
(BROADCAST_TEST): New tests.
(riscv_run_selftests): More tests.
* config/riscv/riscv-v.cc (emit_pred_move): Refine function.
(emit_vlmax_vsetvl): Ditto.
(emit_pred_op): Ditto.
(expand_const_vector): New function.
(legitimize_move): Add constant vector support.
* config/riscv/riscv.cc (riscv_print_operand): New asm print rule for const vector.
* config/riscv/riscv.h (X0_REGNUM): New macro.
* config/riscv/vector-iterators.md: New attribute.
* config/riscv/vector.md (vec_duplicate<mode>): New pattern.
(@pred_broadcast<mode>): New pattern.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/rvv/base/dup-1.c: New test.
* gcc.target/riscv/rvv/base/dup-2.c: New test.

gcc/config/riscv/constraints.md
gcc/config/riscv/predicates.md
gcc/config/riscv/riscv-protos.h
gcc/config/riscv/riscv-selftests.cc
gcc/config/riscv/riscv-v.cc
gcc/config/riscv/riscv.cc
gcc/config/riscv/riscv.h
gcc/config/riscv/vector-iterators.md
gcc/config/riscv/vector.md
gcc/testsuite/gcc.target/riscv/rvv/base/dup-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/rvv/base/dup-2.c [new file with mode: 0644]

index 4088c48150a573db608a70942511291c5f567fee..51cffb2bcb6269460ba2bc4cf7d09baf3dc6d913 100644 (file)
  A constraint that matches a vector of immediate all ones."
  (and (match_code "const_vector")
       (match_test "op == CONSTM1_RTX (GET_MODE (op))")))
+
+(define_constraint "Wdm"
+  "Vector duplicate memory operand"
+  (and (match_operand 0 "memory_operand")
+       (match_code "reg" "0")))
index dfd98761b8b5545f46e8c7b1da882c35411a7d76..5a5a49bf7c092e997869b0450d7b6679792c7cf5 100644 (file)
            (match_test "GET_CODE (op) == UNSPEC
                         && (XINT (op, 1) == UNSPEC_VUNDEF)"))))
 
+;; The scalar operand can be directly broadcast by RVV instructions.
+(define_predicate "direct_broadcast_operand"
+  (ior (match_operand 0 "register_operand")
+       (match_test "satisfies_constraint_Wdm (op)")))
+
 ;; A CONST_INT operand that has exactly two bits cleared.
 (define_predicate "const_nottwobits_operand"
   (and (match_code "const_int")
index 2ec3af05aa4d78e5581b99c7bdb78b8db3b37066..27692ffb2102da9c132a108d5d8fe25f770dff3a 100644 (file)
@@ -119,6 +119,7 @@ extern void riscv_run_selftests (void);
 #endif
 
 namespace riscv_vector {
+#define RVV_VLMAX gen_rtx_REG (Pmode, X0_REGNUM)
 /* Routines implemented in riscv-vector-builtins.cc.  */
 extern void init_builtins (void);
 extern const char *mangle_builtin_type (const_tree);
@@ -130,6 +131,7 @@ extern tree builtin_decl (unsigned, bool);
 extern rtx expand_builtin (unsigned int, tree, rtx);
 extern bool const_vec_all_same_in_range_p (rtx, HOST_WIDE_INT, HOST_WIDE_INT);
 extern bool legitimize_move (rtx, rtx, machine_mode);
+extern void emit_pred_op (unsigned, rtx, rtx, machine_mode);
 enum tail_policy
 {
   TAIL_UNDISTURBED = 0,
index 636874ebc0f0c93cd7c31cbe3f0a0b75a6b8df97..1bf1a648fa1f6da7247208c073e7e7024dc0eaa6 100644 (file)
@@ -33,6 +33,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "expr.h"
 #include "selftest.h"
 #include "selftest-rtl.h"
+#include "insn-attr.h"
+#include "target.h"
+#include "optabs.h"
 
 #if CHECKING_P
 using namespace selftest;
@@ -230,12 +233,136 @@ run_poly_int_selftests (void)
   run_poly_int_selftest ("rv32imafd_zve32x1p0", ABI_ILP32D, POLY_TEST_DIMODE,
                         worklist);
 }
+
+static void
+run_const_vector_selftests (void)
+{
+  /* We dont't need to do the redundant tests in different march && mabi.
+     Just pick up the march && mabi which fully support all RVV modes.  */
+  riscv_selftest_arch_abi_setter rv ("rv64imafdcv", ABI_LP64D);
+  rtl_dump_test t (SELFTEST_LOCATION, locate_file ("riscv/empty-func.rtl"));
+  set_new_first_and_last_insn (NULL, NULL);
+
+  machine_mode mode;
+  std::vector<HOST_WIDE_INT> worklist = {-111, -17, -16, 7, 15, 16, 111};
+
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_INT)
+    {
+      if (riscv_v_ext_vector_mode_p (mode))
+       {
+         for (const HOST_WIDE_INT &val : worklist)
+           {
+             start_sequence ();
+             rtx dest = gen_reg_rtx (mode);
+             rtx dup = gen_const_vec_duplicate (mode, GEN_INT (val));
+             emit_move_insn (dest, dup);
+             rtx_insn *insn = get_last_insn ();
+             rtx src = XEXP (SET_SRC (PATTERN (insn)), 1);
+             /* 1. Should be vmv.v.i for in rang of -16 ~ 15.
+                2. Should be vmv.v.x for exceed -16 ~ 15.  */
+             if (IN_RANGE (val, -16, 15))
+               ASSERT_TRUE (rtx_equal_p (src, dup));
+             else
+               ASSERT_TRUE (
+                 rtx_equal_p (src,
+                              gen_rtx_VEC_DUPLICATE (mode, XEXP (src, 0))));
+             end_sequence ();
+           }
+       }
+    }
+
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_FLOAT)
+    {
+      if (riscv_v_ext_vector_mode_p (mode))
+       {
+         scalar_mode inner_mode = GET_MODE_INNER (mode);
+         REAL_VALUE_TYPE f = REAL_VALUE_ATOF ("0.2928932", inner_mode);
+         rtx ele = const_double_from_real_value (f, inner_mode);
+
+         start_sequence ();
+         rtx dest = gen_reg_rtx (mode);
+         rtx dup = gen_const_vec_duplicate (mode, ele);
+         emit_move_insn (dest, dup);
+         rtx_insn *insn = get_last_insn ();
+         rtx src = XEXP (SET_SRC (PATTERN (insn)), 1);
+         /* Should always be vfmv.v.f.  */
+         ASSERT_TRUE (
+           rtx_equal_p (src, gen_rtx_VEC_DUPLICATE (mode, XEXP (src, 0))));
+         end_sequence ();
+       }
+    }
+
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_BOOL)
+    {
+      /* Test vmset.m.  */
+      if (riscv_v_ext_vector_mode_p (mode))
+       {
+         start_sequence ();
+         rtx dest = gen_reg_rtx (mode);
+         emit_move_insn (dest, CONSTM1_RTX (mode));
+         rtx_insn *insn = get_last_insn ();
+         rtx src = XEXP (SET_SRC (PATTERN (insn)), 1);
+         ASSERT_TRUE (rtx_equal_p (src, CONSTM1_RTX (mode)));
+         end_sequence ();
+       }
+    }
+}
+
+static void
+run_broadcast_selftests (void)
+{
+  /* We dont't need to do the redundant tests in different march && mabi.
+     Just pick up the march && mabi which fully support all RVV modes.  */
+  riscv_selftest_arch_abi_setter rv ("rv64imafdcv", ABI_LP64D);
+  rtl_dump_test t (SELFTEST_LOCATION, locate_file ("riscv/empty-func.rtl"));
+  set_new_first_and_last_insn (NULL, NULL);
+
+  machine_mode mode;
+
+#define BROADCAST_TEST(MODE_CLASS)                                             \
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_INT)                               \
+    {                                                                          \
+      if (riscv_v_ext_vector_mode_p (mode))                                    \
+       {                                                                      \
+         rtx_insn *insn;                                                      \
+         rtx src;                                                             \
+         scalar_mode inner_mode = GET_MODE_INNER (mode);                      \
+         /* Test vlse.v with zero stride.  */                                 \
+         start_sequence ();                                                   \
+         rtx addr = gen_reg_rtx (Pmode);                                      \
+         rtx mem = gen_rtx_MEM (inner_mode, addr);                            \
+         expand_vector_broadcast (mode, mem);                                 \
+         insn = get_last_insn ();                                             \
+         src = XEXP (SET_SRC (PATTERN (insn)), 1);                            \
+         ASSERT_TRUE (MEM_P (XEXP (src, 0)));                                 \
+         ASSERT_TRUE (                                                        \
+           rtx_equal_p (src, gen_rtx_VEC_DUPLICATE (mode, XEXP (src, 0))));   \
+         end_sequence ();                                                     \
+         /* Test vmv.v.x or vfmv.v.f.  */                                     \
+         start_sequence ();                                                   \
+         rtx reg = gen_reg_rtx (inner_mode);                                  \
+         expand_vector_broadcast (mode, reg);                                 \
+         insn = get_last_insn ();                                             \
+         src = XEXP (SET_SRC (PATTERN (insn)), 1);                            \
+         ASSERT_TRUE (REG_P (XEXP (src, 0)));                                 \
+         ASSERT_TRUE (                                                        \
+           rtx_equal_p (src, gen_rtx_VEC_DUPLICATE (mode, XEXP (src, 0))));   \
+         end_sequence ();                                                     \
+       }                                                                      \
+    }
+
+  BROADCAST_TEST (MODE_VECTOR_INT)
+  BROADCAST_TEST (MODE_VECTOR_FLOAT)
+}
+
 namespace selftest {
 /* Run all target-specific selftests.  */
 void
 riscv_run_selftests (void)
 {
   run_poly_int_selftests ();
+  run_const_vector_selftests ();
+  run_broadcast_selftests ();
 }
 } // namespace selftest
 #endif /* #if CHECKING_P */
index e0459e3f610439c71b1ad6cb4b3ea2034a7b099b..fbd8bbfe2543765a290fa7c53d72423c4601dc18 100644 (file)
@@ -40,6 +40,7 @@
 #include "target.h"
 #include "expr.h"
 #include "optabs.h"
+#include "tm-constrs.h"
 
 using namespace riscv_vector;
 
@@ -104,34 +105,80 @@ const_vec_all_same_in_range_p (rtx x, HOST_WIDE_INT minval,
          && IN_RANGE (INTVAL (elt), minval, maxval));
 }
 
-/* Emit an RVV unmask && vl mov from SRC to DEST.  */
-static void
-emit_pred_move (rtx dest, rtx src, machine_mode mask_mode)
+static rtx
+emit_vlmax_vsetvl (machine_mode vmode)
 {
-  insn_expander<7> e;
-  machine_mode mode = GET_MODE (dest);
   rtx vl = gen_reg_rtx (Pmode);
-  unsigned int sew = GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
+  unsigned int sew = GET_MODE_CLASS (vmode) == MODE_VECTOR_BOOL
                       ? 8
-                      : GET_MODE_BITSIZE (GET_MODE_INNER (mode));
+                      : GET_MODE_BITSIZE (GET_MODE_INNER (vmode));
 
-  emit_insn (gen_vsetvl_no_side_effects (
-    Pmode, vl, gen_rtx_REG (Pmode, 0), gen_int_mode (sew, Pmode),
-    gen_int_mode ((unsigned int) mode, Pmode), const1_rtx, const1_rtx));
+  emit_insn (
+    gen_vsetvl_no_side_effects (Pmode, vl, RVV_VLMAX, gen_int_mode (sew, Pmode),
+                               gen_int_mode ((unsigned int) vmode, Pmode),
+                               const1_rtx, const1_rtx));
+  return vl;
+}
+
+/* Emit an RVV unmask && vl mov from SRC to DEST.  */
+void
+emit_pred_op (unsigned icode, rtx dest, rtx src, machine_mode mask_mode)
+{
+  insn_expander<7> e;
+  machine_mode mode = GET_MODE (dest);
 
   e.add_output_operand (dest, mode);
   e.add_all_one_mask_operand (mask_mode);
   e.add_vundef_operand (mode);
 
-  e.add_input_operand (src, mode);
+  e.add_input_operand (src, GET_MODE (src));
 
-  e.add_input_operand (vl, Pmode);
+  rtx vlmax = emit_vlmax_vsetvl (mode);
+  e.add_input_operand (vlmax, Pmode);
 
   e.add_policy_operand (TAIL_AGNOSTIC, MASK_AGNOSTIC);
 
-  enum insn_code icode;
-  icode = code_for_pred_mov (mode);
-  e.expand (icode, true);
+  e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src));
+}
+
+static void
+expand_const_vector (rtx target, rtx src, machine_mode mask_mode)
+{
+  machine_mode mode = GET_MODE (target);
+  scalar_mode elt_mode = GET_MODE_INNER (mode);
+  if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL)
+    {
+      rtx elt;
+      gcc_assert (
+       const_vec_duplicate_p (src, &elt)
+       && (rtx_equal_p (elt, const0_rtx) || rtx_equal_p (elt, const1_rtx)));
+      emit_pred_op (code_for_pred_mov (mode), target, src, mode);
+      return;
+    }
+
+  rtx elt;
+  if (const_vec_duplicate_p (src, &elt))
+    {
+      rtx tmp = register_operand (target, mode) ? target : gen_reg_rtx (mode);
+      /* Element in range -16 ~ 15 integer or 0.0 floating-point,
+        we use vmv.v.i instruction.  */
+      if (satisfies_constraint_vi (src) || satisfies_constraint_Wc0 (src))
+       emit_pred_op (code_for_pred_mov (mode), tmp, src, mask_mode);
+      else
+       emit_pred_op (code_for_pred_broadcast (mode), tmp,
+                     force_reg (elt_mode, elt), mask_mode);
+
+      if (tmp != target)
+       emit_move_insn (target, tmp);
+      return;
+    }
+
+  /* TODO: We only support const duplicate vector for now. More cases
+     will be supported when we support auto-vectorization:
+
+       1. series vector.
+       2. multiple elts duplicate vector.
+       3. multiple patterns with multiple elts.  */
 }
 
 /* Expand a pre-RA RVV data move from SRC to DEST.
@@ -140,6 +187,11 @@ bool
 legitimize_move (rtx dest, rtx src, machine_mode mask_mode)
 {
   machine_mode mode = GET_MODE (dest);
+  if (CONST_VECTOR_P (src))
+    {
+      expand_const_vector (dest, src, mask_mode);
+      return true;
+    }
   if (known_ge (GET_MODE_SIZE (mode), BYTES_PER_RISCV_VECTOR)
       && GET_MODE_CLASS (mode) != MODE_VECTOR_BOOL)
     {
@@ -153,12 +205,12 @@ legitimize_move (rtx dest, rtx src, machine_mode mask_mode)
     {
       rtx tmp = gen_reg_rtx (mode);
       if (MEM_P (src))
-       emit_pred_move (tmp, src, mask_mode);
+       emit_pred_op (code_for_pred_mov (mode), tmp, src, mask_mode);
       else
        emit_move_insn (tmp, src);
       src = tmp;
     }
-  emit_pred_move (dest, src, mask_mode);
+  emit_pred_op (code_for_pred_mov (mode), dest, src, mask_mode);
   return true;
 }
 
index 05bdba5ab4d63e0fae19b5b16bc8dc2446d96dee..bc0411ea86277e410eddd5a2c305e9b2e0756709 100644 (file)
@@ -4229,6 +4229,19 @@ riscv_print_operand (FILE *file, rtx op, int letter)
 
   switch (letter)
     {
+      case 'v': {
+       rtx elt;
+
+       if (!const_vec_duplicate_p (op, &elt))
+         output_operand_lossage ("invalid vector constant");
+       else if (satisfies_constraint_Wc0 (op))
+         asm_fprintf (file, "0");
+       else if (satisfies_constraint_vi (op))
+         asm_fprintf (file, "%wd", INTVAL (elt));
+       else
+         output_operand_lossage ("invalid vector constant");
+       break;
+      }
       case 'm': {
        if (riscv_v_ext_vector_mode_p (mode))
          {
index b05c3c1545c2c27d36fefb0e480ece30b0d00efe..defb475f948ba1e0b6c259153a02a19c8a317bd3 100644 (file)
@@ -651,6 +651,9 @@ enum reg_class
 #define FP_ARG_FIRST (FP_REG_FIRST + 10)
 #define FP_ARG_LAST  (FP_ARG_FIRST + MAX_ARGS_IN_REGISTERS - 1)
 
+/* Helper macro for RVV vsetvl instruction generation.  */
+#define X0_REGNUM GP_REG_FIRST
+
 #define CALLEE_SAVED_REG_NUMBER(REGNO)                 \
   ((REGNO) >= 8 && (REGNO) <= 9 ? (REGNO) - 8 :                \
    (REGNO) >= 18 && (REGNO) <= 27 ? (REGNO) - 16 : -1)
index 9d4a9dc8a0ee9e8664dcdc684367a1940df2ac7b..92c4bd0a6a37624432fb1d23fe2635bd7047406f 100644 (file)
   (VNx1DF "VNx1BI") (VNx2DF "VNx2BI") (VNx4DF "VNx4BI") (VNx8DF "VNx8BI")
 ])
 
+(define_mode_attr VEL [
+  (VNx1QI "QI") (VNx2QI "QI") (VNx4QI "QI") (VNx8QI "QI") (VNx16QI "QI") (VNx32QI "QI") (VNx64QI "QI")
+  (VNx1HI "HI") (VNx2HI "HI") (VNx4HI "HI") (VNx8HI "HI") (VNx16HI "HI") (VNx32HI "HI")
+  (VNx1SI "SI") (VNx2SI "SI") (VNx4SI "SI") (VNx8SI "SI") (VNx16SI "SI")
+  (VNx1DI "DI") (VNx2DI "DI") (VNx4DI "DI") (VNx8DI "DI")
+  (VNx1SF "SF") (VNx2SF "SF") (VNx4SF "SF") (VNx8SF "SF") (VNx16SF "SF")
+  (VNx1DF "DF") (VNx2DF "DF") (VNx4DF "DF") (VNx8DF "DF")
+])
+
 (define_mode_attr sew [
   (VNx1QI "8") (VNx2QI "8") (VNx4QI "8") (VNx8QI "8") (VNx16QI "8") (VNx32QI "8") (VNx64QI "8")
   (VNx1HI "16") (VNx2HI "16") (VNx4HI "16") (VNx8HI "16") (VNx16HI "16") (VNx32HI "16")
index 01418ac5fcff29fa9e0ec23acb5e1d240152601f..611cc862ca8daac5c0505fc56306f5b6ea48c06d 100644 (file)
   [(set_attr "type" "vmov")
    (set_attr "mode" "<MODE>")])
 
+;; -----------------------------------------------------------------
+;; ---- Duplicate Operations
+;; -----------------------------------------------------------------
+
+;; According to GCC internal:
+;; This pattern only handles duplicates of non-constant inputs.
+;; Constant vectors go through the movm pattern instead.
+;; So "direct_broadcast_operand" can only be mem or reg, no CONSTANT.
+(define_expand "vec_duplicate<mode>"
+  [(set (match_operand:V 0 "register_operand")
+       (vec_duplicate:V
+         (match_operand:<VEL> 1 "direct_broadcast_operand")))]
+  "TARGET_VECTOR"
+  {
+    riscv_vector::emit_pred_op (
+      code_for_pred_broadcast (<MODE>mode), operands[0], operands[1], <VM>mode);
+    DONE;
+  }
+)
+
 ;; -----------------------------------------------------------------
 ;; ---- 6. Configuration-Setting Instructions
 ;; -----------------------------------------------------------------
    vle<sew>.v\t%0,%3%p1
    vse<sew>.v\t%3,%0%p1
    vmv.v.v\t%0,%3
-   vmv.v.i\t%0,v%3"
+   vmv.v.i\t%0,%v3"
   "&& register_operand (operands[0], <MODE>mode)
    && register_operand (operands[3], <MODE>mode)
    && satisfies_constraint_vu (operands[2])"
   ""
   [(set_attr "type" "vldm,vstm,vimov,vmalu,vmalu")
    (set_attr "mode" "<MODE>")])
+
+;; -------------------------------------------------------------------------------
+;; ---- Predicated Broadcast
+;; -------------------------------------------------------------------------------
+;; Includes:
+;; - 7.5. Vector Strided Instructions (zero stride)
+;; - 11.16 Vector Integer Move Instructions (vmv.v.x)
+;; - 13.16 Vector Floating-Point Move Instruction (vfmv.v.f)
+;; -------------------------------------------------------------------------------
+
+(define_insn "@pred_broadcast<mode>"
+  [(set (match_operand:V 0 "register_operand"                 "=vr,  vr,  vr,  vr")
+       (if_then_else:V
+         (unspec:<VM>
+           [(match_operand:<VM> 1 "vector_mask_operand"      " Wc1, Wc1, vm, Wc1")
+            (match_operand 4 "vector_length_operand"         " rK,  rK,  rK,  rK")
+            (match_operand 5 "const_int_operand"             "  i,   i,   i,   i")
+            (match_operand 6 "const_int_operand"             "  i,   i,   i,   i")
+            (reg:SI VL_REGNUM)
+            (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+         (vec_duplicate:V
+           (match_operand:<VEL> 3 "direct_broadcast_operand" "  r,   f, Wdm, Wdm"))
+         (match_operand:V 2 "vector_merge_operand"           "vu0, vu0, vu0, vu0")))]
+  "TARGET_VECTOR"
+  "@
+   vmv.v.x\t%0,%3
+   vfmv.v.f\t%0,%3
+   vlse<sew>.v\t%0,%3,zero,%1.t
+   vlse<sew>.v\t%0,%3,zero"
+  [(set_attr "type" "vimov,vfmov,vlds,vlds")
+   (set_attr "mode" "<MODE>")])
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/dup-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/dup-1.c
new file mode 100644 (file)
index 0000000..2a83afa
--- /dev/null
@@ -0,0 +1,521 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gcv -mabi=ilp32 -O3 -fgimple" } */
+
+#include "riscv_vector.h"
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f1 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vint8mf8_t> ((vint8mf8_t *)out_2(D)) = _Literal (vint8mf8_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f2 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vint8mf4_t> ((vint8mf4_t *)out_2(D)) = _Literal (vint8mf4_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f3 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vint8mf2_t> ((vint8mf2_t *)out_2(D)) = _Literal (vint8mf2_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f4 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vint8m1_t> ((vint8m1_t *)out_2(D)) = _Literal (vint8m1_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f5 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vint8m2_t> ((vint8m2_t *)out_2(D)) = _Literal (vint8m2_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f6 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vint8m4_t> ((vint8m4_t *)out_2(D)) = _Literal (vint8m4_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f7 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vint8m8_t> ((vint8m8_t *)out_2(D)) = _Literal (vint8m8_t) 0;
+  return;
+
+}
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f8 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vuint8mf8_t> ((vuint8mf8_t *)out_2(D)) = _Literal (vuint8mf8_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f9 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vuint8mf4_t> ((vuint8mf4_t *)out_2(D)) = _Literal (vuint8mf4_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f10 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vuint8mf2_t> ((vuint8mf2_t *)out_2(D)) = _Literal (vuint8mf2_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f11 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vuint8m1_t> ((vuint8m1_t *)out_2(D)) = _Literal (vuint8m1_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f12 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vuint8m2_t> ((vuint8m2_t *)out_2(D)) = _Literal (vuint8m2_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f13 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vuint8m4_t> ((vuint8m4_t *)out_2(D)) = _Literal (vuint8m4_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f14 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vuint8m8_t> ((vuint8m8_t *)out_2(D)) = _Literal (vuint8m8_t) 0;
+  return;
+
+}
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f15 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vint16mf4_t> ((vint16mf4_t *)out_2(D)) = _Literal (vint16mf4_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f16 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vint16mf2_t> ((vint16mf2_t *)out_2(D)) = _Literal (vint16mf2_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f17 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vint16m1_t> ((vint16m1_t *)out_2(D)) = _Literal (vint16m1_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f18 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vint16m2_t> ((vint16m2_t *)out_2(D)) = _Literal (vint16m2_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f19 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vint16m4_t> ((vint16m4_t *)out_2(D)) = _Literal (vint16m4_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f20 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vint16m8_t> ((vint16m8_t *)out_2(D)) = _Literal (vint16m8_t) 0;
+  return;
+
+}
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f21 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vuint16mf4_t> ((vuint16mf4_t *)out_2(D)) = _Literal (vuint16mf4_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f22 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vuint16mf2_t> ((vuint16mf2_t *)out_2(D)) = _Literal (vuint16mf2_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f23 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vuint16m1_t> ((vuint16m1_t *)out_2(D)) = _Literal (vuint16m1_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f24 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vuint16m2_t> ((vuint16m2_t *)out_2(D)) = _Literal (vuint16m2_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f25 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vuint16m4_t> ((vuint16m4_t *)out_2(D)) = _Literal (vuint16m4_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f26 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vuint16m8_t> ((vuint16m8_t *)out_2(D)) = _Literal (vuint16m8_t) 0;
+  return;
+
+}
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f27 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vint32mf2_t> ((vint32mf2_t *)out_2(D)) = _Literal (vint32mf2_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f28 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vint32m1_t> ((vint32m1_t *)out_2(D)) = _Literal (vint32m1_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f29 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vint32m2_t> ((vint32m2_t *)out_2(D)) = _Literal (vint32m2_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f30 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vint32m4_t> ((vint32m4_t *)out_2(D)) = _Literal (vint32m4_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f31 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vint32m8_t> ((vint32m8_t *)out_2(D)) = _Literal (vint32m8_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f32 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vuint32mf2_t> ((vuint32mf2_t *)out_2(D)) = _Literal (vuint32mf2_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f33 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vuint32m1_t> ((vuint32m1_t *)out_2(D)) = _Literal (vuint32m1_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f34 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vuint32m2_t> ((vuint32m2_t *)out_2(D)) = _Literal (vuint32m2_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f35 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vuint32m4_t> ((vuint32m4_t *)out_2(D)) = _Literal (vuint32m4_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f36 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vuint32m8_t> ((vuint32m8_t *)out_2(D)) = _Literal (vuint32m8_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f37 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vint64m1_t> ((vint64m1_t *)out_2(D)) = _Literal (vint64m1_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f38 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vint64m2_t> ((vint64m2_t *)out_2(D)) = _Literal (vint64m2_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f39 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vint64m4_t> ((vint64m4_t *)out_2(D)) = _Literal (vint64m4_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f40 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vint64m8_t> ((vint64m8_t *)out_2(D)) = _Literal (vint64m8_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f41 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vuint64m1_t> ((vuint64m1_t *)out_2(D)) = _Literal (vuint64m1_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f42 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vuint64m2_t> ((vuint64m2_t *)out_2(D)) = _Literal (vuint64m2_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f43 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vuint64m4_t> ((vuint64m4_t *)out_2(D)) = _Literal (vuint64m4_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f44 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vuint64m8_t> ((vuint64m8_t *)out_2(D)) = _Literal (vuint64m8_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f45 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vfloat32m1_t> ((vfloat32m1_t *)out_2(D)) = _Literal (vfloat32m1_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f46 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vfloat32m2_t> ((vfloat32m2_t *)out_2(D)) = _Literal (vfloat32m2_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f47 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vfloat32m4_t> ((vfloat32m4_t *)out_2(D)) = _Literal (vfloat32m4_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f48 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vfloat32m8_t> ((vfloat32m8_t *)out_2(D)) = _Literal (vfloat32m8_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f49 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vfloat64m1_t> ((vfloat64m1_t *)out_2(D)) = _Literal (vfloat64m1_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f50 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vfloat64m2_t> ((vfloat64m2_t *)out_2(D)) = _Literal (vfloat64m2_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f51 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vfloat64m4_t> ((vfloat64m4_t *)out_2(D)) = _Literal (vfloat64m4_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f52 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vfloat64m8_t> ((vfloat64m8_t *)out_2(D)) = _Literal (vfloat64m8_t) 0;
+  return;
+
+}
+
+/* { dg-final { scan-assembler-times {vmv\.v\.i\s+(?:v[0-9]|v[1-2][0-9]|v3[0-1]),\s*0} 52 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/dup-2.c b/gcc/testsuite/gcc.target/riscv/rvv/base/dup-2.c
new file mode 100644 (file)
index 0000000..c690303
--- /dev/null
@@ -0,0 +1,75 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gcv -mabi=ilp32 -O3 -fgimple" } */
+
+#include "riscv_vector.h"
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f1 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vbool1_t> ((vbool1_t *)out_2(D)) = _Literal (vbool1_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f2 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vbool2_t> ((vbool2_t *)out_2(D)) = _Literal (vbool2_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f3 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vbool4_t> ((vbool4_t *)out_2(D)) = _Literal (vbool4_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f4 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vbool8_t> ((vbool8_t *)out_2(D)) = _Literal (vbool8_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f5 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vbool16_t> ((vbool16_t *)out_2(D)) = _Literal (vbool16_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f6 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vbool32_t> ((vbool32_t *)out_2(D)) = _Literal (vbool32_t) 0;
+  return;
+
+}
+
+
+void __GIMPLE (ssa,guessed_local(1073741824))
+f7 (void * out)
+{
+  __BB(2,guessed_local(1073741824)):
+  __MEM <vbool64_t> ((vbool64_t *)out_2(D)) = _Literal (vbool64_t) 0;
+  return;
+
+}
+
+/* { dg-final { scan-assembler-times {vmclr\.m\s+(?:v[0-9]|v[1-2][0-9]|v3[0-1])} 7 } } */