diff --git a/gcc/config/riscv/riscv-vector-builtins-bases.cc b/gcc/config/riscv/riscv-vector-builtins-bases.cc index a8113f6602b5f5d7dc9285b6542bedc53c83d904..3f92084929d523fb793acd5d8306eb9c30076895 100644 --- a/gcc/config/riscv/riscv-vector-builtins-bases.cc +++ b/gcc/config/riscv/riscv-vector-builtins-bases.cc @@ -361,8 +361,12 @@ public: return e.use_exact_insn ( code_for_pred_dual_widen_scalar (CODE1, CODE2, e.vector_mode ())); case OP_TYPE_wv: - return e.use_exact_insn ( - code_for_pred_single_widen (CODE1, CODE2, e.vector_mode ())); + if (CODE1 == PLUS) + return e.use_exact_insn ( + code_for_pred_single_widen_add (CODE2, e.vector_mode ())); + else + return e.use_exact_insn ( + code_for_pred_single_widen_sub (CODE2, e.vector_mode ())); case OP_TYPE_wx: return e.use_exact_insn ( code_for_pred_single_widen_scalar (CODE1, CODE2, e.vector_mode ())); diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md index cd41ebbb24f56a6ab8340e78852158a4c0bb3fdb..c74dce89db6c20f927216b44cd0deb236dc1a1a9 100644 --- a/gcc/config/riscv/vector.md +++ b/gcc/config/riscv/vector.md @@ -3131,7 +3131,7 @@ [(set_attr "type" "vi<widen_binop_insn_type>") (set_attr "mode" "<V_DOUBLE_TRUNC>")]) -(define_insn "@pred_single_widen_<plus_minus:optab><any_extend:su><mode>" +(define_insn "@pred_single_widen_sub<any_extend:su><mode>" [(set (match_operand:VWEXTI 0 "register_operand" "=&vr,&vr") (if_then_else:VWEXTI (unspec:<VM> @@ -3142,14 +3142,35 @@ (match_operand 8 "const_int_operand" " i, i") (reg:SI VL_REGNUM) (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) - (plus_minus:VWEXTI + (minus:VWEXTI (match_operand:VWEXTI 3 "register_operand" " vr, vr") (any_extend:VWEXTI (match_operand:<V_DOUBLE_TRUNC> 4 "register_operand" " vr, vr"))) (match_operand:VWEXTI 2 "vector_merge_operand" " vu, 0")))] "TARGET_VECTOR" - "vw<plus_minus:insn><any_extend:u>.wv\t%0,%3,%4%p1" - [(set_attr "type" "vi<widen_binop_insn_type>") + "vwsub<any_extend:u>.wv\t%0,%3,%4%p1" + [(set_attr "type" "viwalu") + (set_attr "mode" "<V_DOUBLE_TRUNC>")]) + +(define_insn "@pred_single_widen_add<any_extend:su><mode>" + [(set (match_operand:VWEXTI 0 "register_operand" "=&vr,&vr") + (if_then_else:VWEXTI + (unspec:<VM> + [(match_operand:<VM> 1 "vector_mask_operand" "vmWc1,vmWc1") + (match_operand 5 "vector_length_operand" " rK, rK") + (match_operand 6 "const_int_operand" " i, i") + (match_operand 7 "const_int_operand" " i, i") + (match_operand 8 "const_int_operand" " i, i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (plus:VWEXTI + (any_extend:VWEXTI + (match_operand:<V_DOUBLE_TRUNC> 4 "register_operand" " vr, vr")) + (match_operand:VWEXTI 3 "register_operand" " vr, vr")) + (match_operand:VWEXTI 2 "vector_merge_operand" " vu, 0")))] + "TARGET_VECTOR" + "vwadd<any_extend:u>.wv\t%0,%3,%4%p1" + [(set_attr "type" "viwalu") (set_attr "mode" "<V_DOUBLE_TRUNC>")]) (define_insn "@pred_single_widen_<plus_minus:optab><any_extend:su><mode>_scalar" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen-5.c new file mode 100644 index 0000000000000000000000000000000000000000..7f8909272ab106dd8ea881c0b116c8d7462c9fb9 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen-5.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=scalable" } */ + +#include <stdint-gcc.h> + +#define TEST_TYPE(TYPE1, TYPE2) \ + __attribute__ ((noipa)) void vwadd_##TYPE1_##TYPE2 (TYPE1 *__restrict dst, \ + TYPE2 *__restrict a, \ + TYPE1 *__restrict b, \ + int n) \ + { \ + for (int i = 0; i < n; i++) \ + dst[i] = (TYPE1) a[i] + b[i]; \ + } + +#define TEST_ALL() \ + TEST_TYPE (int16_t, int8_t) \ + TEST_TYPE (uint16_t, uint8_t) \ + TEST_TYPE (int32_t, int16_t) \ + TEST_TYPE (uint32_t, uint16_t) \ + TEST_TYPE (int64_t, int32_t) \ + TEST_TYPE (uint64_t, uint32_t) + +TEST_ALL () + +/* { dg-final { scan-assembler-times {\tvwadd\.wv} 3 } } */ +/* { dg-final { scan-assembler-times {\tvwaddu\.wv} 3 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen-6.c new file mode 100644 index 0000000000000000000000000000000000000000..f9542d7601e148ebbbda23486d449c344873da3f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen-6.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=scalable" } */ + +#include <stdint-gcc.h> + +#define TEST_TYPE(TYPE1, TYPE2) \ + __attribute__ ((noipa)) void vwsub_##TYPE1_##TYPE2 (TYPE1 *__restrict dst, \ + TYPE1 *__restrict a, \ + TYPE2 *__restrict b, \ + int n) \ + { \ + for (int i = 0; i < n; i++) \ + dst[i] = a[i] - (TYPE1) b[i]; \ + } + +#define TEST_ALL() \ + TEST_TYPE (int16_t, int8_t) \ + TEST_TYPE (uint16_t, uint8_t) \ + TEST_TYPE (int32_t, int16_t) \ + TEST_TYPE (uint32_t, uint16_t) \ + TEST_TYPE (int64_t, int32_t) \ + TEST_TYPE (uint64_t, uint32_t) + +TEST_ALL () + +/* { dg-final { scan-assembler-times {\tvwsub\.wv} 3 } } */ +/* { dg-final { scan-assembler-times {\tvwsubu\.wv} 3 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen-complicate-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen-complicate-1.c new file mode 100644 index 0000000000000000000000000000000000000000..baf91b72d60e75c64edbfc48aa8afcac6d07dd84 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen-complicate-1.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=scalable" } */ + +#include <stdint-gcc.h> + +#define TEST_TYPE(TYPE1, TYPE2) \ + __attribute__ ((noipa)) void vwadd_##TYPE1_##TYPE2 ( \ + TYPE1 *__restrict dst, TYPE1 *__restrict dst2, TYPE1 *__restrict dst3, \ + TYPE2 *__restrict a, TYPE2 *__restrict b, TYPE2 *__restrict a2, \ + TYPE2 *__restrict b2, int n) \ + { \ + for (int i = 0; i < n; i++) \ + { \ + dst[i] = (TYPE1) a[i] + (TYPE1) b[i]; \ + dst2[i] = (TYPE1) a2[i] + (TYPE1) b[i]; \ + dst3[i] = (TYPE1) a2[i] + (TYPE1) a[i]; \ + } \ + } + +#define TEST_ALL() \ + TEST_TYPE (int16_t, int8_t) \ + TEST_TYPE (uint16_t, uint8_t) \ + TEST_TYPE (int32_t, int16_t) \ + TEST_TYPE (uint32_t, uint16_t) \ + TEST_TYPE (int64_t, int32_t) \ + TEST_TYPE (uint64_t, uint32_t) + +TEST_ALL () + +/* { dg-final { scan-assembler-times {\tvwadd\.vv} 9 } } */ +/* { dg-final { scan-assembler-times {\tvwaddu\.vv} 9 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen-complicate-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen-complicate-2.c new file mode 100644 index 0000000000000000000000000000000000000000..6d1709bf2f65a3e28e36e008c5a7b3ad26c7bc2e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen-complicate-2.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=scalable" } */ + +#include <stdint-gcc.h> + +#define TEST_TYPE(TYPE1, TYPE2) \ + __attribute__ ((noipa)) void vwadd_##TYPE1_##TYPE2 ( \ + TYPE1 *__restrict dst, TYPE1 *__restrict dst2, TYPE1 *__restrict dst3, \ + TYPE2 *__restrict a, TYPE2 *__restrict b, TYPE2 *__restrict a2, \ + TYPE2 *__restrict b2, int n) \ + { \ + for (int i = 0; i < n; i++) \ + { \ + dst[i] = (TYPE1) a[i] - (TYPE1) b[i]; \ + dst2[i] = (TYPE1) a2[i] - (TYPE1) b[i]; \ + dst3[i] = (TYPE1) a2[i] - (TYPE1) a[i]; \ + } \ + } + +#define TEST_ALL() \ + TEST_TYPE (int16_t, int8_t) \ + TEST_TYPE (uint16_t, uint8_t) \ + TEST_TYPE (int32_t, int16_t) \ + TEST_TYPE (uint32_t, uint16_t) \ + TEST_TYPE (int64_t, int32_t) \ + TEST_TYPE (uint64_t, uint32_t) + +TEST_ALL () + +/* { dg-final { scan-assembler-times {\tvwsub\.vv} 9 } } */ +/* { dg-final { scan-assembler-times {\tvwsubu\.vv} 9 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen_run-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen_run-5.c new file mode 100644 index 0000000000000000000000000000000000000000..ca16585a945ba5a3b051dd7173a43b198739c870 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen_run-5.c @@ -0,0 +1,34 @@ +/* { dg-do run { target { riscv_vector } } } */ +/* { dg-additional-options "--param=riscv-autovec-preference=scalable" } */ + +#include <assert.h> +#include "widen-5.c" + +#define SZ 512 + +#define RUN(TYPE1, TYPE2, LIMIT) \ + TYPE2 a##TYPE2[SZ]; \ + TYPE1 b##TYPE1[SZ]; \ + TYPE1 dst##TYPE1[SZ]; \ + for (int i = 0; i < SZ; i++) \ + { \ + a##TYPE2[i] = LIMIT + i % 8723; \ + b##TYPE1[i] = LIMIT + i & 1964; \ + } \ + vwadd_##TYPE1_##TYPE2 (dst##TYPE1, a##TYPE2, b##TYPE1, SZ); \ + for (int i = 0; i < SZ; i++) \ + assert (dst##TYPE1[i] == ((TYPE1) a##TYPE2[i] + (TYPE1) b##TYPE1[i])); + +#define RUN_ALL() \ + RUN (int16_t, int8_t, -128) \ + RUN (uint16_t, uint8_t, 255) \ + RUN (int32_t, int16_t, -32768) \ + RUN (uint32_t, uint16_t, 65535) \ + RUN (int64_t, int32_t, -2147483648) \ + RUN (uint64_t, uint32_t, 4294967295) + +int +main () +{ + RUN_ALL () +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen_run-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen_run-6.c new file mode 100644 index 0000000000000000000000000000000000000000..5b69c2ab0c615108a97c4a6ada5216017ec27602 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/widen_run-6.c @@ -0,0 +1,34 @@ +/* { dg-do run { target { riscv_vector } } } */ +/* { dg-additional-options "--param=riscv-autovec-preference=scalable" } */ + +#include <assert.h> +#include "widen-6.c" + +#define SZ 512 + +#define RUN(TYPE1, TYPE2, LIMIT) \ + TYPE1 a##TYPE1[SZ]; \ + TYPE2 b##TYPE2[SZ]; \ + TYPE1 dst##TYPE1[SZ]; \ + for (int i = 0; i < SZ; i++) \ + { \ + a##TYPE1[i] = LIMIT + i % 8723; \ + b##TYPE2[i] = LIMIT + i & 1964; \ + } \ + vwsub_##TYPE1_##TYPE2 (dst##TYPE1, a##TYPE1, b##TYPE2, SZ); \ + for (int i = 0; i < SZ; i++) \ + assert (dst##TYPE1[i] == ((TYPE1) a##TYPE1[i] - (TYPE1) b##TYPE2[i])); + +#define RUN_ALL() \ + RUN (int16_t, int8_t, -128) \ + RUN (uint16_t, uint8_t, 255) \ + RUN (int32_t, int16_t, -32768) \ + RUN (uint32_t, uint16_t, 65535) \ + RUN (int64_t, int32_t, -2147483648) \ + RUN (uint64_t, uint32_t, 4294967295) + +int +main () +{ + RUN_ALL () +}