aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJuzhe-Zhong <juzhe.zhong@rivai.ai>2023-08-24 18:08:11 +0800
committerPan Li <pan2.li@intel.com>2023-08-26 10:54:34 +0800
commite7545cadbedfc167749d801bd574cf9fe22ed5c5 (patch)
treef7359f12d544e19ecec3e3f4107607494f6e10b3 /gcc
parent3e8db3739c913575428a7e36ad6fd1a7571552ce (diff)
downloadgcc-e7545cadbedfc167749d801bd574cf9fe22ed5c5.zip
gcc-e7545cadbedfc167749d801bd574cf9fe22ed5c5.tar.gz
gcc-e7545cadbedfc167749d801bd574cf9fe22ed5c5.tar.bz2
RISC-V: Support LEN_FOLD_EXTRACT_LAST auto-vectorization
Consider this following case: int __attribute__ ((noinline, noclone)) condition_reduction (int *a, int min_v) { int last = 66; /* High start value. */ for (int i = 0; i < 4; i++) if (a[i] < min_v) last = i; return last; } --param=riscv-autovec-preference=fixed-vlmax --param=riscv-autovec-lmul=m8 condition_reduction: vsetvli a4,zero,e32,m8,ta,ma li a5,32 vmv.v.x v8,a1 vl8re32.v v0,0(a0) vid.v v16 vmslt.vv v0,v0,v8 vsetvli zero,a5,e8,m2,ta,ma vcpop.m a5,v0 beq a5,zero,.L2 addi a5,a5,-1 vsetvli a4,zero,e32,m8,ta,ma vcompress.vm v8,v16,v0 vslidedown.vx v8,v8,a5 vmv.x.s a0,v8 ret .L2: li a0,66 ret --param=riscv-autovec-preference=scalable condition_reduction: csrr a6,vlenb mv a2,a0 li a3,32 li a0,66 srli a6,a6,2 vsetvli a4,zero,e32,m1,ta,ma vmv.v.x v4,a1 vid.v v1 .L4: vsetvli a5,a3,e8,mf4,tu,mu vsetvli zero,a5,e32,m1,ta,ma ----> redundant vsetvl vle32.v v0,0(a2) vsetvli a4,zero,e32,m1,ta,ma slli a1,a5,2 vmv.v.x v2,a6 vmslt.vv v0,v0,v4 sub a3,a3,a5 vmv1r.v v3,v1 vadd.vv v1,v1,v2 vsetvli zero,a5,e8,mf4,ta,ma vcpop.m a5,v0 beq a5,zero,.L3 addi a5,a5,-1 vsetvli a4,zero,e32,m1,ta,ma vcompress.vm v2,v3,v0 vslidedown.vx v2,v2,a5 vmv.x.s a0,v2 .L3: sext.w a0,a0 add a2,a2,a1 bne a3,zero,.L4 ret There is a redundant vsetvli instruction in VLA vectorized codes which is the VSETVL PASS issue. vsetvl issue is not included in this patch but will be fixed soon. gcc/ChangeLog: * config/riscv/autovec.md (len_fold_extract_last_<mode>): New pattern. * config/riscv/riscv-protos.h (enum insn_type): New enum. (expand_fold_extract_last): New function. * config/riscv/riscv-v.cc (emit_nonvlmax_slide_insn): Ditto. (emit_cpop_insn): Ditto. (emit_nonvlmax_compress_insn): Ditto. (expand_fold_extract_last): Ditto. * config/riscv/vector.md: Fix vcpop.m ratio demand. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/autovec/reduc/extract_last-1.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last-10.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last-11.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last-12.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last-13.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last-14.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last-2.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last-3.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last-4.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last-5.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last-6.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last-7.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last-8.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last-9.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last_run-1.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last_run-10.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last_run-11.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last_run-12.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last_run-13.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last_run-14.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last_run-2.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last_run-3.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last_run-4.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last_run-5.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last_run-6.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last_run-7.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last_run-8.c: New test. * gcc.target/riscv/rvv/autovec/reduc/extract_last_run-9.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/riscv/autovec.md24
-rw-r--r--gcc/config/riscv/riscv-protos.h2
-rw-r--r--gcc/config/riscv/riscv-v.cc125
-rw-r--r--gcc/config/riscv/vector.md2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-1.c20
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-10.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-11.c24
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-12.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-13.c7
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-14.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-2.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-3.c26
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-4.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-5.c8
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-6.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-7.c8
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-8.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-9.c8
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-1.c22
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-10.c4
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-11.c22
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-12.c4
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-13.c22
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-14.c4
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-2.c4
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-3.c23
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-4.c4
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-5.c23
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-6.c4
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-7.c25
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-8.c4
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-9.c23
32 files changed, 478 insertions, 6 deletions
diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index e9659b2..20ab069 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -2127,6 +2127,30 @@
})
;; -------------------------------------------------------------------------
+;; ---- [INT,FP] Extract active element
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - vcompress.vm
+;; - vcpop.m
+;; - vslidedown.vx
+;; - vmv.x.s
+;; - vfmv.f.s
+;; -------------------------------------------------------------------------
+
+(define_expand "len_fold_extract_last_<mode>"
+ [(match_operand:<VEL> 0 "register_operand")
+ (match_operand:<VEL> 1 "register_operand")
+ (match_operand:<VM> 2 "register_operand")
+ (match_operand:V 3 "register_operand")
+ (match_operand 4 "autovec_length_operand")
+ (match_operand 5 "const_0_operand")]
+ "TARGET_VECTOR"
+ {
+ riscv_vector::expand_fold_extract_last (operands);
+ DONE;
+ })
+
+;; -------------------------------------------------------------------------
;; ---- [INT] Average.
;; -------------------------------------------------------------------------
;; Implements the following "average" patterns:
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 56db7d9..0e04702 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -208,6 +208,7 @@ enum insn_type
RVV_SCATTER_M_OP = 4,
RVV_REDUCTION_OP = 3,
RVV_REDUCTION_TU_OP = RVV_REDUCTION_OP + 2,
+ RVV_CPOP = 2,
};
enum vlmul_type
{
@@ -330,6 +331,7 @@ void expand_gather_scatter (rtx *, bool);
void expand_cond_len_ternop (unsigned, rtx *);
void prepare_ternary_operands (rtx *, bool = false);
void expand_lanes_load_store (rtx *, bool);
+void expand_fold_extract_last (rtx *);
/* Rounding mode bitfield for fixed point VXRM. */
enum fixed_point_rounding_mode
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 14eda58..b783fb8 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -197,30 +197,32 @@ public:
if (m_needs_avl_p)
{
rtx len = m_vl_op;
+ machine_mode mode
+ = VECTOR_MODE_P (m_dest_mode) ? m_dest_mode : m_mask_mode;
if (m_vlmax_p)
{
- if (riscv_v_ext_vls_mode_p (m_dest_mode))
+ if (riscv_v_ext_vls_mode_p (mode))
{
/* VLS modes always set VSETVL by
"vsetvl zero, rs1/imm". */
- poly_uint64 nunits = GET_MODE_NUNITS (m_dest_mode);
+ poly_uint64 nunits = GET_MODE_NUNITS (mode);
len = gen_int_mode (nunits, Pmode);
if (!satisfies_constraint_K (len))
len = force_reg (Pmode, len);
m_vlmax_p = false; /* It has became NONVLMAX now. */
}
- else if (const_vlmax_p (m_dest_mode))
+ else if (const_vlmax_p (mode))
{
/* Optimize VLS-VLMAX code gen, we can use vsetivli instead of
the vsetvli to obtain the value of vlmax. */
- poly_uint64 nunits = GET_MODE_NUNITS (m_dest_mode);
+ poly_uint64 nunits = GET_MODE_NUNITS (mode);
len = gen_int_mode (nunits, Pmode);
m_vlmax_p = false; /* It has became NONVLMAX now. */
}
else if (can_create_pseudo_p ())
{
len = gen_reg_rtx (Pmode);
- emit_vlmax_vsetvl (m_dest_mode, len);
+ emit_vlmax_vsetvl (mode, len);
}
}
add_input_operand (len, Pmode);
@@ -848,6 +850,28 @@ emit_nonvlmax_slide_tu_insn (unsigned icode, rtx *ops, rtx avl)
e.emit_insn ((enum insn_code) icode, ops);
}
+/* This function emits a {NONVLMAX, TAIL_ANY, MASK_ANY} vsetvli
+ followed by a vslide insn (with real merge operand). */
+void
+emit_nonvlmax_slide_insn (unsigned icode, rtx *ops, rtx avl)
+{
+ machine_mode dest_mode = GET_MODE (ops[0]);
+ machine_mode mask_mode = get_mask_mode (dest_mode);
+ insn_expander<RVV_INSN_OPERANDS_MAX> e (RVV_SLIDE_OP,
+ /* HAS_DEST_P */ true,
+ /* FULLY_UNMASKED_P */ true,
+ /* USE_REAL_MERGE_P */ true,
+ /* HAS_AVL_P */ true,
+ /* VLMAX_P */ true,
+ dest_mode,
+ mask_mode);
+
+ e.set_policy (TAIL_ANY);
+ e.set_policy (MASK_ANY);
+ e.set_vl (avl);
+
+ e.emit_insn ((enum insn_code) icode, ops);
+}
/* This function emits merge instruction. */
void
@@ -1111,6 +1135,25 @@ emit_scalar_move_insn (unsigned icode, rtx *ops, rtx len)
e.emit_insn ((enum insn_code) icode, ops);
}
+/* Emit vcpop.m instruction. */
+
+static void
+emit_cpop_insn (unsigned icode, rtx *ops, rtx len)
+{
+ machine_mode dest_mode = GET_MODE (ops[0]);
+ machine_mode mask_mode = GET_MODE (ops[1]);
+ insn_expander<RVV_INSN_OPERANDS_MAX> e (RVV_CPOP,
+ /* HAS_DEST_P */ true,
+ /* FULLY_UNMASKED_P */ true,
+ /* USE_REAL_MERGE_P */ true,
+ /* HAS_AVL_P */ true,
+ /* VLMAX_P */ len ? false : true,
+ dest_mode, mask_mode);
+
+ e.set_vl (len);
+ e.emit_insn ((enum insn_code) icode, ops);
+}
+
/* Emit vmv.v.x instruction with vlmax. */
static void
@@ -1228,6 +1271,25 @@ emit_vlmax_compress_insn (unsigned icode, rtx *ops)
e.emit_insn ((enum insn_code) icode, ops);
}
+/* Emit compress instruction. */
+static void
+emit_nonvlmax_compress_insn (unsigned icode, rtx *ops, rtx avl)
+{
+ machine_mode dest_mode = GET_MODE (ops[0]);
+ machine_mode mask_mode = get_mask_mode (dest_mode);
+ insn_expander<RVV_INSN_OPERANDS_MAX> e (RVV_COMPRESS_OP,
+ /* HAS_DEST_P */ true,
+ /* FULLY_UNMASKED_P */ false,
+ /* USE_REAL_MERGE_P */ true,
+ /* HAS_AVL_P */ true,
+ /* VLMAX_P */ true, dest_mode,
+ mask_mode);
+
+ e.set_policy (TAIL_ANY);
+ e.set_vl (avl);
+ e.emit_insn ((enum insn_code) icode, ops);
+}
+
/* Emit reduction instruction. */
static void
emit_vlmax_reduction_insn (unsigned icode, int op_num, rtx *ops)
@@ -3816,4 +3878,57 @@ expand_lanes_load_store (rtx *ops, bool is_load)
}
}
+/* Expand LEN_FOLD_EXTRACT_LAST. */
+void
+expand_fold_extract_last (rtx *ops)
+{
+ rtx dst = ops[0];
+ rtx default_value = ops[1];
+ rtx mask = ops[2];
+ rtx anchor = gen_reg_rtx (Pmode);
+ rtx index = gen_reg_rtx (Pmode);
+ rtx vect = ops[3];
+ rtx else_label = gen_label_rtx ();
+ rtx end_label = gen_label_rtx ();
+ rtx len = ops[4];
+ poly_int64 value;
+ machine_mode mode = GET_MODE (vect);
+ machine_mode mask_mode = GET_MODE (mask);
+ rtx compress_vect = gen_reg_rtx (mode);
+ rtx slide_vect = gen_reg_rtx (mode);
+ insn_code icode;
+
+ if (poly_int_rtx_p (len, &value) && known_eq (value, GET_MODE_NUNITS (mode)))
+ len = NULL_RTX;
+
+ /* Calculate the number of 1-bit in mask. */
+ rtx cpop_ops[] = {anchor, mask};
+ emit_cpop_insn (code_for_pred_popcount (mask_mode, Pmode), cpop_ops, len);
+
+ riscv_expand_conditional_branch (else_label, EQ, anchor, const0_rtx);
+ emit_insn (gen_rtx_SET (index, gen_rtx_PLUS (Pmode, anchor, constm1_rtx)));
+ /* Compress the vector. */
+ icode = code_for_pred_compress (mode);
+ rtx compress_ops[] = {compress_vect, RVV_VUNDEF (mode), vect, mask};
+ if (len)
+ emit_nonvlmax_compress_insn (icode, compress_ops, len);
+ else
+ emit_vlmax_compress_insn (icode, compress_ops);
+ /* Emit the slide down to index 0 in a new vector. */
+ rtx slide_ops[] = {slide_vect, RVV_VUNDEF (mode), compress_vect, index};
+ icode = code_for_pred_slide (UNSPEC_VSLIDEDOWN, mode);
+ if (len)
+ emit_nonvlmax_slide_insn (icode, slide_ops, len);
+ else
+ emit_vlmax_slide_insn (icode, slide_ops);
+ /* Emit v(f)mv.[xf].s. */
+ emit_insn (gen_pred_extract_first (mode, dst, slide_vect));
+
+ emit_jump_insn (gen_jump (end_label));
+ emit_barrier ();
+ emit_label (else_label);
+ emit_move_insn (dst, default_value);
+ emit_label (end_label);
+}
+
} // namespace riscv_vector
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 6ceae25..a442e0f 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -417,7 +417,7 @@
vialu,vshift,vicmp,vimul,vidiv,vsalu,\
vext,viwalu,viwmul,vicalu,vnshift,\
vimuladd,vimerge,vaalu,vsmul,vsshift,\
- vnclip,viminmax,viwmuladd,vmpop,vmffs,vmsfs,\
+ vnclip,viminmax,viwmuladd,vmffs,vmsfs,\
vmiota,vmidx,vfalu,vfmul,vfminmax,vfdiv,\
vfwalu,vfwmul,vfsqrt,vfrecp,vfsgnj,vfcmp,\
vfmerge,vfcvtitof,vfcvtftoi,vfwcvtitof,\
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-1.c
new file mode 100644
index 0000000..6c86f29
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-1.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax -fno-vect-cost-model -fdump-tree-optimized" } */
+
+#define N 32
+
+/* Simple condition reduction. */
+
+int __attribute__ ((noinline, noclone))
+condition_reduction (int *a, int min_v)
+{
+ int last = 66; /* High start value. */
+
+ for (int i = 0; i < N; i++)
+ if (a[i] < min_v)
+ last = i;
+
+ return last;
+}
+
+/* { dg-final { scan-tree-dump "\.LEN_FOLD_EXTRACT_LAST" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-10.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-10.c
new file mode 100644
index 0000000..c5fe520
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-10.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=scalable -fno-vect-cost-model -fdump-tree-optimized" } */
+
+#include "extract_last-9.c"
+
+/* { dg-final { scan-tree-dump "\.LEN_FOLD_EXTRACT_LAST" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-11.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-11.c
new file mode 100644
index 0000000..85547c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-11.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax -fno-vect-cost-model -fdump-tree-optimized" } */
+
+#define N 32
+
+#ifndef TYPE
+#define TYPE float
+#endif
+
+/* Non-integer data types. */
+
+TYPE __attribute__ ((noinline, noclone))
+condition_reduction (TYPE *a, TYPE min_v)
+{
+ TYPE last = 0;
+
+ for (int i = 0; i < N; i++)
+ if (a[i] < min_v)
+ last = a[i];
+
+ return last;
+}
+
+/* { dg-final { scan-tree-dump "\.LEN_FOLD_EXTRACT_LAST" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-12.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-12.c
new file mode 100644
index 0000000..c165cb3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-12.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=scalable -fno-vect-cost-model -fdump-tree-optimized" } */
+
+#include "extract_last-11.c"
+
+/* { dg-final { scan-tree-dump "\.LEN_FOLD_EXTRACT_LAST" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-13.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-13.c
new file mode 100644
index 0000000..9a04af6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-13.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax -fno-vect-cost-model -fdump-tree-optimized" } */
+
+#define TYPE double
+#include "extract_last-11.c"
+
+/* { dg-final { scan-tree-dump "\.LEN_FOLD_EXTRACT_LAST" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-14.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-14.c
new file mode 100644
index 0000000..88f8a4c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-14.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=scalable -fno-vect-cost-model -fdump-tree-optimized" } */
+
+#include "extract_last-13.c"
+
+/* { dg-final { scan-tree-dump "\.LEN_FOLD_EXTRACT_LAST" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-2.c
new file mode 100644
index 0000000..b1eea0d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-2.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=scalable -fno-vect-cost-model -fdump-tree-optimized" } */
+
+#include "extract_last-1.c"
+
+/* { dg-final { scan-tree-dump "\.LEN_FOLD_EXTRACT_LAST" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-3.c
new file mode 100644
index 0000000..2c94ef5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-3.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax -fno-vect-cost-model -fdump-tree-optimized" } */
+
+#include <stdint-gcc.h>
+
+#if !defined(TYPE)
+#define TYPE uint32_t
+#endif
+
+#define N 254
+
+/* Non-simple condition reduction. */
+
+TYPE __attribute__ ((noinline, noclone))
+condition_reduction (TYPE *a, TYPE min_v)
+{
+ TYPE last = 65;
+
+ for (TYPE i = 0; i < N; i++)
+ if (a[i] < min_v)
+ last = a[i];
+
+ return last;
+}
+
+/* { dg-final { scan-tree-dump "\.LEN_FOLD_EXTRACT_LAST" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-4.c
new file mode 100644
index 0000000..a9ac667
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-4.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=scalable -fno-vect-cost-model -fdump-tree-optimized" } */
+
+#include "extract_last-3.c"
+
+/* { dg-final { scan-tree-dump "\.LEN_FOLD_EXTRACT_LAST" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-5.c
new file mode 100644
index 0000000..dc7fa63
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-5.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax -fno-vect-cost-model -fdump-tree-optimized" } */
+
+#define TYPE uint8_t
+
+#include "extract_last-3.c"
+
+/* { dg-final { scan-tree-dump "\.LEN_FOLD_EXTRACT_LAST" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-6.c
new file mode 100644
index 0000000..4e434a1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-6.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=scalable -fno-vect-cost-model -fdump-tree-optimized" } */
+
+#include "extract_last-5.c"
+
+/* { dg-final { scan-tree-dump "\.LEN_FOLD_EXTRACT_LAST" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-7.c
new file mode 100644
index 0000000..e75e9b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-7.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax -fno-vect-cost-model -fdump-tree-optimized" } */
+
+#define TYPE int16_t
+
+#include "extract_last-3.c"
+
+/* { dg-final { scan-tree-dump "\.LEN_FOLD_EXTRACT_LAST" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-8.c
new file mode 100644
index 0000000..a37eb26
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-8.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=scalable -fno-vect-cost-model -fdump-tree-optimized" } */
+
+#include "extract_last-7.c"
+
+/* { dg-final { scan-tree-dump "\.LEN_FOLD_EXTRACT_LAST" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-9.c
new file mode 100644
index 0000000..c7ae0d7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last-9.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax -fno-vect-cost-model -fdump-tree-optimized" } */
+
+#define TYPE uint64_t
+
+#include "extract_last-3.c"
+
+/* { dg-final { scan-tree-dump "\.LEN_FOLD_EXTRACT_LAST" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-1.c
new file mode 100644
index 0000000..c208345
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-1.c
@@ -0,0 +1,22 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=fixed-vlmax -fno-vect-cost-model" } */
+
+#include "extract_last-1.c"
+
+int __attribute__ ((optimize (1)))
+main (void)
+{
+ int a[N] = {
+ 11, -12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 1, 2, -3, 4, 5, 6, 7, -8, 9, 10,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32
+ };
+
+ int ret = condition_reduction (a, 1);
+
+ if (ret != 17)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-10.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-10.c
new file mode 100644
index 0000000..7ff435d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-10.c
@@ -0,0 +1,4 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -fno-vect-cost-model" } */
+
+#include "extract_last_run-9.c"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-11.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-11.c
new file mode 100644
index 0000000..99af6b3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-11.c
@@ -0,0 +1,22 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=fixed-vlmax -fno-vect-cost-model" } */
+
+#include "extract_last-11.c"
+
+int __attribute__ ((optimize (1)))
+main (void)
+{
+ float a[N] = {
+ 11.5, 12.2, 13.22, 14.1, 15.2, 16.3, 17, 18.7, 19, 20,
+ 1, 2, 3.3, 4.3333, 5.5, 6.23, 7, 8.63, 9, 10.6,
+ 21, 22.12, 23.55, 24.76, 25, 26, 27.34, 28.765, 29, 30,
+ 31.111, 32.322
+ };
+
+ float ret = condition_reduction (a, 16.7);
+
+ if (ret != (float) 10.6)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-12.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-12.c
new file mode 100644
index 0000000..43d1c76
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-12.c
@@ -0,0 +1,4 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -fno-vect-cost-model" } */
+
+#include "extract_last_run-11.c"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-13.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-13.c
new file mode 100644
index 0000000..1e41896
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-13.c
@@ -0,0 +1,22 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=fixed-vlmax -fno-vect-cost-model" } */
+
+#include "extract_last-13.c"
+
+int __attribute__ ((optimize (1)))
+main (void)
+{
+ double a[N] = {
+ 11.5, 12.2, 13.22, 14.1, 15.2, 16.3, 17, 18.7, 19, 20,
+ 1, 2, 3.3, 4.3333, 5.5, 6.23, 7, 8.63, 9, 10.6,
+ 21, 22.12, 23.55, 24.76, 25, 26, 27.34, 28.765, 29, 30,
+ 31.111, 32.322
+ };
+
+ double ret = condition_reduction (a, 16.7);
+
+ if (ret != 10.6)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-14.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-14.c
new file mode 100644
index 0000000..535b68f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-14.c
@@ -0,0 +1,4 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -fno-vect-cost-model" } */
+
+#include "extract_last_run-13.c"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-2.c
new file mode 100644
index 0000000..ee53bf9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-2.c
@@ -0,0 +1,4 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -fno-vect-cost-model" } */
+
+#include "extract_last_run-1.c"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-3.c
new file mode 100644
index 0000000..ff2b025
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-3.c
@@ -0,0 +1,23 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=fixed-vlmax -fno-vect-cost-model" } */
+
+#include "extract_last-3.c"
+
+int __attribute__ ((optimize (1)))
+main (void)
+{
+ TYPE a[N] = {
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32
+ };
+ __builtin_memset (a + 32, 43, (N - 32) * sizeof (TYPE));
+
+ TYPE ret = condition_reduction (a, 16);
+
+ if (ret != 10)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-4.c
new file mode 100644
index 0000000..4b5b633
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-4.c
@@ -0,0 +1,4 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -fno-vect-cost-model" } */
+
+#include "extract_last_run-3.c"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-5.c
new file mode 100644
index 0000000..7b66b24
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-5.c
@@ -0,0 +1,23 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=fixed-vlmax -fno-vect-cost-model" } */
+
+#include "extract_last-5.c"
+
+int __attribute__ ((optimize (1)))
+main (void)
+{
+ TYPE a[N] = {
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32
+ };
+ __builtin_memset (a + 32, 43, (N - 32) * sizeof (TYPE));
+
+ TYPE ret = condition_reduction (a, 16);
+
+ if (ret != 10)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-6.c
new file mode 100644
index 0000000..a52eac9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-6.c
@@ -0,0 +1,4 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -fno-vect-cost-model" } */
+
+#include "extract_last_run-5.c"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-7.c
new file mode 100644
index 0000000..a1ac4a5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-7.c
@@ -0,0 +1,25 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=fixed-vlmax -fno-vect-cost-model" } */
+
+#include "extract_last-7.c"
+
+extern void abort (void) __attribute__ ((noreturn));
+
+int __attribute__ ((optimize (1)))
+main (void)
+{
+ TYPE a[N] = {
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32
+ };
+ __builtin_memset (a+32, 43, (N-32)*sizeof (TYPE));
+
+ TYPE ret = condition_reduction (a, 16);
+
+ if (ret != 10)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-8.c
new file mode 100644
index 0000000..56858f9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-8.c
@@ -0,0 +1,4 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -fno-vect-cost-model" } */
+
+#include "extract_last_run-7.c"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-9.c
new file mode 100644
index 0000000..67672bf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/extract_last_run-9.c
@@ -0,0 +1,23 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=fixed-vlmax -fno-vect-cost-model" } */
+
+#include "extract_last-9.c"
+
+int __attribute__ ((optimize (1)))
+main (void)
+{
+ TYPE a[N] = {
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32
+ };
+ __builtin_memset (a + 32, 43, (N - 32) * sizeof (TYPE));
+
+ TYPE ret = condition_reduction (a, 16);
+
+ if (ret != 10)
+ __builtin_abort ();
+
+ return 0;
+}