aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRobin Dapp <rdapp@ventanamicro.com>2023-05-12 16:26:08 +0200
committerRobin Dapp <rdapp@ventanamicro.com>2023-05-26 21:54:30 +0200
commita1b23dcf2337ab8666fac7d1e191ca987710d184 (patch)
treed5359bb1150fb804c2830d447fbd1a0f7201b650 /gcc
parent25907509787e3ef68cd8054460893cd316a8186a (diff)
downloadgcc-a1b23dcf2337ab8666fac7d1e191ca987710d184.zip
gcc-a1b23dcf2337ab8666fac7d1e191ca987710d184.tar.gz
gcc-a1b23dcf2337ab8666fac7d1e191ca987710d184.tar.bz2
RISC-V: Implement autovec abs, vneg, vnot.
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/riscv/autovec.md41
-rw-r--r--gcc/config/riscv/riscv-protos.h2
-rw-r--r--gcc/config/riscv/riscv-v.cc16
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-run.c39
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c8
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c8
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-template.h26
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-run.c29
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-template.h18
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-run.c43
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-template.h22
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/rvv.exp2
16 files changed, 278 insertions, 0 deletions
diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index 64433c7..b24867a 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -477,3 +477,44 @@
riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, ops);
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 0768997..c031354 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 3dd7ee8..6928c8d2 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 0000000..7404dbe
--- /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 0000000..a8b92c9
--- /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 0000000..2e7f086
--- /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 0000000..882de9f
--- /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 0000000..abeb50f
--- /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 0000000..69d9ebb
--- /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 0000000..d2c2e17
--- /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 0000000..93e690f
--- /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 0000000..2870b21
--- /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 0000000..ecc4316
--- /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 0000000..67e28af
--- /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 0000000..747375e
--- /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 9466c20..c0ab0dc 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp
+++ b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp
@@ -67,6 +67,8 @@ foreach op $AUTOVEC_TEST_OPTS {
"" "$op"
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/autovec/conversions/*.\[cS\]]] \
"" "$op"
+ dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/autovec/unop/*.\[cS\]]] \
+ "" "$op"
}
# VLS-VLMAX tests