From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pj1-x102e.google.com (mail-pj1-x102e.google.com [IPv6:2607:f8b0:4864:20::102e]) by sourceware.org (Postfix) with ESMTPS id 52C40385702F for ; Tue, 30 May 2023 06:06:28 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 52C40385702F Authentication-Results: sourceware.org; dmarc=pass (p=reject dis=none) header.from=sifive.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=sifive.com Received: by mail-pj1-x102e.google.com with SMTP id 98e67ed59e1d1-256712e2be3so1820777a91.2 for ; Mon, 29 May 2023 23:06:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; t=1685426787; x=1688018787; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=RYbQHzdUpOeDoMbtPM62CqRdFjGHoSZQRUXVQw152fA=; b=Q8R7BZUmO39gKs47sJul88zdMKpY6hG0iuKM3lZe357lNoxkwVdlEaxO7BuEkhe7rM CGyeXyACtTTujPKYgtbY/8tXXNQhF0IfDXpCOo5Fw1ijTA9NzYMtHEm/fyzJ6dIB8/y4 wDBX/yoFnKY6TIAXzjBGx+dWj5U4S1zz4ef1bM8e605SDvo+oXUtDjsF6nPkc9YfqQpJ 8yJBoTLlEtlz9WBlxBC2W11/tDLlKFplQfdpX1gcSkt3phuMsxI2yeuqzvQqARuSerKh LQ0EVNhYbsf+PmxHFQCJUuNAGRqDA5BGY49eLKCIrQE+IIdt8nB188OpFA/0FGmqtJUc CaOQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685426787; x=1688018787; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=RYbQHzdUpOeDoMbtPM62CqRdFjGHoSZQRUXVQw152fA=; b=UsoV2/dneyKPxuxHVsXwmnoq2DNPHkv3wKYNVaCvYiEZDP3yeRU1IEYOQELUQRLK4p vZgKf2DXI5bydIGzZ3osDIKxf1dIeuI4zne405tPkAg4EgdZcNlxbsU3KKOjo75zdNUN jy0S3vx4ME7vAAqCsxbj8/QPCEQjFRajZMjCfHDRDBW/3fgAAtRXsYAX6TMbMjuUqh7B Nr6bIf7vjpMOCx/usXLGxTwPe3k25EUAcZg4+0aKSX3765GsJx4UqvhR7K+d0x4DSMwV ZZcnFrFiwyGjkfCflwOeuN/s4bjeFDYFLNd7JnTOtXoCgco3UDFO/9S1wGUTos1uyPZ/ fKgQ== X-Gm-Message-State: AC+VfDyxqKlE088jT/f82I8f7IZYQpSqJN29awaTV+QE4aLUF2VrP5wb pYcot1Z+QpGzg7V/Xc2ulxNMH0q+nMmKq0yh6+EITsvA/r7jZAKo48OuYKcShko2sZ7ONzJNgsS em+nEEW7a8rvvjq+fbgfpGw4MJySyXn+sk3FlUYk9zxtT7DHNY3lVQ/YBBhXwxvar7Sxn+Kudzh gJqVg= X-Google-Smtp-Source: ACHHUZ78U8WdAT5md8wBQM8ZMsyXc5Al9oMebnJ84hc94WVwdaxIFqvGaD5STuTTLctDFY3lu9WpwA== X-Received: by 2002:a17:902:768c:b0:1a1:bf22:2b6e with SMTP id m12-20020a170902768c00b001a1bf222b6emr1275392pll.43.1685426786449; Mon, 29 May 2023 23:06:26 -0700 (PDT) Received: from hsinchu02.internal.sifive.com (59-124-168-89.hinet-ip.hinet.net. [59.124.168.89]) by smtp.gmail.com with ESMTPSA id jj4-20020a170903048400b001b04cf94f90sm1917036plb.217.2023.05.29.23.06.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 May 2023 23:06:25 -0700 (PDT) From: Kito Cheng To: gcc-patches@gcc.gnu.org, palmer@dabbelt.com, kito.cheng@gmail.com, juzhe.zhong@rivai.ai, jeffreyalaw@gmail.com, rdapp.gcc@gmail.com, pan2.li@intel.com Cc: Kito Cheng Subject: [PATCH] RISC-V: Basic VLS code gen for RISC-V Date: Tue, 30 May 2023 14:06:21 +0800 Message-Id: <20230530060621.31449-1-kito.cheng@sifive.com> X-Mailer: git-send-email 2.40.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-12.3 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_SHORT,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE,URIBL_BLACK autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: GNU vector extensions is widly used around this world, and this patch enable that with RISC-V vector extensions, this can help people leverage existing code base with RVV, and also can write vector programs in a familiar way. The idea of VLS code gen support is emulate VLS operation by VLA operation with specific length. Key design point is we defer the mode conversion (From VLS to VLA mode) after register allocation, it come with several advantages: - VLS pattern is much friendly for most optimization pass like combine. - Register allocator can spill/restore exact size of VLS type instead of whole register. This is compatible with VLA vectorization. Only support move and binary part of operation patterns. gcc/ChangeLog: * config/riscv/riscv-modes.def: Introduce VLS modes. * config/riscv/riscv-protos.h (riscv_vector::minimal_vls_mode): New. (riscv_vector::vls_insn_expander): New. (riscv_vector::vls_mode_p): New. * config/riscv/riscv-v.cc (riscv_vector::minimal_vls_mode): New. (riscv_vector::vls_mode_p): New. (riscv_vector::vls_insn_expander): New. (riscv_vector::update_vls_mode): New. * config/riscv/riscv.cc (riscv_v_ext_mode_p): New. (riscv_v_adjust_nunits): Handle VLS type. (riscv_hard_regno_nregs): Ditto. (riscv_hard_regno_mode_ok): Ditto. (riscv_regmode_natural_size): Ditto. * config/riscv/vector-iterators.md (VLS): New. (VM): Handle VLS type. (vel): Ditto. * config/riscv/vector.md: Include vector-vls.md. * config/riscv/vector-vls.md: New file. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/rvv.exp: Add vls folder. * gcc.target/riscv/rvv/vls/binop-template.h: New test. * gcc.target/riscv/rvv/vls/binop-v.c: New test. * gcc.target/riscv/rvv/vls/binop-zve32x.c: New test. * gcc.target/riscv/rvv/vls/binop-zve64x.c: New test. * gcc.target/riscv/rvv/vls/move-template.h: New test. * gcc.target/riscv/rvv/vls/move-v.c: New test. * gcc.target/riscv/rvv/vls/move-zve32x.c: New test. * gcc.target/riscv/rvv/vls/move-zve64x.c: New test. * gcc.target/riscv/rvv/vls/load-store-template.h: New test. * gcc.target/riscv/rvv/vls/load-store-v.c: New test. * gcc.target/riscv/rvv/vls/load-store-zve32x.c: New test. * gcc.target/riscv/rvv/vls/load-store-zve64x.c: New test. * gcc.target/riscv/rvv/vls/vls-types.h: New test. --- gcc/config/riscv/riscv-modes.def | 3 + gcc/config/riscv/riscv-protos.h | 4 ++ gcc/config/riscv/riscv-v.cc | 67 +++++++++++++++++++ gcc/config/riscv/riscv.cc | 27 +++++++- gcc/config/riscv/vector-iterators.md | 6 ++ gcc/config/riscv/vector-vls.md | 64 ++++++++++++++++++ gcc/config/riscv/vector.md | 2 + gcc/testsuite/gcc.target/riscv/rvv/rvv.exp | 4 ++ .../gcc.target/riscv/rvv/vls/binop-template.h | 18 +++++ .../gcc.target/riscv/rvv/vls/binop-v.c | 18 +++++ .../gcc.target/riscv/rvv/vls/binop-zve32x.c | 18 +++++ .../gcc.target/riscv/rvv/vls/binop-zve64x.c | 18 +++++ .../riscv/rvv/vls/load-store-template.h | 8 +++ .../gcc.target/riscv/rvv/vls/load-store-v.c | 17 +++++ .../riscv/rvv/vls/load-store-zve32x.c | 17 +++++ .../riscv/rvv/vls/load-store-zve64x.c | 17 +++++ .../gcc.target/riscv/rvv/vls/move-template.h | 13 ++++ .../gcc.target/riscv/rvv/vls/move-v.c | 10 +++ .../gcc.target/riscv/rvv/vls/move-zve32x.c | 10 +++ .../gcc.target/riscv/rvv/vls/move-zve64x.c | 10 +++ .../gcc.target/riscv/rvv/vls/vls-types.h | 42 ++++++++++++ 21 files changed, 391 insertions(+), 2 deletions(-) create mode 100644 gcc/config/riscv/vector-vls.md create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/binop-template.h create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/binop-v.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/binop-zve32x.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/binop-zve64x.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-template.h create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-v.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-zve32x.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-zve64x.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/move-template.h create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/move-v.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/move-zve32x.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/move-zve64x.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/vls-types.h diff --git a/gcc/config/riscv/riscv-modes.def b/gcc/config/riscv/riscv-modes.def index 19a4f9fb3db..f897e560667 100644 --- a/gcc/config/riscv/riscv-modes.def +++ b/gcc/config/riscv/riscv-modes.def @@ -318,6 +318,9 @@ RVV_TUPLE_PARTIAL_MODES (6) RVV_TUPLE_PARTIAL_MODES (7) RVV_TUPLE_PARTIAL_MODES (8) +/* VLS modes. */ +VECTOR_MODES (INT, 16); /* V16QI V8HI V4SI V2DI */ + /* TODO: According to RISC-V 'V' ISA spec, the maximun vector length can be 65536 for a single vector register which means the vector mode in GCC can be maximum = 65536 * 8 bits (LMUL=8). diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 0462f96c8d5..56f714bbfb5 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -261,6 +261,10 @@ enum frm_field_enum opt_machine_mode vectorize_related_mode (machine_mode, scalar_mode, poly_uint64); unsigned int autovectorize_vector_modes (vec *, bool); +machine_mode minimal_vla_mode (machine_mode); +void +vls_insn_expander (unsigned, int, rtx *, machine_mode, machine_mode); +bool vls_mode_p (machine_mode); } /* We classify builtin types into two classes: diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc index a5715bb466c..f9fb8cd9be4 100644 --- a/gcc/config/riscv/riscv-v.cc +++ b/gcc/config/riscv/riscv-v.cc @@ -1697,4 +1697,71 @@ expand_vcond (rtx *ops) gen_vcond_mask (data_mode, data_mode, ops[0], ops[1], ops[2], mask)); } +/* Return the minimal containable VLA mode for MODE. */ + +machine_mode +minimal_vla_mode (machine_mode mode) +{ + gcc_assert (GET_MODE_NUNITS (mode).is_constant ()); + unsigned type_size = GET_MODE_NUNITS (mode).to_constant (); + poly_uint64 nunits = type_size * poly_uint64 (1, 1); + opt_machine_mode vla_mode = get_vector_mode (GET_MODE_INNER (mode), nunits); + return vla_mode.else_void (); +} + +/* Return true if MODE is true VLS mode. */ + +bool +vls_mode_p (machine_mode mode) +{ + switch (mode) + { + case E_V4SImode: + case E_V2DImode: + case E_V8HImode: + case E_V16QImode: + return true; + default: + return false; + } +} + +/* Convert all OPERANDS to VLA_MODE. */ + +static void +update_vls_mode (machine_mode vla_mode, unsigned n_operands, rtx *operands) +{ + unsigned i; + for (i = 0; i < n_operands; ++i) + { + switch (GET_CODE (operands[i])) + { + case REG: + operands[i] = gen_rtx_REG (vla_mode, REGNO (operands[i])); + break; + case MEM: + operands[i] = change_address (operands[i], vla_mode, NULL_RTX); + break; + default: + gcc_unreachable (); + } + } +} + +/* Expand VLS operation to VLA pattern. */ + +void +vls_insn_expander (unsigned icode, int op_num, rtx *operands, + machine_mode vls_mode, machine_mode vla_mode) +{ + update_vls_mode (vla_mode, /* n_operands */ op_num, operands); + + poly_uint16 nunit = GET_MODE_NUNITS (vls_mode); + + gcc_assert (nunit.is_constant ()); + + riscv_vector::emit_nonvlmax_insn (icode, op_num, operands, + GEN_INT (nunit.to_constant ())); +} + } // namespace riscv_vector diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 3954fc07a8b..2e14f2e0d53 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -1034,7 +1034,8 @@ riscv_v_ext_tuple_mode_p (machine_mode mode) static bool riscv_v_ext_mode_p (machine_mode mode) { - return riscv_v_ext_vector_mode_p (mode) || riscv_v_ext_tuple_mode_p (mode); + return riscv_v_ext_vector_mode_p (mode) || riscv_v_ext_tuple_mode_p (mode) + || riscv_vector::vls_mode_p (mode); } /* Call from ADJUST_NUNITS in riscv-modes.def. Return the correct @@ -1043,7 +1044,7 @@ riscv_v_ext_mode_p (machine_mode mode) poly_int64 riscv_v_adjust_nunits (machine_mode mode, int scale) { - if (riscv_v_ext_mode_p (mode)) + if (riscv_v_ext_mode_p (mode) && !riscv_vector::vls_mode_p (mode)) return riscv_vector_chunks * scale; return scale; } @@ -6059,6 +6060,22 @@ riscv_register_move_cost (machine_mode mode, static unsigned int riscv_hard_regno_nregs (unsigned int regno, machine_mode mode) { + if (riscv_vector::vls_mode_p (mode)) + { + if (TARGET_MIN_VLEN) + { + unsigned min_byte_per_vector_register = TARGET_MIN_VLEN / 8; + unsigned mode_size = GET_MODE_SIZE (mode).to_constant (); + + if (min_byte_per_vector_register >= mode_size) + return 1; + + return mode_size / min_byte_per_vector_register; + } + else + return 1; + } + if (riscv_v_ext_vector_mode_p (mode)) { /* Handle fractional LMUL, it only occupy part of vector register but @@ -6148,6 +6165,10 @@ riscv_hard_regno_mode_ok (unsigned int regno, machine_mode mode) but for mask vector register, register numbers can be any number. */ int lmul = 1; machine_mode rvv_mode = mode; + + if (riscv_vector::vls_mode_p (mode)) + rvv_mode = riscv_vector::minimal_vla_mode (mode); + if (riscv_v_ext_tuple_mode_p (rvv_mode)) rvv_mode = riscv_vector::get_subpart_mode (rvv_mode); poly_int64 size = GET_MODE_SIZE (rvv_mode); @@ -7223,6 +7244,8 @@ riscv_vector_alignment (const_tree type) poly_uint64 riscv_regmode_natural_size (machine_mode mode) { + if (riscv_vector::vls_mode_p (mode)) + return GET_MODE_SIZE (mode); /* The natural size for RVV data modes is one RVV data vector, and similarly for predicates. We can't independently modify anything smaller than that. */ diff --git a/gcc/config/riscv/vector-iterators.md b/gcc/config/riscv/vector-iterators.md index 70fb5b80b1b..650f2651c7d 100644 --- a/gcc/config/riscv/vector-iterators.md +++ b/gcc/config/riscv/vector-iterators.md @@ -84,6 +84,10 @@ (define_c_enum "unspec" [ UNSPEC_MODIFY_VL ]) +(define_mode_iterator VLS [ + V2DI V4SI V8HI V16QI +]) + (define_mode_iterator V [ (VNx1QI "TARGET_MIN_VLEN < 128") VNx2QI VNx4QI VNx8QI VNx16QI VNx32QI (VNx64QI "TARGET_MIN_VLEN > 32") (VNx128QI "TARGET_MIN_VLEN >= 128") (VNx1HI "TARGET_MIN_VLEN < 128") VNx2HI VNx4HI VNx8HI VNx16HI (VNx32HI "TARGET_MIN_VLEN > 32") (VNx64HI "TARGET_MIN_VLEN >= 128") @@ -976,6 +980,7 @@ (define_mode_attr VM [ (VNx2x4DF "VNx4BI") (VNx3x4DF "VNx4BI") (VNx4x4DF "VNx4BI") (VNx2x2DF "VNx2BI") (VNx3x2DF "VNx2BI") (VNx4x2DF "VNx2BI") (VNx5x2DF "VNx2BI") (VNx6x2DF "VNx2BI") (VNx7x2DF "VNx2BI") (VNx8x2DF "VNx2BI") (VNx2x1DF "VNx1BI") (VNx3x1DF "VNx1BI") (VNx4x1DF "VNx1BI") (VNx5x1DF "VNx1BI") (VNx6x1DF "VNx1BI") (VNx7x1DF "VNx1BI") (VNx8x1DF "VNx1BI") + (V2DI "V2BI") (V4SI "V4BI") (V8HI "V8BI") (V16QI "V16BI") ]) (define_mode_attr vm [ @@ -1003,6 +1008,7 @@ (define_mode_attr vel [ (VNx1DI "di") (VNx2DI "di") (VNx4DI "di") (VNx8DI "di") (VNx16DI "di") (VNx1SF "sf") (VNx2SF "sf") (VNx4SF "sf") (VNx8SF "sf") (VNx16SF "sf") (VNx32SF "sf") (VNx1DF "df") (VNx2DF "df") (VNx4DF "df") (VNx8DF "df") (VNx16DF "df") + (V2DI "di") (V4SI "si") (V8HI "hi") (V16QI "qi") ]) (define_mode_attr VSUBEL [ diff --git a/gcc/config/riscv/vector-vls.md b/gcc/config/riscv/vector-vls.md new file mode 100644 index 00000000000..af7e7a6c726 --- /dev/null +++ b/gcc/config/riscv/vector-vls.md @@ -0,0 +1,64 @@ +;; Machine description for vector length specific type operation with +;; RISC-V 'V' Extension for GNU compiler. +;; Copyright (C) 2023 Free Software Foundation, Inc. + +;; This file is part of GCC. + +;; GCC is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; GCC is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; . + +(define_expand "mov" + [(set (match_operand:VLS 0 "nonimmediate_operand") + (match_operand:VLS 1 "vector_move_operand"))] + "TARGET_VECTOR" +{ + // TODO: Only allow register and memory now, we should allow legal + // vector_const too. + if (MEM_P (operands[0]) && MEM_P (operands[1])) + operands[1] = force_reg (GET_MODE(operands[1]), operands[1]); +}) + +(define_insn_and_split "*mov" + [(set (match_operand:VLS 0 "nonimmediate_operand" "=vr,vr, m,vr") + (match_operand:VLS 1 "vector_move_operand" " vr, m,vr,vi"))] + "TARGET_VECTOR && + (register_operand (operands[0], mode) + || register_operand (operands[1], mode))" + "#" + "reload_completed" + [(const_int 0)] +{ + machine_mode vla_mode = riscv_vector::minimal_vla_mode (mode); + riscv_vector::vls_insn_expander ( + code_for_pred_mov (vla_mode), riscv_vector::RVV_UNOP, operands, + mode, vla_mode); + DONE; +}) + +(define_insn_and_split "3" + [(set (match_operand:VLS 0 "register_operand" "=vr") + (any_int_binop_no_shift:VLS + (match_operand:VLS 1 "register_operand" "vr") + (match_operand:VLS 2 "register_operand" "vr")))] + "TARGET_VECTOR" + "#" + "reload_completed" + [(const_int 0)] +{ + machine_mode vla_mode = riscv_vector::minimal_vla_mode (mode); + riscv_vector::vls_insn_expander ( + code_for_pred (, vla_mode), riscv_vector::RVV_BINOP, + operands, mode, vla_mode); + DONE; +}) diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md index cd696da5d89..e3fd0807b22 100644 --- a/gcc/config/riscv/vector.md +++ b/gcc/config/riscv/vector.md @@ -25,6 +25,7 @@ ;; - Intrinsics (https://github.com/riscv/rvv-intrinsic-doc) ;; - Auto-vectorization (autovec.md) ;; - Combine optimization (TBD) +;; - VLS patterns (vector-vls.md) (include "vector-iterators.md") @@ -8407,3 +8408,4 @@ (define_split ) (include "autovec.md") +(include "vector-vls.md") diff --git a/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp index bf03570b9cc..f6c56a63ada 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp +++ b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp @@ -77,5 +77,9 @@ foreach op $AUTOVEC_TEST_OPTS { dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/autovec/vls-vlmax/*.\[cS\]]] \ "-std=c99 -O3 -ftree-vectorize --param riscv-autovec-preference=fixed-vlmax" $CFLAGS +# VLS test +gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/vls/*.\[cS\]]] \ + "" $CFLAGS + # All done. dg-finish diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-template.h b/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-template.h new file mode 100644 index 00000000000..0114c124646 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-template.h @@ -0,0 +1,18 @@ +#include "vls-types.h" +#define __BINOP(NAME, OP, VLS_TYPE, SCALAR_TYPE) \ +void binop_##NAME##VLS_TYPE \ + (VLS_TYPE *src1, VLS_TYPE *src2, VLS_TYPE *dst) \ +{ \ + *dst = *src1 OP *src2; \ +} + +#define BINOP(VLS_TYPE, SCALAR_TYPE) \ +__BINOP (ADD, +, VLS_TYPE, SCALAR_TYPE) \ +__BINOP (MUL, *, VLS_TYPE, SCALAR_TYPE) \ +__BINOP (DIV, /, VLS_TYPE, SCALAR_TYPE) \ +__BINOP (MOD, %, VLS_TYPE, SCALAR_TYPE) \ +__BINOP (AND, &, VLS_TYPE, SCALAR_TYPE) \ +__BINOP (IOR, |, VLS_TYPE, SCALAR_TYPE) \ +__BINOP (XOR, ^, VLS_TYPE, SCALAR_TYPE) + +FOR_EACH_VLS_TYPE(BINOP) diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-v.c b/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-v.c new file mode 100644 index 00000000000..78c1a19cfbf --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-v.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv -mabi=lp64" } */ + +#include "binop-template.h" + +/* { dg-final { scan-assembler {vsetivli\s+zero,16,e8,m1} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,8,e16,m1} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,4,e32,m1} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,2,e64,m1} } } */ +/* { dg-final { scan-assembler-times {vadd\.vv} 8} } */ +/* { dg-final { scan-assembler-times {vmul\.vv} 8} } */ +/* { dg-final { scan-assembler-times {vdiv\.vv} 4} } */ +/* { dg-final { scan-assembler-times {vdivu\.vv} 4 } } */ +/* { dg-final { scan-assembler-times {vrem\.vv} 4} } */ +/* { dg-final { scan-assembler-times {vremu\.vv} 4 } } */ +/* { dg-final { scan-assembler-times {vand\.vv} 8} } */ +/* { dg-final { scan-assembler-times {vor\.vv} 8 } } */ +/* { dg-final { scan-assembler-times {vxor\.vv} 8} } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-zve32x.c b/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-zve32x.c new file mode 100644 index 00000000000..bca56ba32a5 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-zve32x.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gc_zve32x -mabi=ilp32" } */ + +#include "binop-template.h" + +/* { dg-final { scan-assembler {vsetivli\s+zero,16,e8,m4} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,8,e16,m4} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,4,e32,m4} } } */ +/* { dg-final { scan-assembler-not {vsetivli\s+zero,2,e64,m4} } } */ +/* { dg-final { scan-assembler-times {vadd\.vv} 6} } */ +/* { dg-final { scan-assembler-times {vmul\.vv} 6} } */ +/* { dg-final { scan-assembler-times {vdiv\.vv} 3} } */ +/* { dg-final { scan-assembler-times {vdivu\.vv} 3 } } */ +/* { dg-final { scan-assembler-times {vrem\.vv} 3} } */ +/* { dg-final { scan-assembler-times {vremu\.vv} 3 } } */ +/* { dg-final { scan-assembler-times {vand\.vv} 6} } */ +/* { dg-final { scan-assembler-times {vor\.vv} 6 } } */ +/* { dg-final { scan-assembler-times {vxor\.vv} 6} } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-zve64x.c b/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-zve64x.c new file mode 100644 index 00000000000..45dcad12a93 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-zve64x.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gc_zve64x -mabi=ilp32" } */ + +#include "binop-template.h" + +/* { dg-final { scan-assembler {vsetivli\s+zero,16,e8,m2} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,8,e16,m2} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,4,e32,m2} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,2,e64,m2} } } */ +/* { dg-final { scan-assembler-times {vadd\.vv} 8} } */ +/* { dg-final { scan-assembler-times {vmul\.vv} 8} } */ +/* { dg-final { scan-assembler-times {vdiv\.vv} 4} } */ +/* { dg-final { scan-assembler-times {vdivu\.vv} 4 } } */ +/* { dg-final { scan-assembler-times {vrem\.vv} 4} } */ +/* { dg-final { scan-assembler-times {vremu\.vv} 4 } } */ +/* { dg-final { scan-assembler-times {vand\.vv} 8} } */ +/* { dg-final { scan-assembler-times {vor\.vv} 8 } } */ +/* { dg-final { scan-assembler-times {vxor\.vv} 8} } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-template.h b/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-template.h new file mode 100644 index 00000000000..9ea0c7cb5dc --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-template.h @@ -0,0 +1,8 @@ +#include "vls-types.h" +#define LOAD_STORE(VLS_TYPE, SCALAR_TYPE) \ +void load_store_##VLS_TYPE (VLS_TYPE *src, VLS_TYPE *dst) \ +{ \ + *dst = *src; \ +} + +FOR_EACH_VLS_TYPE(LOAD_STORE) diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-v.c b/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-v.c new file mode 100644 index 00000000000..b8adcea70d6 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-v.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv -mabi=lp64" } */ + +#include "load-store-template.h" + +/* { dg-final { scan-assembler {vsetivli\s+zero,16,e8,m1} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,8,e16,m1} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,4,e32,m1} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,2,e64,m1} } } */ +/* { dg-final { scan-assembler-times {vle8\.v} 2 } } */ +/* { dg-final { scan-assembler-times {vle16\.v} 2 } } */ +/* { dg-final { scan-assembler-times {vle32\.v} 2 } } */ +/* { dg-final { scan-assembler-times {vle64\.v} 2 } } */ +/* { dg-final { scan-assembler-times {vse8\.v} 2 } } */ +/* { dg-final { scan-assembler-times {vse16\.v} 2 } } */ +/* { dg-final { scan-assembler-times {vse32\.v} 2 } } */ +/* { dg-final { scan-assembler-times {vse64\.v} 2 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-zve32x.c b/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-zve32x.c new file mode 100644 index 00000000000..ef3426d00a1 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-zve32x.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gc_zve32x -mabi=ilp32" } */ + +#include "load-store-template.h" + +/* { dg-final { scan-assembler {vsetivli\s+zero,16,e8,m4} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,8,e16,m4} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,4,e32,m4} } } */ +/* { dg-final { scan-assembler-not {vsetivli\s+zero,2,e64,m4} } } */ +/* { dg-final { scan-assembler-times {vle8\.v} 2 } } */ +/* { dg-final { scan-assembler-times {vle16\.v} 2 } } */ +/* { dg-final { scan-assembler-times {vle32\.v} 2 } } */ +/* { dg-final { scan-assembler-not {vle64\.v} } } */ +/* { dg-final { scan-assembler-times {vse8\.v} 2 } } */ +/* { dg-final { scan-assembler-times {vse16\.v} 2 } } */ +/* { dg-final { scan-assembler-times {vse32\.v} 2 } } */ +/* { dg-final { scan-assembler-not {vse64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-zve64x.c b/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-zve64x.c new file mode 100644 index 00000000000..e03220d89f8 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-zve64x.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gc_zve64x -mabi=ilp32" } */ + +#include "load-store-template.h" + +/* { dg-final { scan-assembler {vsetivli\s+zero,16,e8,m2} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,8,e16,m2} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,4,e32,m2} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,2,e64,m2} } } */ +/* { dg-final { scan-assembler-times {vle8\.v} 2 } } */ +/* { dg-final { scan-assembler-times {vle16\.v} 2 } } */ +/* { dg-final { scan-assembler-times {vle32\.v} 2 } } */ +/* { dg-final { scan-assembler-times {vle64\.v} 2 } } */ +/* { dg-final { scan-assembler-times {vse8\.v} 2 } } */ +/* { dg-final { scan-assembler-times {vse16\.v} 2 } } */ +/* { dg-final { scan-assembler-times {vse32\.v} 2 } } */ +/* { dg-final { scan-assembler-times {vse64\.v} 2 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/move-template.h b/gcc/testsuite/gcc.target/riscv/rvv/vls/move-template.h new file mode 100644 index 00000000000..e328a42204c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/move-template.h @@ -0,0 +1,13 @@ +#include "vls-types.h" + +#define MOVE(VLS_TYPE, SCALAR_TYPE) \ +void move_##VLS_TYPE () \ +{ \ + register VLS_TYPE src##VLS_TYPE __asm__ ("v0"); \ + register VLS_TYPE dst##VLS_TYPE __asm__ ("v8"); \ + __asm__ volatile ("#def" : "=vr"(src##VLS_TYPE)); \ + dst##VLS_TYPE = src##VLS_TYPE; \ + __asm__ volatile ("#use" : : "vr"(dst##VLS_TYPE)); \ +} + +FOR_EACH_VLS_TYPE(MOVE) diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/move-v.c b/gcc/testsuite/gcc.target/riscv/rvv/vls/move-v.c new file mode 100644 index 00000000000..91c89df098e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/move-v.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv -mabi=lp64" } */ + +#include "move-template.h" + +/* { dg-final { scan-assembler {vsetivli\s+zero,16,e8,m1} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,8,e16,m1} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,4,e32,m1} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,2,e64,m1} } } */ +/* { dg-final { scan-assembler-times {vmv\.v\.v} 8 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/move-zve32x.c b/gcc/testsuite/gcc.target/riscv/rvv/vls/move-zve32x.c new file mode 100644 index 00000000000..175986edf15 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/move-zve32x.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gc_zve32x -mabi=ilp32" } */ + +#include "move-template.h" + +/* { dg-final { scan-assembler {vsetivli\s+zero,16,e8,m4} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,8,e16,m4} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,4,e32,m4} } } */ +/* { dg-final { scan-assembler-not {vsetivli\s+zero,2,e64,m4} } } */ +/* { dg-final { scan-assembler-times {vmv\.v\.v} 6 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/move-zve64x.c b/gcc/testsuite/gcc.target/riscv/rvv/vls/move-zve64x.c new file mode 100644 index 00000000000..2e574b1f3ee --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/move-zve64x.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gc_zve64x -mabi=ilp32" } */ + +#include "move-template.h" + +/* { dg-final { scan-assembler {vsetivli\s+zero,16,e8,m2} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,8,e16,m2} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,4,e32,m2} } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,2,e64,m2} } } */ +/* { dg-final { scan-assembler-times {vmv\.v\.v} 8 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/vls-types.h b/gcc/testsuite/gcc.target/riscv/rvv/vls/vls-types.h new file mode 100644 index 00000000000..302823b583f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/vls-types.h @@ -0,0 +1,42 @@ +#ifndef __VLS_TYPE_H +#define __VLS_TYPE_H +#include + +typedef int8_t int8x16_t __attribute__ ((vector_size (16))); +typedef int16_t int16x8_t __attribute__ ((vector_size (16))); +typedef int32_t int32x4_t __attribute__ ((vector_size (16))); +typedef int64_t int64x2_t __attribute__ ((vector_size (16))); + +typedef uint8_t uint8x16_t __attribute__ ((vector_size (16))); +typedef uint16_t uint16x8_t __attribute__ ((vector_size (16))); +typedef uint32_t uint32x4_t __attribute__ ((vector_size (16))); +typedef uint64_t uint64x2_t __attribute__ ((vector_size (16))); + + +#if __riscv_v_elen == 32 + +#define FOR_EACH_VLS_TYPE(FUNC) \ + FUNC (int8x16_t, int8_t) \ + FUNC (int16x8_t, int16_t) \ + FUNC (int32x4_t, int32_t) \ + FUNC (uint8x16_t, uint8_t) \ + FUNC (uint16x8_t, uint16_t) \ + FUNC (uint32x4_t, uint32_t) + +#elif __riscv_v_elen == 64 + +#define FOR_EACH_VLS_TYPE(FUNC) \ + FUNC (int8x16_t, int8_t) \ + FUNC (int16x8_t, int16_t) \ + FUNC (int32x4_t, int32_t) \ + FUNC (int64x2_t, int64_t) \ + FUNC (uint8x16_t, uint8_t) \ + FUNC (uint16x8_t, uint16_t) \ + FUNC (uint32x4_t, uint32_t) \ + FUNC (uint64x2_t, uint64_t) + +#else +#error "zve* or v extension is required." +#endif + +#endif -- 2.40.1