From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2017) id 307943856604; Tue, 27 Jun 2023 21:30:57 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 307943856604 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1687901457; bh=e4Q5AUwe5F8gAvCS82RCYGXajVI1biF5KAOsPl+f0Fs=; h=From:To:Subject:Date:From; b=rJkrX+fwlYnFXQcmGOKjrAklOa+RTItyOqkBYkegLzUrLGmjNPGNkd/7HpwQtUtDZ dZycGgLbXLxsDGf0Vh/1vjroDUjvxWjHltULZ/sT445P1thPx3xekOfghKf0HCGq5c Dk1r9vzChGAU+GRjm5/aEBQYiZrQLkKubyaqWSkM= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Robin Dapp To: gcc-cvs@gcc.gnu.org Subject: [gcc r14-2139] RISC-V: Add autovec FP widening/narrowing. X-Act-Checkin: gcc X-Git-Author: Robin Dapp X-Git-Refname: refs/heads/master X-Git-Oldrev: 1f3d97bdf1e2ac3770468127fb39645bb68f6291 X-Git-Newrev: a9b40612baf2f936ac1d211fbc0b3e46404cefa7 Message-Id: <20230627213057.307943856604@sourceware.org> Date: Tue, 27 Jun 2023 21:30:57 +0000 (GMT) List-Id: https://gcc.gnu.org/g:a9b40612baf2f936ac1d211fbc0b3e46404cefa7 commit r14-2139-ga9b40612baf2f936ac1d211fbc0b3e46404cefa7 Author: Robin Dapp Date: Tue Jun 20 13:07:23 2023 +0200 RISC-V: Add autovec FP widening/narrowing. This patch adds FP widening and narrowing expanders as well as tests. Conceptually similar to integer extension/truncation, we emulate _Float16 -> double by two vfwcvts and double -> _Float16 by two vfncvts. gcc/ChangeLog: * config/riscv/autovec.md (extend2): New expander. (extend2): Ditto. (trunc2): Ditto. (trunc2): Ditto. * config/riscv/vector-iterators.md: Add VQEXTF and HF to V_QUAD_TRUNC and v_quad_trunc. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/autovec/conversions/vfncvt-run.c: New test. * gcc.target/riscv/rvv/autovec/conversions/vfncvt-rv32gcv.c: New test. * gcc.target/riscv/rvv/autovec/conversions/vfncvt-rv64gcv.c: New test. * gcc.target/riscv/rvv/autovec/conversions/vfncvt-template.h: New test. * gcc.target/riscv/rvv/autovec/conversions/vfncvt-zvfh-run.c: New test. * gcc.target/riscv/rvv/autovec/conversions/vfwcvt-run.c: New test. * gcc.target/riscv/rvv/autovec/conversions/vfwcvt-rv32gcv.c: New test. * gcc.target/riscv/rvv/autovec/conversions/vfwcvt-rv64gcv.c: New test. * gcc.target/riscv/rvv/autovec/conversions/vfwcvt-template.h: New test. * gcc.target/riscv/rvv/autovec/conversions/vfwcvt-zvfh-run.c: New test. Diff: --- gcc/config/riscv/autovec.md | 88 +++++++++++++++++++++- gcc/config/riscv/vector-iterators.md | 14 ++++ .../riscv/rvv/autovec/conversions/vfncvt-run.c | 33 ++++++++ .../riscv/rvv/autovec/conversions/vfncvt-rv32gcv.c | 7 ++ .../riscv/rvv/autovec/conversions/vfncvt-rv64gcv.c | 7 ++ .../rvv/autovec/conversions/vfncvt-template.h | 16 ++++ .../rvv/autovec/conversions/vfncvt-zvfh-run.c | 34 +++++++++ .../riscv/rvv/autovec/conversions/vfwcvt-run.c | 33 ++++++++ .../riscv/rvv/autovec/conversions/vfwcvt-rv32gcv.c | 6 ++ .../riscv/rvv/autovec/conversions/vfwcvt-rv64gcv.c | 6 ++ .../rvv/autovec/conversions/vfwcvt-template.h | 16 ++++ .../rvv/autovec/conversions/vfwcvt-zvfh-run.c | 34 +++++++++ 12 files changed, 292 insertions(+), 2 deletions(-) diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md index b0e5950fb56..a7c8056a774 100644 --- a/gcc/config/riscv/autovec.md +++ b/gcc/config/riscv/autovec.md @@ -162,12 +162,12 @@ riscv_vector::emit_vlmax_insn (code_for_pred_scalar (, mode), riscv_vector::RVV_BINOP, operands); DONE; -} +} [(set_attr "type" "vshift") (set_attr "mode" "")]) ;; ------------------------------------------------------------------------- -;; ---- [INT] Binary shifts by scalar. +;; ---- [INT] Binary shifts by vector. ;; ------------------------------------------------------------------------- ;; Includes: ;; - vsll.vv/vsra.vv/vsrl.vv @@ -428,6 +428,90 @@ DONE; }) +;; ------------------------------------------------------------------------- +;; ---- [FP] Widening. +;; ------------------------------------------------------------------------- +;; - vfwcvt.f.f.v +;; ------------------------------------------------------------------------- +(define_insn_and_split "extend2" + [(set (match_operand:VWEXTF_ZVFHMIN 0 "register_operand" "=&vr") + (float_extend:VWEXTF_ZVFHMIN + (match_operand: 1 "register_operand" " vr")))] + "TARGET_VECTOR && can_create_pseudo_p ()" + "#" + "&& 1" + [(const_int 0)] +{ + insn_code icode = code_for_pred_extend (mode); + riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, operands); + DONE; +} + [(set_attr "type" "vfwcvtftof") + (set_attr "mode" "")]) + +(define_expand "extend2" + [(set (match_operand:VQEXTF 0 "register_operand") + (float_extend:VQEXTF + (match_operand: 1 "register_operand")))] + "TARGET_VECTOR && (TARGET_ZVFHMIN || TARGET_ZVFH)" +{ + rtx dblw = gen_reg_rtx (mode); + insn_code icode = code_for_pred_extend (mode); + rtx ops1[] = {dblw, operands[1]}; + riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, ops1); + + icode = code_for_pred_extend (mode); + rtx ops2[] = {operands[0], dblw}; + riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, ops2); + DONE; +}) + +;; ------------------------------------------------------------------------- +;; ---- [FP] Narrowing. +;; ------------------------------------------------------------------------- +;; - vfncvt.f.f.w +;; ------------------------------------------------------------------------- +(define_insn_and_split "trunc2" + [(set (match_operand: 0 "register_operand" "=vr") + (truncate: + (match_operand:VWEXTF_ZVFHMIN 1 "register_operand" " vr")))] + "TARGET_VECTOR && can_create_pseudo_p ()" + "#" + "&& 1" + [(const_int 0)] +{ + insn_code icode = code_for_pred_trunc (mode); + riscv_vector::emit_vlmax_fp_insn (icode, riscv_vector::RVV_UNOP, operands); + DONE; +} + [(set_attr "type" "vfncvtftof") + (set_attr "mode" "")]) + +;; ------------------------------------------------------------------------- +;; Narrowing to a mode whose inner mode size is a quarter of mode's. +;; We emulate this with two consecutive vfncvts. +;; ------------------------------------------------------------------------- +(define_expand "trunc2" + [(set (match_operand: 0 "register_operand") + (truncate: + (match_operand:VQEXTF 1 "register_operand")))] + "TARGET_VECTOR && (TARGET_ZVFHMIN || TARGET_ZVFH)" +{ + rtx half = gen_reg_rtx (mode); + rtx opshalf[] = {half, operands[1]}; + + /* According to the RISC-V V Spec 13.19. we need to use + vfncvt.rod.f.f.w for all steps but the last. */ + insn_code icode = code_for_pred_rod_trunc (mode); + riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, opshalf); + + rtx ops[] = {operands[0], half}; + icode = code_for_pred_trunc (mode); + riscv_vector::emit_vlmax_fp_insn (icode, riscv_vector::RVV_UNOP, ops); + DONE; +}) + + ;; ========================================================================= ;; == Conversions ;; ========================================================================= diff --git a/gcc/config/riscv/vector-iterators.md b/gcc/config/riscv/vector-iterators.md index 7893aa66a2b..8134bc0ddd6 100644 --- a/gcc/config/riscv/vector-iterators.md +++ b/gcc/config/riscv/vector-iterators.md @@ -547,6 +547,14 @@ (VNx16DI "TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 128") ]) +(define_mode_iterator VQEXTF [ + (VNx1DF "TARGET_VECTOR_ELEN_FP_64 && TARGET_MIN_VLEN < 128") + (VNx2DF "TARGET_VECTOR_ELEN_FP_64") + (VNx4DF "TARGET_VECTOR_ELEN_FP_64") + (VNx8DF "TARGET_VECTOR_ELEN_FP_64") + (VNx16DF "TARGET_VECTOR_ELEN_FP_64 && TARGET_MIN_VLEN >= 128") +]) + (define_mode_iterator VOEXTI [ (VNx1DI "TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN < 128") (VNx2DI "TARGET_VECTOR_ELEN_64") (VNx4DI "TARGET_VECTOR_ELEN_64") (VNx8DI "TARGET_VECTOR_ELEN_64") @@ -1305,6 +1313,9 @@ (VNx16SI "VNx16QI") (VNx32SI "VNx32QI") (VNx1DI "VNx1HI") (VNx2DI "VNx2HI") (VNx4DI "VNx4HI") (VNx8DI "VNx8HI") (VNx16DI "VNx16HI") + + (VNx1DF "VNx1HF") (VNx2DF "VNx2HF") (VNx4DF "VNx4HF") (VNx8DF "VNx8HF") + (VNx16DF "VNx16HF") ]) (define_mode_attr V_OCT_TRUNC [ @@ -1330,6 +1341,9 @@ (VNx16SI "vnx16qi") (VNx32SI "vnx32qi") (VNx1DI "vnx1hi") (VNx2DI "vnx2hi") (VNx4DI "vnx4hi") (VNx8DI "vnx8hi") (VNx16DI "vnx16hi") + + (VNx1DF "vnx1hf") (VNx2DF "vnx2hf") (VNx4DF "vnx4hf") (VNx8DF "vnx8hf") + (VNx16DF "vnx16hf") ]) (define_mode_attr v_oct_trunc [ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfncvt-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfncvt-run.c new file mode 100644 index 00000000000..65d2826c8a1 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfncvt-run.c @@ -0,0 +1,33 @@ +/* { dg-do run { target { riscv_vector } } } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vfncvt-template.h" + +#include + +#define SZ 512 +#define EPS 1e-4 + +#define RUN(TYPE1,TYPE2) \ + TYPE1 src##TYPE1##TYPE2[SZ]; \ + TYPE2 dst##TYPE1##TYPE2[SZ]; \ + for (int i = 0; i < SZ; i++) \ + { \ + src##TYPE1##TYPE2[i] = (i & 1) ? -i : i; \ + src##TYPE1##TYPE2[i] *= 3.141592; \ + dst##TYPE1##TYPE2[i] = -1; \ + } \ + vfncvt_##TYPE1##TYPE2 (dst##TYPE1##TYPE2, \ + src##TYPE1##TYPE2, SZ); \ + for (int i = 0; i < SZ; i++) \ + assert (__builtin_fabs (dst##TYPE1##TYPE2[i] \ + - ((i & 1) ? -i : i) * 3.141592) < EPS); \ + + +#define RUN_ALL() \ + RUN(double, float) \ + +int main () +{ + RUN_ALL() +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfncvt-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfncvt-rv32gcv.c new file mode 100644 index 00000000000..10fe75d2754 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfncvt-rv32gcv.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vfncvt-template.h" + +/* { dg-final { scan-assembler-times {\tvfncvt\.f\.f\.w} 3 } } */ +/* { dg-final { scan-assembler-times {\tvfncvt\.rod\.f\.f\.w} 1 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfncvt-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfncvt-rv64gcv.c new file mode 100644 index 00000000000..fd40fa242e4 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfncvt-rv64gcv.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv_zvfh -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vfncvt-template.h" + +/* { dg-final { scan-assembler-times {\tvfncvt\.f\.f\.w} 3 } } */ +/* { dg-final { scan-assembler-times {\tvfncvt\.rod\.f\.f\.w} 1 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfncvt-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfncvt-template.h new file mode 100644 index 00000000000..221e8838d36 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfncvt-template.h @@ -0,0 +1,16 @@ +#include + +#define TEST(TYPE1, TYPE2) \ + __attribute__((noipa)) \ + void vfncvt_##TYPE1##TYPE2 (TYPE2 *dst, TYPE1 *a, int n) \ + { \ + for (int i = 0; i < n; i++) \ + dst[i] = (TYPE2)a[i]; \ + } + +#define TEST_ALL() \ + TEST(float, _Float16) \ + TEST(double, _Float16) \ + TEST(double, float) \ + +TEST_ALL() diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfncvt-zvfh-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfncvt-zvfh-run.c new file mode 100644 index 00000000000..38e0d84b4e2 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfncvt-zvfh-run.c @@ -0,0 +1,34 @@ +/* { dg-do run { target { riscv_vector && riscv_zvfh_hw } } } */ +/* { dg-additional-options "-std=c99 -march=rv64gcv_zvfh -mabi=lp64d -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */ + +#include "vfncvt-template.h" + +#include + +#define SZ 512 +#define EPS 1e-4 + +#define RUN(TYPE1,TYPE2) \ + TYPE1 src##TYPE1##TYPE2[SZ]; \ + TYPE2 dst##TYPE1##TYPE2[SZ]; \ + for (int i = 0; i < SZ; i++) \ + { \ + src##TYPE1##TYPE2[i] = (i & 1) ? -i : i; \ + src##TYPE1##TYPE2[i] *= 0.0003141592; \ + dst##TYPE1##TYPE2[i] = -1; \ + } \ + vfncvt_##TYPE1##TYPE2 (dst##TYPE1##TYPE2, \ + src##TYPE1##TYPE2, SZ); \ + for (int i = 0; i < SZ; i++) \ + assert (__builtin_fabs (dst##TYPE1##TYPE2[i] \ + - ((i & 1) ? -i : i) * 0.0003141592) < EPS); \ + + +#define RUN_ALL() \ + RUN(float, _Float16) \ + RUN(double, _Float16) \ + +int main () +{ + RUN_ALL() +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfwcvt-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfwcvt-run.c new file mode 100644 index 00000000000..9594909c4ee --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfwcvt-run.c @@ -0,0 +1,33 @@ +/* { dg-do run { target { riscv_vector } } } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vfwcvt-template.h" + +#include + +#define SZ 512 +#define EPS 1e-4 + +#define RUN(TYPE1,TYPE2) \ + TYPE1 src##TYPE1##TYPE2[SZ]; \ + TYPE2 dst##TYPE1##TYPE2[SZ]; \ + for (int i = 0; i < SZ; i++) \ + { \ + src##TYPE1##TYPE2[i] = (i & 1) ? -i : i; \ + src##TYPE1##TYPE2[i] *= 3.141592; \ + dst##TYPE1##TYPE2[i] = -1; \ + } \ + vfwcvt_##TYPE1##TYPE2 (dst##TYPE1##TYPE2, \ + src##TYPE1##TYPE2, SZ); \ + for (int i = 0; i < SZ; i++) \ + assert (__builtin_fabs (dst##TYPE1##TYPE2[i] \ + - ((i & 1) ? -i : i) * 3.141592) < EPS); \ + + +#define RUN_ALL() \ + RUN(float, double) \ + +int main () +{ + RUN_ALL() +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfwcvt-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfwcvt-rv32gcv.c new file mode 100644 index 00000000000..006bdb24c41 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfwcvt-rv32gcv.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vfwcvt-template.h" + +/* { dg-final { scan-assembler-times {\tvfwcvt\.f\.f\.v} 4 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfwcvt-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfwcvt-rv64gcv.c new file mode 100644 index 00000000000..7ec710702c9 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfwcvt-rv64gcv.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv_zvfh -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vfwcvt-template.h" + +/* { dg-final { scan-assembler-times {\tvfwcvt\.f\.f\.v} 4 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfwcvt-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfwcvt-template.h new file mode 100644 index 00000000000..b6ccf3ba2f5 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfwcvt-template.h @@ -0,0 +1,16 @@ +#include + +#define TEST(TYPE1, TYPE2) \ + __attribute__((noipa)) \ + void vfwcvt_##TYPE1##TYPE2 (TYPE2 *dst, TYPE1 *a, int n) \ + { \ + for (int i = 0; i < n; i++) \ + dst[i] = (TYPE2)a[i]; \ + } + +#define TEST_ALL() \ + TEST(_Float16, float) \ + TEST(_Float16, double) \ + TEST(float, double) \ + +TEST_ALL() diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfwcvt-zvfh-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfwcvt-zvfh-run.c new file mode 100644 index 00000000000..77d653e256d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/conversions/vfwcvt-zvfh-run.c @@ -0,0 +1,34 @@ +/* { dg-do run { target { riscv_vector && riscv_zvfh_hw } } } */ +/* { dg-additional-options "-std=c99 -march=rv64gcv_zvfh -mabi=lp64d -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */ + +#include "vfwcvt-template.h" + +#include + +#define SZ 512 +#define EPS 1e-4 + +#define RUN(TYPE1,TYPE2) \ + TYPE1 src##TYPE1##TYPE2[SZ]; \ + TYPE2 dst##TYPE1##TYPE2[SZ]; \ + for (int i = 0; i < SZ; i++) \ + { \ + src##TYPE1##TYPE2[i] = (i & 1) ? -i : i; \ + src##TYPE1##TYPE2[i] *= 0.0003141592; \ + dst##TYPE1##TYPE2[i] = -1; \ + } \ + vfwcvt_##TYPE1##TYPE2 (dst##TYPE1##TYPE2, \ + src##TYPE1##TYPE2, SZ); \ + for (int i = 0; i < SZ; i++) \ + assert (__builtin_fabs (dst##TYPE1##TYPE2[i] \ + - ((i & 1) ? -i : i) * 0.0003141592) < EPS); \ + + +#define RUN_ALL() \ + RUN(_Float16, float) \ + RUN(_Float16, double) \ + +int main () +{ + RUN_ALL() +}