> Beside, V2 patch should change this: > emit_vlmax_masked_insn (unsigned icode, int op_num, rtx *ops) > > change it into emit_vlmax_masked_mu_insn .
V3 is inline with these changes. This patch implements abs<mode>2, vneg<mode>2 and vnot<mode>2 expanders for integer vector registers and adds tests for them. gcc/ChangeLog: * config/riscv/autovec.md (<optab><mode>2): Add vneg/vnot. (abs<mode>2): Add. * config/riscv/riscv-protos.h (emit_vlmax_masked_mu_insn): Declare. * config/riscv/riscv-v.cc (emit_vlmax_masked_mu_insn): New function. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/rvv.exp: Add unop tests. * gcc.target/riscv/rvv/autovec/unop/abs-run.c: New test. * gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c: New test. * gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c: New test. * gcc.target/riscv/rvv/autovec/unop/abs-template.h: New test. * gcc.target/riscv/rvv/autovec/unop/vneg-run.c: New test. * gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c: New test. * gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c: New test. * gcc.target/riscv/rvv/autovec/unop/vneg-template.h: New test. * gcc.target/riscv/rvv/autovec/unop/vnot-run.c: New test. * gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c: New test. * gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c: New test. * gcc.target/riscv/rvv/autovec/unop/vnot-template.h: New test. --- gcc/config/riscv/autovec.md | 43 ++++++++++++++++++- gcc/config/riscv/riscv-protos.h | 2 + gcc/config/riscv/riscv-v.cc | 16 +++++++ .../riscv/rvv/autovec/unop/abs-run.c | 39 +++++++++++++++++ .../riscv/rvv/autovec/unop/abs-rv32gcv.c | 8 ++++ .../riscv/rvv/autovec/unop/abs-rv64gcv.c | 8 ++++ .../riscv/rvv/autovec/unop/abs-template.h | 26 +++++++++++ .../riscv/rvv/autovec/unop/vneg-run.c | 29 +++++++++++++ .../riscv/rvv/autovec/unop/vneg-rv32gcv.c | 6 +++ .../riscv/rvv/autovec/unop/vneg-rv64gcv.c | 6 +++ .../riscv/rvv/autovec/unop/vneg-template.h | 18 ++++++++ .../riscv/rvv/autovec/unop/vnot-run.c | 43 +++++++++++++++++++ .../riscv/rvv/autovec/unop/vnot-rv32gcv.c | 6 +++ .../riscv/rvv/autovec/unop/vnot-rv64gcv.c | 6 +++ .../riscv/rvv/autovec/unop/vnot-template.h | 22 ++++++++++ gcc/testsuite/gcc.target/riscv/rvv/rvv.exp | 2 + 16 files changed, 279 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-run.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-template.h create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-run.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-template.h create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-run.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-template.h diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md index 7fe4d94de39..38216d9812f 100644 --- a/gcc/config/riscv/autovec.md +++ b/gcc/config/riscv/autovec.md @@ -145,7 +145,7 @@ (define_expand "<optab><mode>3" }) ;; ------------------------------------------------------------------------- -;; ---- [INT] Binary shifts by scalar. +;; ---- [INT] Binary shifts by vector. ;; ------------------------------------------------------------------------- ;; Includes: ;; - vsll.vv/vsra.vv/vsrl.vv @@ -373,3 +373,44 @@ (define_expand "vcondu<V:mode><VI:mode>" DONE; } ) + +;; ========================================================================= +;; == Unary arithmetic +;; ========================================================================= + +;; ------------------------------------------------------------------------------- +;; ---- [INT] Unary operations +;; ------------------------------------------------------------------------------- +;; Includes: +;; - vneg.v/vnot.v +;; ------------------------------------------------------------------------------- +(define_expand "<optab><mode>2" + [(set (match_operand:VI 0 "register_operand") + (any_int_unop:VI + (match_operand:VI 1 "register_operand")))] + "TARGET_VECTOR" +{ + insn_code icode = code_for_pred (<CODE>, <MODE>mode); + riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, operands); + DONE; +}) + +;; ------------------------------------------------------------------------------- +;; - ABS expansion to vmslt and vneg +;; ------------------------------------------------------------------------------- + +(define_expand "abs<mode>2" + [(set (match_operand:VI 0 "register_operand") + (match_operand:VI 1 "register_operand"))] + "TARGET_VECTOR" +{ + rtx zero = gen_const_vec_duplicate (<MODE>mode, GEN_INT (0)); + machine_mode mask_mode = riscv_vector::get_mask_mode (<MODE>mode).require (); + rtx mask = gen_reg_rtx (mask_mode); + riscv_vector::expand_vec_cmp (mask, LT, operands[1], zero); + + rtx ops[] = {operands[0], mask, operands[1], operands[1]}; + riscv_vector::emit_vlmax_masked_mu_insn (code_for_pred (NEG, <MODE>mode), + riscv_vector::RVV_UNOP_MU, ops); + DONE; +}) diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 36419c95bbd..b6a8be5d90b 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -140,6 +140,7 @@ 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. */ }; enum vlmul_type { @@ -180,6 +181,7 @@ void emit_nonvlmax_insn (unsigned, int, rtx *, rtx); void emit_vlmax_merge_insn (unsigned, int, rtx *); void emit_vlmax_cmp_insn (unsigned, rtx *); void emit_vlmax_cmp_mu_insn (unsigned, rtx *); +void emit_vlmax_masked_mu_insn (unsigned, int, rtx *); enum vlmul_type get_vlmul (machine_mode); unsigned int get_ratio (machine_mode); unsigned int get_nf (machine_mode); diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc index f71ad9e46a1..6a2299bad7c 100644 --- a/gcc/config/riscv/riscv-v.cc +++ b/gcc/config/riscv/riscv-v.cc @@ -426,6 +426,22 @@ emit_vlmax_cmp_mu_insn (unsigned icode, rtx *ops) e.emit_insn ((enum insn_code) icode, ops); } +/* This function emits a masked instruction. */ +void +emit_vlmax_masked_mu_insn (unsigned icode, int op_num, rtx *ops) +{ + machine_mode dest_mode = GET_MODE (ops[0]); + machine_mode mask_mode = get_mask_mode (dest_mode).require (); + insn_expander<11> e (/*OP_NUM*/ op_num, /*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_policy (MASK_UNDISTURBED); + e.emit_insn ((enum insn_code) icode, ops); +} + /* Expand series const vector. */ void diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-run.c new file mode 100644 index 00000000000..7404dbe037e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-run.c @@ -0,0 +1,39 @@ +/* { dg-do run { target { riscv_vector } } } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "abs-template.h" + +#include <assert.h> + +#define SZ 128 + +#define RUN(TYPE) \ + TYPE a##TYPE[SZ]; \ + for (int i = 0; i < SZ; i++) \ + { \ + if (i & 1) \ + a##TYPE[i] = i - 64; \ + else \ + a##TYPE[i] = i; \ + } \ + vabs_##TYPE (a##TYPE, a##TYPE, SZ); \ + for (int i = 0; i < SZ; i++) \ + { \ + printf ("%d %d %d\n", i, a##TYPE[i], i - 64); \ + if (i & 1) \ + assert (a##TYPE[i] == abs (i - 64)); \ + else \ + assert (a##TYPE[i] == i); \ + } + + +#define RUN_ALL() \ + RUN(int8_t) \ + RUN(int16_t) \ + RUN(int32_t) \ + RUN(int64_t) + +int main () +{ + RUN_ALL() +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c new file mode 100644 index 00000000000..a8b92c9450f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "abs-template.h" + +/* { dg-final { scan-assembler-times {\tvseti?vli\s+[a-z0-9,]+,ta,mu} 4 } } */ +/* { dg-final { scan-assembler-times {\tvmslt\.vi} 4 } } */ +/* { dg-final { scan-assembler-times {\tvneg.v\sv[0-9]+,v[0-9]+,v0\.t} 4 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c new file mode 100644 index 00000000000..2e7f0864ee7 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "abs-template.h" + +/* { dg-final { scan-assembler-times {\tvseti?vli\s+[a-z0-9,]+,ta,mu} 4 } } */ +/* { dg-final { scan-assembler-times {\tvmslt\.vi} 4 } } */ +/* { dg-final { scan-assembler-times {\tvneg.v\sv[0-9]+,v[0-9]+,v0\.t} 4 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-template.h new file mode 100644 index 00000000000..882de9f4efb --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-template.h @@ -0,0 +1,26 @@ +#include <stdlib.h> +#include <stdint-gcc.h> + +#define TEST_TYPE(TYPE) \ + __attribute__((noipa)) \ + void vabs_##TYPE (TYPE *dst, TYPE *a, int n) \ + { \ + for (int i = 0; i < n; i++) \ + dst[i] = abs (a[i]); \ + } + +#define TEST_TYPE2(TYPE) \ + __attribute__((noipa)) \ + void vabs_##TYPE (TYPE *dst, TYPE *a, int n) \ + { \ + for (int i = 0; i < n; i++) \ + dst[i] = llabs (a[i]); \ + } + +#define TEST_ALL() \ + TEST_TYPE(int8_t) \ + TEST_TYPE(int16_t) \ + TEST_TYPE(int32_t) \ + TEST_TYPE2(int64_t) + +TEST_ALL() diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-run.c new file mode 100644 index 00000000000..abeb50f21ea --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-run.c @@ -0,0 +1,29 @@ +/* { dg-do run { target { riscv_vector } } } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vneg-template.h" + +#include <assert.h> + +#define SZ 255 + +#define RUN(TYPE) \ + TYPE a##TYPE[SZ]; \ + for (int i = 0; i < SZ; i++) \ + { \ + a##TYPE[i] = i - 127; \ + } \ + vneg_##TYPE (a##TYPE, a##TYPE, SZ); \ + for (int i = 0; i < SZ; i++) \ + assert (a##TYPE[i] == -(i - 127)); + +#define RUN_ALL() \ + RUN(int8_t) \ + RUN(int16_t) \ + RUN(int32_t) \ + RUN(int64_t) + +int main () +{ + RUN_ALL() +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c new file mode 100644 index 00000000000..69d9ebb0953 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vneg-template.h" + +/* { dg-final { scan-assembler-times {\tvneg\.v} 4 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c new file mode 100644 index 00000000000..d2c2e17c13e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vneg-template.h" + +/* { dg-final { scan-assembler-times {\tvneg\.v} 4 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-template.h new file mode 100644 index 00000000000..f766a3b6461 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-template.h @@ -0,0 +1,18 @@ +#include <stdlib.h> +#include <stdint-gcc.h> + +#define TEST_TYPE(TYPE) \ + __attribute__((noipa)) \ + void vneg_##TYPE (TYPE *dst, TYPE *a, int n) \ + { \ + for (int i = 0; i < n; i++) \ + dst[i] = -a[i]; \ + } + +#define TEST_ALL() \ + TEST_TYPE(int8_t) \ + TEST_TYPE(int16_t) \ + TEST_TYPE(int32_t) \ + TEST_TYPE(int64_t) + +TEST_ALL() diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-run.c new file mode 100644 index 00000000000..2870b21a218 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-run.c @@ -0,0 +1,43 @@ +/* { dg-do run { target { riscv_vector } } } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vnot-template.h" + +#include <assert.h> + +#define SZ 255 + +#define RUN(TYPE) \ + TYPE a##TYPE[SZ]; \ + for (int i = 0; i < SZ; i++) \ + { \ + a##TYPE[i] = i - 127; \ + } \ + vnot_##TYPE (a##TYPE, a##TYPE, SZ); \ + for (int i = 0; i < SZ; i++) \ + assert (a##TYPE[i] == (TYPE)~(i - 127)); + +#define RUN2(TYPE) \ + TYPE a##TYPE[SZ]; \ + for (int i = 0; i < SZ; i++) \ + { \ + a##TYPE[i] = i; \ + } \ + vnot_##TYPE (a##TYPE, a##TYPE, SZ); \ + for (int i = 0; i < SZ; i++) \ + assert (a##TYPE[i] == (TYPE)~i); + +#define RUN_ALL() \ + RUN(int8_t) \ + RUN(int16_t) \ + RUN(int32_t) \ + RUN(int64_t) \ + RUN(uint8_t) \ + RUN(uint16_t) \ + RUN(uint32_t) \ + RUN(uint64_t) + +int main () +{ + RUN_ALL() +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c new file mode 100644 index 00000000000..ecc4316bd4f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vnot-template.h" + +/* { dg-final { scan-assembler-times {\tvnot\.v} 8 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c new file mode 100644 index 00000000000..67e28af2cd8 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vnot-template.h" + +/* { dg-final { scan-assembler-times {\tvnot\.v} 8 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-template.h new file mode 100644 index 00000000000..b7a63f04485 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-template.h @@ -0,0 +1,22 @@ +#include <stdlib.h> +#include <stdint-gcc.h> + +#define TEST_TYPE(TYPE) \ + __attribute__((noipa)) \ + void vnot_##TYPE (TYPE *dst, TYPE *a, int n) \ + { \ + for (int i = 0; i < n; i++) \ + dst[i] = ~a[i]; \ + } + +#define TEST_ALL() \ + TEST_TYPE(int8_t) \ + TEST_TYPE(uint8_t) \ + TEST_TYPE(int16_t) \ + TEST_TYPE(uint16_t) \ + TEST_TYPE(int32_t) \ + TEST_TYPE(uint32_t) \ + TEST_TYPE(int64_t) \ + TEST_TYPE(uint64_t) + +TEST_ALL() diff --git a/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp index 9809a421fc8..f5c022d0a30 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp +++ b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp @@ -65,6 +65,8 @@ foreach op $AUTOVEC_TEST_OPTS { "" "$op" dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/autovec/cmp/*.\[cS\]]] \ "" "$op" + dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/autovec/unop/*.\[cS\]]] \ + "" "$op" } # VLS-VLMAX tests -- 2.40.1