On Mon, Aug 21, 2023 at 10:42 PM Lehua Ding <lehua.d...@rivai.ai> wrote: > > Hi, > > This patch add conditional unary neg/abs/not autovec patterns to RISC-V > backend. > Consider this C code: > > void > test_3 (float *__restrict a, float *__restrict b, int *__restrict pred, int n) > { > for (int i = 0; i < n; i += 1) > { > a[i] = pred[i] ? __builtin_fabsf (b[i]) : a[i]; > } > } > > Before this patch: > ... > vsetvli a7,zero,e32,m1,ta,ma > vfabs.v v2,v2 > vmerge.vvm v1,v1,v2,v0 > ... > > After this patch: > ... > vsetvli a7,zero,e32,m1,ta,mu > vfabs.v v1,v2,v0.t > ... > > For int neg/abs/not and FP neg patterns, Defining the corresponding cond_xxx > paterns is enough.
Maybe we should add optabs and IFN support for conditional ABS too. I added it for conditional not with r14-3257-ga32de58c9e63 to fix up a regression I had introduced with SVE code. Thanks, Andrew > For the FP abs pattern, We need to change the definition of `abs<mode>2` and > `@vcond_mask_<mode><vm>` pattern from define_expand to define_insn_and_split > in order to fuse them into a new pattern `*cond_abs<mode>` at the combine > pass. > After changing the pattern of neg, a vlmax copysin + neg fusion pattern needs > to be added. > > A fusion process similar to the one below: > > (insn 30 29 31 4 (set (reg:RVVM1SF 152 [ vect_iftmp.15 ]) > (abs:RVVM1SF (reg:RVVM1SF 137 [ vect__6.14 ]))) "float.c":15:56 > discrim 1 12799 {absrvvm1sf2} > (expr_list:REG_DEAD (reg:RVVM1SF 137 [ vect__6.14 ]) > (nil))) > > (insn 31 30 32 4 (set (reg:RVVM1SF 140 [ vect_iftmp.19 ]) > (if_then_else:RVVM1SF (reg:RVVMF32BI 136 [ mask__27.11 ]) > (reg:RVVM1SF 152 [ vect_iftmp.15 ]) > (reg:RVVM1SF 139 [ vect_iftmp.18 ]))) 12707 > {vcond_mask_rvvm1sfrvvmf32bi} > (expr_list:REG_DEAD (reg:RVVM1SF 152 [ vect_iftmp.15 ]) > (expr_list:REG_DEAD (reg:RVVM1SF 139 [ vect_iftmp.18 ]) > (expr_list:REG_DEAD (reg:RVVMF32BI 136 [ mask__27.11 ]) > (nil))))) > ==> > > (insn 31 30 32 4 (set (reg:RVVM1SF 140 [ vect_iftmp.19 ]) > (if_then_else:RVVM1SF (reg:RVVMF32BI 136 [ mask__27.11 ]) > (abs:RVVM1SF (reg:RVVM1SF 137 [ vect__6.14 ])) > (reg:RVVM1SF 139 [ vect_iftmp.18 ]))) 13444 {*cond_absrvvm1sf} > (expr_list:REG_DEAD (reg:RVVM1SF 137 [ vect__6.14 ]) > (expr_list:REG_DEAD (reg:RVVMF32BI 136 [ mask__27.11 ]) > (expr_list:REG_DEAD (reg:RVVM1SF 139 [ vect_iftmp.18 ]) > (nil))))) > > Best, > Lehua > > gcc/ChangeLog: > > * config/riscv/autovec-opt.md (*cond_abs<mode>): New combine pattern. > (*copysign<mode>_neg): Ditto. > * config/riscv/autovec.md (@vcond_mask_<mode><vm>): Adjust. > (<optab><mode>2): Ditto. > (cond_<optab><mode>): New. > (cond_len_<optab><mode>): Ditto. > * config/riscv/riscv-protos.h (enum insn_type): New. > (expand_cond_len_unop): New helper func. > * config/riscv/riscv-v.cc (shuffle_merge_patterns): Adjust. > (expand_cond_len_unop): New helper func. > > gcc/testsuite/ChangeLog: > > * gcc.target/riscv/rvv/autovec/cond/cond_unary_1.c: New test. > * gcc.target/riscv/rvv/autovec/cond/cond_unary_1_run.c: New test. > * gcc.target/riscv/rvv/autovec/cond/cond_unary_2.c: New test. > * gcc.target/riscv/rvv/autovec/cond/cond_unary_2_run.c: New test. > * gcc.target/riscv/rvv/autovec/cond/cond_unary_3.c: New test. > * gcc.target/riscv/rvv/autovec/cond/cond_unary_3_run.c: New test. > * gcc.target/riscv/rvv/autovec/cond/cond_unary_4.c: New test. > * gcc.target/riscv/rvv/autovec/cond/cond_unary_4_run.c: New test. > * gcc.target/riscv/rvv/autovec/cond/cond_unary_5.c: New test. > * gcc.target/riscv/rvv/autovec/cond/cond_unary_5_run.c: New test. > * gcc.target/riscv/rvv/autovec/cond/cond_unary_6.c: New test. > * gcc.target/riscv/rvv/autovec/cond/cond_unary_6_run.c: New test. > * gcc.target/riscv/rvv/autovec/cond/cond_unary_7.c: New test. > * gcc.target/riscv/rvv/autovec/cond/cond_unary_7_run.c: New test. > * gcc.target/riscv/rvv/autovec/cond/cond_unary_8.c: New test. > * gcc.target/riscv/rvv/autovec/cond/cond_unary_8_run.c: New test. > > --- > gcc/config/riscv/autovec-opt.md | 39 ++++++++ > gcc/config/riscv/autovec.md | 97 +++++++++++++++++-- > gcc/config/riscv/riscv-protos.h | 7 +- > gcc/config/riscv/riscv-v.cc | 56 ++++++++++- > .../riscv/rvv/autovec/cond/cond_unary_1.c | 43 ++++++++ > .../riscv/rvv/autovec/cond/cond_unary_1_run.c | 27 ++++++ > .../riscv/rvv/autovec/cond/cond_unary_2.c | 47 +++++++++ > .../riscv/rvv/autovec/cond/cond_unary_2_run.c | 28 ++++++ > .../riscv/rvv/autovec/cond/cond_unary_3.c | 43 ++++++++ > .../riscv/rvv/autovec/cond/cond_unary_3_run.c | 27 ++++++ > .../riscv/rvv/autovec/cond/cond_unary_4.c | 43 ++++++++ > .../riscv/rvv/autovec/cond/cond_unary_4_run.c | 27 ++++++ > .../riscv/rvv/autovec/cond/cond_unary_5.c | 37 +++++++ > .../riscv/rvv/autovec/cond/cond_unary_5_run.c | 26 +++++ > .../riscv/rvv/autovec/cond/cond_unary_6.c | 41 ++++++++ > .../riscv/rvv/autovec/cond/cond_unary_6_run.c | 27 ++++++ > .../riscv/rvv/autovec/cond/cond_unary_7.c | 37 +++++++ > .../riscv/rvv/autovec/cond/cond_unary_7_run.c | 26 +++++ > .../riscv/rvv/autovec/cond/cond_unary_8.c | 37 +++++++ > .../riscv/rvv/autovec/cond/cond_unary_8_run.c | 28 ++++++ > 20 files changed, 730 insertions(+), 13 deletions(-) > create mode 100644 > gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_1.c > create mode 100644 > gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_1_run.c > create mode 100644 > gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_2.c > create mode 100644 > gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_2_run.c > create mode 100644 > gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_3.c > create mode 100644 > gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_3_run.c > create mode 100644 > gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_4.c > create mode 100644 > gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_4_run.c > create mode 100644 > gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_5.c > create mode 100644 > gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_5_run.c > create mode 100644 > gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_6.c > create mode 100644 > gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_6_run.c > create mode 100644 > gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_7.c > create mode 100644 > gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_7_run.c > create mode 100644 > gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_8.c > create mode 100644 > gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_8_run.c > > diff --git a/gcc/config/riscv/autovec-opt.md b/gcc/config/riscv/autovec-opt.md > index 99b609a99d9..8247eb87ddb 100644 > --- a/gcc/config/riscv/autovec-opt.md > +++ b/gcc/config/riscv/autovec-opt.md > @@ -684,3 +684,42 @@ > } > [(set_attr "type" "vfwmuladd") > (set_attr "mode" "<V_DOUBLE_TRUNC>")]) > + > +;; Combine <op> and vcond_mask generated by midend into cond_len_<op> > +;; Currently supported operations: > +;; abs(FP) > +(define_insn_and_split "*cond_abs<mode>" > + [(set (match_operand:VF 0 "register_operand") > + (if_then_else:VF > + (match_operand:<VM> 3 "register_operand") > + (abs:VF (match_operand:VF 1 "nonmemory_operand")) > + (match_operand:VF 2 "register_operand")))] > + "TARGET_VECTOR && can_create_pseudo_p ()" > + "#" > + "&& 1" > + [(const_int 0)] > +{ > + emit_insn (gen_cond_len_abs<mode> (operands[0], operands[3], operands[1], > + operands[2], > + gen_int_mode (GET_MODE_NUNITS > (<MODE>mode), Pmode), > + const0_rtx)); > + DONE; > +}) > + > +;; Combine vlmax neg and UNSPEC_VCOPYSIGN > +(define_insn_and_split "*copysign<mode>_neg" > + [(set (match_operand:VF 0 "register_operand") > + (neg:VF > + (unspec:VF [ > + (match_operand:VF 1 "register_operand") > + (match_operand:VF 2 "register_operand") > + ] UNSPEC_VCOPYSIGN)))] > + "TARGET_VECTOR && can_create_pseudo_p ()" > + "#" > + "&& 1" > + [(const_int 0)] > +{ > + riscv_vector::emit_vlmax_insn (code_for_pred_ncopysign (<MODE>mode), > + riscv_vector::RVV_BINOP, operands); > + DONE; > +}) > diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md > index acca4c22b90..e1addc07036 100644 > --- a/gcc/config/riscv/autovec.md > +++ b/gcc/config/riscv/autovec.md > @@ -552,12 +552,16 @@ > ;; - vfmerge.vf > ;; ------------------------------------------------------------------------- > > -(define_expand "@vcond_mask_<mode><vm>" > - [(match_operand:V 0 "register_operand") > - (match_operand:<VM> 3 "register_operand") > - (match_operand:V 1 "nonmemory_operand") > - (match_operand:V 2 "register_operand")] > - "TARGET_VECTOR" > +(define_insn_and_split "@vcond_mask_<mode><vm>" > + [(set (match_operand:V 0 "register_operand") > + (if_then_else:V > + (match_operand:<VM> 3 "register_operand") > + (match_operand:V 1 "nonmemory_operand") > + (match_operand:V 2 "register_operand")))] > + "TARGET_VECTOR && can_create_pseudo_p ()" > + "#" > + "&& 1" > + [(const_int 0)] > { > /* The order of vcond_mask is opposite to pred_merge. */ > std::swap (operands[1], operands[2]); > @@ -979,11 +983,14 @@ > ;; Includes: > ;; - vfneg.v/vfabs.v > ;; > ------------------------------------------------------------------------------- > -(define_expand "<optab><mode>2" > +(define_insn_and_split "<optab><mode>2" > [(set (match_operand:VF 0 "register_operand") > (any_float_unop_nofrm:VF > (match_operand:VF 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::RVV_UNOP, operands); > @@ -1499,6 +1506,80 @@ > DONE; > }) > > +;; ------------------------------------------------------------------------- > +;; ---- [INT] Conditional unary operations > +;; ------------------------------------------------------------------------- > +;; Includes: > +;; - vneg/vnot > +;; ------------------------------------------------------------------------- > + > +(define_expand "cond_<optab><mode>" > + [(match_operand:VI 0 "register_operand") > + (match_operand:<VM> 1 "vector_mask_operand") > + (any_int_unop:VI > + (match_operand:VI 2 "register_operand")) > + (match_operand:VI 3 "register_operand")] > + "TARGET_VECTOR" > +{ > + /* Normalize into cond_len_* operations. */ > + emit_insn (gen_cond_len_<optab><mode> (operands[0], operands[1], > operands[2], > + operands[3], > + gen_int_mode (GET_MODE_NUNITS > (<MODE>mode), Pmode), > + const0_rtx)); > + DONE; > +}) > + > +(define_expand "cond_len_<optab><mode>" > + [(match_operand:VI 0 "register_operand") > + (match_operand:<VM> 1 "vector_mask_operand") > + (any_int_unop:VI > + (match_operand:VI 2 "register_operand")) > + (match_operand:VI 3 "register_operand") > + (match_operand 4 "autovec_length_operand") > + (match_operand 5 "const_0_operand")] > + "TARGET_VECTOR" > +{ > + riscv_vector::expand_cond_len_unop (<CODE>, operands); > + DONE; > +}) > + > +;; ------------------------------------------------------------------------- > +;; ---- [FP] Conditional unary operations > +;; ------------------------------------------------------------------------- > +;; Includes: > +;; - vfneg/vfabs > +;; ------------------------------------------------------------------------- > + > +(define_expand "cond_<optab><mode>" > + [(match_operand:VF 0 "register_operand") > + (match_operand:<VM> 1 "vector_mask_operand") > + (any_float_unop_nofrm:VF > + (match_operand:VF 2 "register_operand")) > + (match_operand:VF 3 "register_operand")] > + "TARGET_VECTOR" > +{ > + /* Normalize into cond_len_* operations. */ > + emit_insn (gen_cond_len_<optab><mode> (operands[0], operands[1], > operands[2], > + operands[3], > + gen_int_mode (GET_MODE_NUNITS > (<MODE>mode), Pmode), > + const0_rtx)); > + DONE; > +}) > + > +(define_expand "cond_len_<optab><mode>" > + [(match_operand:VF 0 "register_operand") > + (match_operand:<VM> 1 "vector_mask_operand") > + (any_float_unop_nofrm:VF > + (match_operand:VF 2 "register_operand")) > + (match_operand:VF 3 "register_operand") > + (match_operand 4 "autovec_length_operand") > + (match_operand 5 "const_0_operand")] > + "TARGET_VECTOR" > +{ > + riscv_vector::expand_cond_len_unop (<CODE>, operands); > + DONE; > +}) > + > ;; ------------------------------------------------------------------------- > ;; ---- [INT] Conditional binary operations > ;; ------------------------------------------------------------------------- > diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h > index 472c00dc439..2c4405c9860 100644 > --- a/gcc/config/riscv/riscv-protos.h > +++ b/gcc/config/riscv/riscv-protos.h > @@ -184,6 +184,10 @@ enum insn_type > { > RVV_MISC_OP = 1, > RVV_UNOP = 2, > + RVV_UNOP_M = RVV_UNOP + 2, > + RVV_UNOP_MU = RVV_UNOP + 2, > + RVV_UNOP_TU = RVV_UNOP + 2, > + RVV_UNOP_TUMU = RVV_UNOP + 2, > RVV_BINOP = 3, > RVV_BINOP_MU = RVV_BINOP + 2, > RVV_BINOP_TU = RVV_BINOP + 2, > @@ -191,8 +195,6 @@ enum insn_type > RVV_MERGE_OP = 4, > RVV_CMP_OP = 4, > RVV_CMP_MU_OP = RVV_CMP_OP + 2, /* +2 means mask and maskoff operand. */ > - RVV_UNOP_MU = RVV_UNOP + 2, /* Likewise. */ > - RVV_UNOP_M = RVV_UNOP + 2, /* Likewise. */ > RVV_TERNOP = 5, > RVV_TERNOP_MU = RVV_TERNOP + 1, > RVV_TERNOP_TU = RVV_TERNOP + 1, > @@ -294,6 +296,7 @@ bool neg_simm5_p (rtx); > bool has_vi_variant_p (rtx_code, rtx); > void expand_vec_cmp (rtx, rtx_code, rtx, rtx); > bool expand_vec_cmp_float (rtx, rtx_code, rtx, rtx, bool); > +void expand_cond_len_unop (rtx_code, rtx *); > void expand_cond_len_binop (rtx_code, rtx *); > void expand_reduction (rtx_code, rtx *, rtx, > reduction_type = reduction_type::UNORDERED); > diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc > index b01028c6201..14eda581d00 100644 > --- a/gcc/config/riscv/riscv-v.cc > +++ b/gcc/config/riscv/riscv-v.cc > @@ -2992,7 +2992,9 @@ shuffle_merge_patterns (struct expand_vec_perm_d *d) > emit_vlmax_cmp_insn (icode, ops); > > /* TARGET = MASK ? OP0 : OP1. */ > - emit_insn (gen_vcond_mask (vmode, vmode, d->target, d->op0, d->op1, mask)); > + /* swap op0 and op1 since the order is opposite to pred_merge. */ > + rtx ops2[] = {d->target, d->op1, d->op0, mask}; > + emit_vlmax_merge_insn (code_for_pred_merge (vmode), > riscv_vector::RVV_MERGE_OP, ops2); > return true; > } > > @@ -3384,10 +3386,58 @@ needs_fp_rounding (rtx_code code, machine_mode mode) > { > if (!FLOAT_MODE_P (mode)) > return false; > - return code != SMIN && code != SMAX; > + return code != SMIN && code != SMAX && code != NEG && code != ABS; > } > > -/* Expand COND_LEN_*. */ > +/* Expand unary ops COND_LEN_*. */ > +void > +expand_cond_len_unop (rtx_code code, rtx *ops) > +{ > + rtx dest = ops[0]; > + rtx mask = ops[1]; > + rtx src = ops[2]; > + rtx merge = ops[3]; > + rtx len = ops[4]; > + machine_mode mode = GET_MODE (dest); > + machine_mode mask_mode = GET_MODE (mask); > + > + poly_int64 value; > + bool is_dummy_mask = rtx_equal_p (mask, CONSTM1_RTX (mask_mode)); > + bool is_vlmax_len > + = poly_int_rtx_p (len, &value) && known_eq (value, GET_MODE_NUNITS > (mode)); > + rtx cond_ops[] = {dest, mask, merge, src}; > + insn_code icode = code_for_pred (code, mode); > + > + if (is_dummy_mask) > + { > + /* Use TU, MASK ANY policy. */ > + if (needs_fp_rounding (code, mode)) > + emit_nonvlmax_fp_tu_insn (icode, RVV_UNOP_TU, cond_ops, len); > + else > + emit_nonvlmax_tu_insn (icode, RVV_UNOP_TU, cond_ops, len); > + } > + else > + { > + if (is_vlmax_len) > + { > + /* Use TAIL ANY, MU policy. */ > + if (needs_fp_rounding (code, mode)) > + emit_vlmax_masked_fp_mu_insn (icode, RVV_UNOP_MU, cond_ops); > + else > + emit_vlmax_masked_mu_insn (icode, RVV_UNOP_MU, cond_ops); > + } > + else > + { > + /* Use TU, MU policy. */ > + if (needs_fp_rounding (code, mode)) > + emit_nonvlmax_fp_tumu_insn (icode, RVV_UNOP_TUMU, cond_ops, len); > + else > + emit_nonvlmax_tumu_insn (icode, RVV_UNOP_TUMU, cond_ops, len); > + } > + } > +} > + > +/* Expand binary ops COND_LEN_*. */ > void > expand_cond_len_binop (rtx_code code, rtx *ops) > { > diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_1.c > b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_1.c > new file mode 100644 > index 00000000000..e8bf41a55a1 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_1.c > @@ -0,0 +1,43 @@ > +/* { dg-do compile } */ > +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d --param > riscv-autovec-preference=scalable -fno-vect-cost-model" } */ > + > +#include <stdint.h> > + > +#define abs(A) ((A) < 0 ? -(A) : (A)) > +#define neg(A) (-(A)) > +#define not(A) (~(A)) > + > +#define DEF_LOOP(TYPE, OP) \ > + void __attribute__ ((noipa)) \ > + test_##TYPE##_##OP (TYPE *__restrict r, TYPE *__restrict a, \ > + TYPE *__restrict pred, int n) \ > + { \ > + for (int i = 0; i < n; ++i) \ > + r[i] = pred[i] ? OP (a[i]) : a[i]; \ > + } > + > +#define TEST_INT_TYPE(T, TYPE) \ > + T (TYPE, abs) \ > + T (TYPE, neg) \ > + T (TYPE, not) > + > +#define TEST_FLOAT_TYPE(T, TYPE, SUFFIX) \ > + T (TYPE, __builtin_fabs##SUFFIX) \ > + T (TYPE, neg) > + > +#define TEST_ALL(T) \ > + TEST_INT_TYPE (T, int8_t) \ > + TEST_INT_TYPE (T, int16_t) \ > + TEST_INT_TYPE (T, int32_t) \ > + TEST_INT_TYPE (T, int64_t) \ > + TEST_FLOAT_TYPE (T, _Float16, f16) \ > + TEST_FLOAT_TYPE (T, float, f) \ > + TEST_FLOAT_TYPE (T, double, ) > + > +TEST_ALL (DEF_LOOP) > + > +/* NOTE: int abs operator is converted to vmslt + vneg.v */ > +/* { dg-final { scan-assembler-times {\tvneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 8 } > } */ > +/* { dg-final { scan-assembler-times {\tvnot\.v\tv[0-9]+,v[0-9]+,v0\.t} 4 } > } */ > +/* { dg-final { scan-assembler-times {\tvfabs\.v\tv[0-9]+,v[0-9]+,v0\.t} 3 } > } */ > +/* { dg-final { scan-assembler-times {\tvfneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 3 } > } */ > diff --git > a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_1_run.c > b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_1_run.c > new file mode 100644 > index 00000000000..90f1c1a71e7 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_1_run.c > @@ -0,0 +1,27 @@ > +/* { dg-do run { target { riscv_vector } } } */ > +/* { dg-additional-options "--param riscv-autovec-preference=scalable > -fno-vect-cost-model" } */ > + > +#include "cond_unary_1.c" > + > +#define N 99 > + > +#define TEST_LOOP(TYPE, OP) \ > + { \ > + TYPE r[N], a[N], pred[N]; \ > + for (int i = 0; i < N; ++i) \ > + { \ > + a[i] = (i & 1 ? i : 3 * i) * (i % 3 == 0 ? 1 : -1); \ > + pred[i] = (i % 7 < 4); \ > + asm volatile ("" ::: "memory"); \ > + } \ > + test_##TYPE##_##OP (r, a, pred, N); \ > + for (int i = 0; i < N; ++i) \ > + if (r[i] != (pred[i] ? OP (a[i]) : a[i])) \ > + __builtin_abort (); \ > + } > + > +int main () > +{ > + TEST_ALL (TEST_LOOP) > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_2.c > b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_2.c > new file mode 100644 > index 00000000000..fb984ded12f > --- /dev/null > +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_2.c > @@ -0,0 +1,47 @@ > +/* { dg-do compile } */ > +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d --param > riscv-autovec-preference=scalable -fno-vect-cost-model" } */ > + > +#include <stdint.h> > + > +#define abs(A) ((A) < 0 ? -(A) : (A)) > +#define neg(A) (-(A)) > +#define not(A) (~(A)) > + > +#define DEF_LOOP(TYPE, OP) \ > + void __attribute__ ((noipa)) \ > + test_##TYPE##_##OP (TYPE *__restrict r, TYPE *__restrict a, \ > + TYPE *__restrict b, \ > + TYPE *__restrict pred, int n) \ > + { \ > + for (int i = 0; i < n; ++i) \ > + { \ > + TYPE bi = b[i]; \ > + r[i] = pred[i] ? OP (a[i]) : bi; \ > + } \ > + } > + > +#define TEST_INT_TYPE(T, TYPE) \ > + T (TYPE, abs) \ > + T (TYPE, neg) \ > + T (TYPE, not) > + > +#define TEST_FLOAT_TYPE(T, TYPE, SUFFIX) \ > + T (TYPE, __builtin_fabs##SUFFIX) \ > + T (TYPE, neg) > + > +#define TEST_ALL(T) \ > + TEST_INT_TYPE (T, int8_t) \ > + TEST_INT_TYPE (T, int16_t) \ > + TEST_INT_TYPE (T, int32_t) \ > + TEST_INT_TYPE (T, int64_t) \ > + TEST_FLOAT_TYPE (T, _Float16, f16) \ > + TEST_FLOAT_TYPE (T, float, f) \ > + TEST_FLOAT_TYPE (T, double, ) > + > +TEST_ALL (DEF_LOOP) > + > +/* NOTE: int abs operator is converted to vmslt + vneg.v */ > +/* { dg-final { scan-assembler-times {\tvneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 8 } > } */ > +/* { dg-final { scan-assembler-times {\tvnot\.v\tv[0-9]+,v[0-9]+,v0\.t} 4 } > } */ > +/* { dg-final { scan-assembler-times {\tvfabs\.v\tv[0-9]+,v[0-9]+,v0\.t} 3 } > } */ > +/* { dg-final { scan-assembler-times {\tvfneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 3 } > } */ > diff --git > a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_2_run.c > b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_2_run.c > new file mode 100644 > index 00000000000..b739c5d8df2 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_2_run.c > @@ -0,0 +1,28 @@ > +/* { dg-do run { target { riscv_vector } } } */ > +/* { dg-additional-options "--param riscv-autovec-preference=scalable > -fno-vect-cost-model" } */ > + > +#include "cond_unary_2.c" > + > +#define N 99 > + > +#define TEST_LOOP(TYPE, OP) \ > + { \ > + TYPE r[N], a[N], b[N], pred[N]; \ > + for (int i = 0; i < N; ++i) \ > + { \ > + a[i] = (i & 1 ? i : 3 * i) * (i % 3 == 0 ? 1 : -1); \ > + b[i] = (i % 9) * (i % 7 + 1); \ > + pred[i] = (i % 7 < 4); \ > + asm volatile ("" ::: "memory"); \ > + } \ > + test_##TYPE##_##OP (r, a, b, pred, N); \ > + for (int i = 0; i < N; ++i) \ > + if (r[i] != (pred[i] ? OP (a[i]) : b[i])) \ > + __builtin_abort (); \ > + } > + > +int main () > +{ > + TEST_ALL (TEST_LOOP) > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_3.c > b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_3.c > new file mode 100644 > index 00000000000..a1aeaf076de > --- /dev/null > +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_3.c > @@ -0,0 +1,43 @@ > +/* { dg-do compile } */ > +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d --param > riscv-autovec-preference=scalable -fno-vect-cost-model" } */ > + > +#include <stdint.h> > + > +#define abs(A) ((A) < 0 ? -(A) : (A)) > +#define neg(A) (-(A)) > +#define not(A) (~(A)) > + > +#define DEF_LOOP(TYPE, OP) \ > + void __attribute__ ((noipa)) \ > + test_##TYPE##_##OP (TYPE *__restrict r, TYPE *__restrict a, \ > + TYPE *__restrict pred, int n) \ > + { \ > + for (int i = 0; i < n; ++i) \ > + r[i] = pred[i] ? OP (a[i]) : 5; \ > + } > + > +#define TEST_INT_TYPE(T, TYPE) \ > + T (TYPE, abs) \ > + T (TYPE, neg) \ > + T (TYPE, not) > + > +#define TEST_FLOAT_TYPE(T, TYPE, SUFFIX) \ > + T (TYPE, __builtin_fabs##SUFFIX) \ > + T (TYPE, neg) > + > +#define TEST_ALL(T) \ > + TEST_INT_TYPE (T, int8_t) \ > + TEST_INT_TYPE (T, int16_t) \ > + TEST_INT_TYPE (T, int32_t) \ > + TEST_INT_TYPE (T, int64_t) \ > + TEST_FLOAT_TYPE (T, _Float16, f16) \ > + TEST_FLOAT_TYPE (T, float, f) \ > + TEST_FLOAT_TYPE (T, double, ) > + > +TEST_ALL (DEF_LOOP) > + > +/* NOTE: int abs operator is converted to vmslt + vneg.v */ > +/* { dg-final { scan-assembler-times {\tvneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 8 } > } */ > +/* { dg-final { scan-assembler-times {\tvnot\.v\tv[0-9]+,v[0-9]+,v0\.t} 4 } > } */ > +/* { dg-final { scan-assembler-times {\tvfabs\.v\tv[0-9]+,v[0-9]+,v0\.t} 3 } > } */ > +/* { dg-final { scan-assembler-times {\tvfneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 3 } > } */ > diff --git > a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_3_run.c > b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_3_run.c > new file mode 100644 > index 00000000000..9234c94d9bf > --- /dev/null > +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_3_run.c > @@ -0,0 +1,27 @@ > +/* { dg-do run { target { riscv_vector } } } */ > +/* { dg-additional-options "--param riscv-autovec-preference=scalable > -fno-vect-cost-model" } */ > + > +#include "cond_unary_3.c" > + > +#define N 99 > + > +#define TEST_LOOP(TYPE, OP) \ > + { \ > + TYPE r[N], a[N], pred[N]; \ > + for (int i = 0; i < N; ++i) \ > + { \ > + a[i] = (i & 1 ? i : 3 * i) * (i % 3 == 0 ? 1 : -1); \ > + pred[i] = (i % 7 < 4); \ > + asm volatile ("" ::: "memory"); \ > + } \ > + test_##TYPE##_##OP (r, a, pred, N); \ > + for (int i = 0; i < N; ++i) \ > + if (r[i] != (pred[i] ? OP (a[i]) : 5)) \ > + __builtin_abort (); \ > + } > + > +int main () > +{ > + TEST_ALL (TEST_LOOP) > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_4.c > b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_4.c > new file mode 100644 > index 00000000000..ed041fe28cd > --- /dev/null > +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_4.c > @@ -0,0 +1,43 @@ > +/* { dg-do compile } */ > +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d --param > riscv-autovec-preference=scalable -fno-vect-cost-model" } */ > + > +#include <stdint.h> > + > +#define abs(A) ((A) < 0 ? -(A) : (A)) > +#define neg(A) (-(A)) > +#define not(A) (~(A)) > + > +#define DEF_LOOP(TYPE, OP) \ > + void __attribute__ ((noipa)) \ > + test_##TYPE##_##OP (TYPE *__restrict r, TYPE *__restrict a, \ > + TYPE *__restrict pred, int n) \ > + { \ > + for (int i = 0; i < n; ++i) \ > + r[i] = pred[i] ? OP (a[i]) : 0; \ > + } > + > +#define TEST_INT_TYPE(T, TYPE) \ > + T (TYPE, abs) \ > + T (TYPE, neg) \ > + T (TYPE, not) > + > +#define TEST_FLOAT_TYPE(T, TYPE, SUFFIX) \ > + T (TYPE, __builtin_fabs##SUFFIX) \ > + T (TYPE, neg) > + > +#define TEST_ALL(T) \ > + TEST_INT_TYPE (T, int8_t) \ > + TEST_INT_TYPE (T, int16_t) \ > + TEST_INT_TYPE (T, int32_t) \ > + TEST_INT_TYPE (T, int64_t) \ > + TEST_FLOAT_TYPE (T, _Float16, f16) \ > + TEST_FLOAT_TYPE (T, float, f) \ > + TEST_FLOAT_TYPE (T, double, ) > + > +TEST_ALL (DEF_LOOP) > + > +/* NOTE: int abs operator is converted to vmslt + vneg.v */ > +/* { dg-final { scan-assembler-times {\tvneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 8 } > } */ > +/* { dg-final { scan-assembler-times {\tvnot\.v\tv[0-9]+,v[0-9]+,v0\.t} 4 } > } */ > +/* { dg-final { scan-assembler-times {\tvfabs\.v\tv[0-9]+,v[0-9]+,v0\.t} 3 } > } */ > +/* { dg-final { scan-assembler-times {\tvfneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 3 } > } */ > diff --git > a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_4_run.c > b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_4_run.c > new file mode 100644 > index 00000000000..52fd4d07be9 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_4_run.c > @@ -0,0 +1,27 @@ > +/* { dg-do run { target { riscv_vector } } } */ > +/* { dg-additional-options "--param riscv-autovec-preference=scalable > -fno-vect-cost-model" } */ > + > +#include "cond_unary_4.c" > + > +#define N 99 > + > +#define TEST_LOOP(TYPE, OP) \ > + { \ > + TYPE r[N], a[N], pred[N]; \ > + for (int i = 0; i < N; ++i) \ > + { \ > + a[i] = (i & 1 ? i : 3 * i) * (i % 3 == 0 ? 1 : -1); \ > + pred[i] = (i % 7 < 4); \ > + asm volatile ("" ::: "memory"); \ > + } \ > + test_##TYPE##_##OP (r, a, pred, N); \ > + for (int i = 0; i < N; ++i) \ > + if (r[i] != (pred[i] ? OP (a[i]) : 0)) \ > + __builtin_abort (); \ > + } > + > +int main () > +{ > + TEST_ALL (TEST_LOOP) > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_5.c > b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_5.c > new file mode 100644 > index 00000000000..6c0a25aad6b > --- /dev/null > +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_5.c > @@ -0,0 +1,37 @@ > +/* { dg-do compile } */ > +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d --param > riscv-autovec-preference=scalable -fno-vect-cost-model" } */ > + > +#include <stdint.h> > + > +#define abs(A) ((A) < 0 ? -(A) : (A)) > +#define neg(A) (-(A)) > +#define not(A) (~(A)) > + > +#define DEF_LOOP(TYPE1, TYPE2, COUNT, OP) \ > + void __attribute__ ((noipa)) \ > + test_##TYPE1##_##TYPE2##_##OP (TYPE2 *__restrict r, \ > + TYPE2 *__restrict a, \ > + TYPE1 *__restrict pred) \ > + { \ > + for (int i = 0; i < COUNT; ++i) \ > + r[i] = pred[i] ? OP (a[i]) : a[i]; \ > + } > + > +#define TEST_TYPES(T, TYPE1, TYPE2, COUNT) \ > + T (TYPE1, TYPE2, COUNT, abs) \ > + T (TYPE1, TYPE2, COUNT, neg) \ > + T (TYPE1, TYPE2, COUNT, not) > + > +#define TEST_ALL(T) \ > + TEST_TYPES (T, int16_t, int8_t, 7) \ > + TEST_TYPES (T, int32_t, int8_t, 3) \ > + TEST_TYPES (T, int32_t, int16_t, 3) \ > + TEST_TYPES (T, int64_t, int8_t, 5) \ > + TEST_TYPES (T, int64_t, int16_t, 5) \ > + TEST_TYPES (T, int64_t, int32_t, 5) > + > +TEST_ALL (DEF_LOOP) > + > +/* NOTE: int abs operator is converted to vmslt + vneg.v */ > +/* { dg-final { scan-assembler-times {\tvneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 12 { > xfail { any-opts "--param riscv-autovec-lmul=m2" } } } } */ > +/* { dg-final { scan-assembler-times {\tvnot\.v\tv[0-9]+,v[0-9]+,v0\.t} 6 { > xfail { any-opts "--param riscv-autovec-lmul=m2" } } } } */ > diff --git > a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_5_run.c > b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_5_run.c > new file mode 100644 > index 00000000000..efd4c2936f1 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_5_run.c > @@ -0,0 +1,26 @@ > +/* { dg-do run { target { riscv_vector } } } */ > +/* { dg-additional-options "--param riscv-autovec-preference=scalable > -fno-vect-cost-model" } */ > + > +#include "cond_unary_5.c" > + > +#define TEST_LOOP(TYPE1, TYPE2, N, OP) \ > + { \ > + TYPE1 pred[N]; \ > + TYPE2 r[N], a[N]; \ > + for (int i = 0; i < N; ++i) \ > + { \ > + a[i] = (i & 1 ? i : 3 * i) * (i % 3 == 0 ? 1 : -1); \ > + pred[i] = (i % 4 < 2); \ > + asm volatile ("" ::: "memory"); \ > + } \ > + test_##TYPE1##_##TYPE2##_##OP (r, a, pred); \ > + for (int i = 0; i < N; ++i) \ > + if (r[i] != (pred[i] ? OP (a[i]) : a[i])) \ > + __builtin_abort (); \ > + } > + > +int main () > +{ > + TEST_ALL (TEST_LOOP) > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_6.c > b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_6.c > new file mode 100644 > index 00000000000..b2050f21389 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_6.c > @@ -0,0 +1,41 @@ > +/* { dg-do compile } */ > +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d --param > riscv-autovec-preference=scalable -fno-vect-cost-model" } */ > + > +#include <stdint.h> > + > +#define abs(A) ((A) < 0 ? -(A) : (A)) > +#define neg(A) (-(A)) > +#define not(A) (~(A)) > + > +#define DEF_LOOP(TYPE1, TYPE2, COUNT, OP) \ > + void __attribute__ ((noipa)) \ > + test_##TYPE1##_##TYPE2##_##OP (TYPE2 *__restrict r, \ > + TYPE2 *__restrict a, \ > + TYPE2 *__restrict b, \ > + TYPE1 *__restrict pred) \ > + { \ > + for (int i = 0; i < COUNT; ++i) \ > + { \ > + TYPE2 bi = b[i]; \ > + r[i] = pred[i] ? OP (a[i]) : bi; \ > + } \ > + } > + > +#define TEST_TYPES(T, TYPE1, TYPE2, COUNT) \ > + T (TYPE1, TYPE2, COUNT, abs) \ > + T (TYPE1, TYPE2, COUNT, neg) \ > + T (TYPE1, TYPE2, COUNT, not) > + > +#define TEST_ALL(T) \ > + TEST_TYPES (T, int16_t, int8_t, 7) \ > + TEST_TYPES (T, int32_t, int8_t, 3) \ > + TEST_TYPES (T, int32_t, int16_t, 3) \ > + TEST_TYPES (T, int64_t, int8_t, 5) \ > + TEST_TYPES (T, int64_t, int16_t, 5) \ > + TEST_TYPES (T, int64_t, int32_t, 5) > + > +TEST_ALL (DEF_LOOP) > + > +/* NOTE: int abs operator is converted to vmslt + vneg.v */ > +/* { dg-final { scan-assembler-times {\tvneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 12 { > xfail { any-opts "--param riscv-autovec-lmul=m2" } } } } */ > +/* { dg-final { scan-assembler-times {\tvnot\.v\tv[0-9]+,v[0-9]+,v0\.t} 6 { > xfail { any-opts "--param riscv-autovec-lmul=m2" } } } } */ > diff --git > a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_6_run.c > b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_6_run.c > new file mode 100644 > index 00000000000..e42be948748 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_6_run.c > @@ -0,0 +1,27 @@ > +/* { dg-do run { target { riscv_vector } } } */ > +/* { dg-additional-options "--param riscv-autovec-preference=scalable > -fno-vect-cost-model" } */ > + > +#include "cond_unary_6.c" > + > +#define TEST_LOOP(TYPE1, TYPE2, N, OP) \ > + { \ > + TYPE1 pred[N]; \ > + TYPE2 r[N], a[N], b[N]; \ > + for (int i = 0; i < N; ++i) \ > + { \ > + a[i] = (i & 1 ? i : 3 * i) * (i % 3 == 0 ? 1 : -1); \ > + b[i] = (i % 5) * (i % 6 + 3); \ > + pred[i] = (i % 4 < 2); \ > + asm volatile ("" ::: "memory"); \ > + } \ > + test_##TYPE1##_##TYPE2##_##OP (r, a, b, pred); \ > + for (int i = 0; i < N; ++i) \ > + if (r[i] != (pred[i] ? OP (a[i]) : b[i])) \ > + __builtin_abort (); \ > + } > + > +int main () > +{ > + TEST_ALL (TEST_LOOP) > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_7.c > b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_7.c > new file mode 100644 > index 00000000000..72577703cee > --- /dev/null > +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_7.c > @@ -0,0 +1,37 @@ > +/* { dg-do compile } */ > +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d --param > riscv-autovec-preference=scalable -fno-vect-cost-model" } */ > + > +#include <stdint.h> > + > +#define abs(A) ((A) < 0 ? -(A) : (A)) > +#define neg(A) (-(A)) > +#define not(A) (~(A)) > + > +#define DEF_LOOP(TYPE1, TYPE2, COUNT, OP) \ > + void __attribute__ ((noipa)) \ > + test_##TYPE1##_##TYPE2##_##OP (TYPE2 *__restrict r, \ > + TYPE2 *__restrict a, \ > + TYPE1 *__restrict pred) \ > + { \ > + for (int i = 0; i < COUNT; ++i) \ > + r[i] = pred[i] ? OP (a[i]) : 5; \ > + } > + > +#define TEST_TYPES(T, TYPE1, TYPE2, COUNT) \ > + T (TYPE1, TYPE2, COUNT, abs) \ > + T (TYPE1, TYPE2, COUNT, neg) \ > + T (TYPE1, TYPE2, COUNT, not) > + > +#define TEST_ALL(T) \ > + TEST_TYPES (T, int16_t, int8_t, 7) \ > + TEST_TYPES (T, int32_t, int8_t, 3) \ > + TEST_TYPES (T, int32_t, int16_t, 3) \ > + TEST_TYPES (T, int64_t, int8_t, 5) \ > + TEST_TYPES (T, int64_t, int16_t, 5) \ > + TEST_TYPES (T, int64_t, int32_t, 5) > + > +TEST_ALL (DEF_LOOP) > + > +/* NOTE: int abs operator is converted to vmslt + vneg.v */ > +/* { dg-final { scan-assembler-times {\tvneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 12 { > xfail { any-opts "--param riscv-autovec-lmul=m2" } } } } */ > +/* { dg-final { scan-assembler-times {\tvnot\.v\tv[0-9]+,v[0-9]+,v0\.t} 6 { > xfail { any-opts "--param riscv-autovec-lmul=m2" } } } } */ > diff --git > a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_7_run.c > b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_7_run.c > new file mode 100644 > index 00000000000..50ff6727086 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_7_run.c > @@ -0,0 +1,26 @@ > +/* { dg-do run { target { riscv_vector } } } */ > +/* { dg-additional-options "--param riscv-autovec-preference=scalable > -fno-vect-cost-model" } */ > + > +#include "cond_unary_7.c" > + > +#define TEST_LOOP(TYPE1, TYPE2, N, OP) \ > + { \ > + TYPE1 pred[N]; \ > + TYPE2 r[N], a[N]; \ > + for (int i = 0; i < N; ++i) \ > + { \ > + a[i] = (i & 1 ? i : 3 * i) * (i % 3 == 0 ? 1 : -1); \ > + pred[i] = (i % 4 < 2); \ > + asm volatile ("" ::: "memory"); \ > + } \ > + test_##TYPE1##_##TYPE2##_##OP (r, a, pred); \ > + for (int i = 0; i < N; ++i) \ > + if (r[i] != (pred[i] ? OP (a[i]) : 5)) \ > + __builtin_abort (); \ > + } > + > +int main () > +{ > + TEST_ALL (TEST_LOOP) > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_8.c > b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_8.c > new file mode 100644 > index 00000000000..269cc3ded95 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_8.c > @@ -0,0 +1,37 @@ > +/* { dg-do compile } */ > +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d --param > riscv-autovec-preference=scalable -fno-vect-cost-model" } */ > + > +#include <stdint.h> > + > +#define abs(A) ((A) < 0 ? -(A) : (A)) > +#define neg(A) (-(A)) > +#define not(A) (~(A)) > + > +#define DEF_LOOP(TYPE1, TYPE2, COUNT, OP) \ > + void __attribute__ ((noipa)) \ > + test_##TYPE1##_##TYPE2##_##OP (TYPE2 *__restrict r, \ > + TYPE2 *__restrict a, \ > + TYPE1 *__restrict pred) \ > + { \ > + for (int i = 0; i < COUNT; ++i) \ > + r[i] = pred[i] ? OP (a[i]) : 0; \ > + } > + > +#define TEST_TYPES(T, TYPE1, TYPE2, COUNT) \ > + T (TYPE1, TYPE2, COUNT, abs) \ > + T (TYPE1, TYPE2, COUNT, neg) \ > + T (TYPE1, TYPE2, COUNT, not) > + > +#define TEST_ALL(T) \ > + TEST_TYPES (T, int16_t, int8_t, 7) \ > + TEST_TYPES (T, int32_t, int8_t, 3) \ > + TEST_TYPES (T, int32_t, int16_t, 3) \ > + TEST_TYPES (T, int64_t, int8_t, 5) \ > + TEST_TYPES (T, int64_t, int16_t, 5) \ > + TEST_TYPES (T, int64_t, int32_t, 5) > + > +TEST_ALL (DEF_LOOP) > + > +/* NOTE: int abs operator is converted to vmslt + vneg.v */ > +/* { dg-final { scan-assembler-times {\tvneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 12 { > xfail { any-opts "--param riscv-autovec-lmul=m2" } } } } */ > +/* { dg-final { scan-assembler-times {\tvnot\.v\tv[0-9]+,v[0-9]+,v0\.t} 6 { > xfail { any-opts "--param riscv-autovec-lmul=m2" } } } } */ > diff --git > a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_8_run.c > b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_8_run.c > new file mode 100644 > index 00000000000..dcc72313f99 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_8_run.c > @@ -0,0 +1,28 @@ > +/* { dg-do run { target { riscv_vector } } } */ > +/* { dg-additional-options "--param riscv-autovec-preference=scalable > -fno-vect-cost-model" } */ > + > +#include "cond_unary_8.c" > + > +#define N 99 > + > +#define TEST_LOOP(TYPE1, TYPE2, N, OP) \ > + { \ > + TYPE1 pred[N]; \ > + TYPE2 r[N], a[N]; \ > + for (int i = 0; i < N; ++i) \ > + { \ > + a[i] = (i & 1 ? i : 3 * i) * (i % 3 == 0 ? 1 : -1); \ > + pred[i] = (i % 4 < 2); \ > + asm volatile ("" ::: "memory"); \ > + } \ > + test_##TYPE1##_##TYPE2##_##OP (r, a, pred); \ > + for (int i = 0; i < N; ++i) \ > + if (r[i] != (pred[i] ? OP (a[i]) : 0)) \ > + __builtin_abort (); \ > + } > + > +int main () > +{ > + TEST_ALL (TEST_LOOP) > + return 0; > +} > -- > 2.36.3 > >