From patchwork Tue May 31 08:49:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "juzhe.zhong@rivai.ai" X-Patchwork-Id: 54546 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A755F3954421 for ; Tue, 31 May 2022 08:53:31 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from smtpbgsg2.qq.com (smtpbgsg2.qq.com [54.254.200.128]) by sourceware.org (Postfix) with ESMTPS id 697D4386F463 for ; Tue, 31 May 2022 08:50:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 697D4386F463 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=rivai.ai Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=rivai.ai X-QQ-mid: bizesmtp84t1653987025tmm7icwv Received: from server1.localdomain ( [42.247.22.65]) by bizesmtp.qq.com (ESMTP) with id ; Tue, 31 May 2022 16:50:24 +0800 (CST) X-QQ-SSF: 01400000002000B0F000000A0000000 X-QQ-FEAT: 0VgNaGdhy9iV3OGcTTZT+ByT6OlgolLye3sgRjec1mugZo/B2iylQPhW+KZry 5YUjDueopGqNGAhToWIMLmQ8Xsvwcalb9rLJC9qIGpDPHY1vFjuyEWnp2egMxTYLnlQ5hcp 7DdIFslbmVMhrsdhsUiYHQeOZ47DbBmYFLR/v+IJ8FDd2YeNB4yRKhGZhSn+MOLIs3y41Vs myenhY/Pb+t+r3LZ9CK6aGSP97ynsxtqR9vM0ojiHGfSfB5JfndgNapjec5sElxGsGAbOeQ 2Z/b5QzIELzDGfgMgLcie+hKvGItzg7gI7vw9443grBchLSV+OA478RggYLlHW0uzZ0JU4H dAkXWI6Jg6iN6ag4/BFJEwDzpyPh+2oJlJ9TPiB X-QQ-GoodBg: 2 From: juzhe.zhong@rivai.ai To: gcc-patches@gcc.gnu.org Subject: [PATCH 03/21] Add RVV datatypes Date: Tue, 31 May 2022 16:49:54 +0800 Message-Id: <20220531085012.269719-4-juzhe.zhong@rivai.ai> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220531085012.269719-1-juzhe.zhong@rivai.ai> References: <20220531085012.269719-1-juzhe.zhong@rivai.ai> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:rivai.ai:qybgforeign:qybgforeign10 X-QQ-Bgrelay: 1 X-Spam-Status: No, score=-8.5 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, 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 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kito.cheng@gmail.com, juzhe.zhong@rivai.ai Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" From: zhongjuzhe gcc/ChangeLog: * config/riscv/riscv-vector-builtins.cc (make_type_sizeless): New function. (sizeless_type_p): New function. (vector_builtin_mode): New function. (vector_legal_vlmul): New function. (add_vector_type_attribute): New function. (register_general_builtin_types): New function. (DEFINE_SCALAR_PTR_TYPE_NODE): New function. (register_builtin_types): New function. (register_vector_type): New function. (handle_pragma_vector): New function. (lookup_rvv_type_attribute): New function. (builtin_type_p): New function. (verify_type_context): New function. (mangle_builtin_type): New function. * config/riscv/riscv-vector-builtins.h (builtin_type_p): New function. (verify_type_context): New function. (mangle_builtin_type): New function. * config/riscv/riscv.cc (riscv_vector_mode_supported_p): New function. (riscv_vector_alignment): New function. (riscv_vectorize_preferred_vector_alignment): New function. (riscv_simd_vector_alignment_reachable): New function. (riscv_builtin_support_vector_misalignment): New function. (riscv_compatible_vector_types_p): New function. (riscv_verify_type_context): New function. (riscv_mangle_type): New function. (TARGET_VECTOR_MODE_SUPPORTED_P): New targethook. (TARGET_VECTOR_ALIGNMENT): New targethook. (TARGET_VECTORIZE_PREFERRED_VECTOR_ALIGNMENT): New targethook. (TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE): New targethook. (TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT): New targethook. (TARGET_COMPATIBLE_VECTOR_TYPES_P): New targethook. (TARGET_VERIFY_TYPE_CONTEXT): New targethook. (TARGET_MANGLE_TYPE): New targethook. --- gcc/config/riscv/riscv-vector-builtins.cc | 466 ++++++++++++++++++++++ gcc/config/riscv/riscv-vector-builtins.h | 3 + gcc/config/riscv/riscv.cc | 144 +++++++ 3 files changed, 613 insertions(+) diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc index 7ea07a24b5b..ef734572add 100644 --- a/gcc/config/riscv/riscv-vector-builtins.cc +++ b/gcc/config/riscv/riscv-vector-builtins.cc @@ -109,6 +109,286 @@ static unsigned int NUM_INSN_FUNC; static void init_def_variables (); +/* Force TYPE to be a sizeless type. */ +static void +make_type_sizeless (tree type) +{ + TYPE_ATTRIBUTES (type) = tree_cons (get_identifier ("RVV sizeless type"), + NULL_TREE, TYPE_ATTRIBUTES (type)); +} + +/* Return true if TYPE is a sizeless type. */ +static bool +sizeless_type_p (const_tree type) +{ + if (type == error_mark_node) + return NULL_TREE; + return lookup_attribute ("RVV sizeless type", TYPE_ATTRIBUTES (type)); +} + +machine_mode +vector_builtin_mode (scalar_mode inner_mode, enum vlmul_field_enum vlmul) +{ + switch (inner_mode) + { + case E_BImode: + return vlmul == VLMUL_FIELD_000 ? VNx16BImode + : vlmul == VLMUL_FIELD_001 ? VNx32BImode + : vlmul == VLMUL_FIELD_010 ? VNx64BImode + : vlmul == VLMUL_FIELD_011 ? VNx128BImode + : vlmul == VLMUL_FIELD_111 ? VNx8BImode + : vlmul == VLMUL_FIELD_110 ? VNx4BImode + : VNx2BImode; + + case E_QImode: + return vlmul == VLMUL_FIELD_000 ? VNx16QImode + : vlmul == VLMUL_FIELD_001 ? VNx32QImode + : vlmul == VLMUL_FIELD_010 ? VNx64QImode + : vlmul == VLMUL_FIELD_011 ? VNx128QImode + : vlmul == VLMUL_FIELD_111 ? VNx8QImode + : vlmul == VLMUL_FIELD_110 ? VNx4QImode + : VNx2QImode; + + case E_HImode: + if (vlmul == VLMUL_FIELD_101) + gcc_unreachable (); + + return vlmul == VLMUL_FIELD_000 ? VNx8HImode + : vlmul == VLMUL_FIELD_001 ? VNx16HImode + : vlmul == VLMUL_FIELD_010 ? VNx32HImode + : vlmul == VLMUL_FIELD_011 ? VNx64HImode + : vlmul == VLMUL_FIELD_111 ? VNx4HImode + : VNx2HImode; + + case E_SImode: + if (vlmul == VLMUL_FIELD_101 || vlmul == VLMUL_FIELD_110) + gcc_unreachable (); + + return vlmul == VLMUL_FIELD_000 ? VNx4SImode + : vlmul == VLMUL_FIELD_001 ? VNx8SImode + : vlmul == VLMUL_FIELD_010 ? VNx16SImode + : vlmul == VLMUL_FIELD_011 ? VNx32SImode + : VNx2SImode; + + case E_DImode: + if (vlmul == VLMUL_FIELD_101 || vlmul == VLMUL_FIELD_110 || + vlmul == VLMUL_FIELD_111) + gcc_unreachable (); + + return vlmul == VLMUL_FIELD_000 ? VNx2DImode + : vlmul == VLMUL_FIELD_001 ? VNx4DImode + : vlmul == VLMUL_FIELD_010 ? VNx8DImode + : VNx16DImode; + + case E_SFmode: + if (vlmul == VLMUL_FIELD_101 || vlmul == VLMUL_FIELD_110) + gcc_unreachable (); + + return vlmul == VLMUL_FIELD_000 ? VNx4SFmode + : vlmul == VLMUL_FIELD_001 ? VNx8SFmode + : vlmul == VLMUL_FIELD_010 ? VNx16SFmode + : vlmul == VLMUL_FIELD_011 ? VNx32SFmode + : VNx2SFmode; + + case E_DFmode: + if (vlmul == VLMUL_FIELD_101 || vlmul == VLMUL_FIELD_110 || + vlmul == VLMUL_FIELD_111) + gcc_unreachable (); + + return vlmul == VLMUL_FIELD_000 ? VNx2DFmode + : vlmul == VLMUL_FIELD_001 ? VNx4DFmode + : vlmul == VLMUL_FIELD_010 ? VNx8DFmode + : VNx16DFmode; + + default: + gcc_unreachable (); + } + + gcc_unreachable (); +} + +static bool +vector_legal_vlmul (scalar_mode inner_mode, enum vlmul_field_enum vlmul) +{ + if (vlmul == VLMUL_FIELD_100) + return false; + + switch (inner_mode) + { + case E_HImode: + return vlmul != VLMUL_FIELD_101; + + case E_SImode: + case E_SFmode: + return vlmul != VLMUL_FIELD_101 && vlmul != VLMUL_FIELD_110; + + case E_DImode: + case E_DFmode: + return vlmul <= VLMUL_FIELD_011; + + default: + break; + } + + return true; +} + +/* Record that TYPE is an ABI-defined VECTOR type that contains SEW and LMUL + information for RVV vector. MANGLED_NAME, if nonnull, is the ABI-defined + mangling of the type. + */ +static void +add_vector_type_attribute (tree type, unsigned int nf, unsigned int sew, unsigned int vlmul, + unsigned int is_bool, const char *mangled_name) +{ + tree mangled_name_tree + = (mangled_name ? get_identifier (mangled_name) : NULL_TREE); + + tree value = tree_cons (NULL_TREE, mangled_name_tree, NULL_TREE); + value = tree_cons (NULL_TREE, size_int (nf), value); + value = tree_cons (NULL_TREE, size_int (sew), value); + value = tree_cons (NULL_TREE, size_int (vlmul), value); + value = tree_cons (NULL_TREE, size_int (is_bool), value); + TYPE_ATTRIBUTES (type) = tree_cons (get_identifier ("RVV type"), value, + TYPE_ATTRIBUTES (type)); +} + +/* These codes copied from ARM. */ +static void +register_general_builtin_types (void) +{ + scalar_types[VECTOR_TYPE_bool] = boolean_type_node; + scalar_types[VECTOR_TYPE_int8] = intQI_type_node; + scalar_types[VECTOR_TYPE_uint8] = unsigned_intQI_type_node; + scalar_types[VECTOR_TYPE_int16] = intHI_type_node; + scalar_types[VECTOR_TYPE_uint16] = unsigned_intHI_type_node; + + if (TARGET_64BIT) + { + scalar_types[VECTOR_TYPE_int32] = intSI_type_node; + scalar_types[VECTOR_TYPE_uint32] = unsigned_intSI_type_node; + } + else + { + /* int32_t/uint32_t defined as `long`/`unsigned long` in RV32, + but intSI_type_node/unsigned_intSI_type_node is + `int` and `unsigned int`, so use long_integer_type_node and + long_unsigned_type_node here for type consistent. */ + scalar_types[VECTOR_TYPE_int32] = long_integer_type_node; + scalar_types[VECTOR_TYPE_uint32] = long_unsigned_type_node; + } + + scalar_types[VECTOR_TYPE_int64] = intDI_type_node; + scalar_types[VECTOR_TYPE_uint64] = unsigned_intDI_type_node; + scalar_types[VECTOR_TYPE_float32] = float_type_node; + scalar_types[VECTOR_TYPE_float64] = double_type_node; + + /* Pointer type */ +#define DEFINE_SCALAR_PTR_TYPE_NODE(NBITS) \ + scalar_pointer_types[VECTOR_TYPE_int##NBITS] = \ + build_pointer_type (scalar_types[VECTOR_TYPE_int##NBITS]); \ + scalar_pointer_types[VECTOR_TYPE_uint##NBITS] = \ + build_pointer_type (scalar_types[VECTOR_TYPE_uint##NBITS]); \ + const_scalar_pointer_types[VECTOR_TYPE_int##NBITS] = build_pointer_type ( \ + build_type_variant (scalar_types[VECTOR_TYPE_int##NBITS], 1, 0)); \ + const_scalar_pointer_types[VECTOR_TYPE_uint##NBITS] = build_pointer_type ( \ + build_type_variant (scalar_types[VECTOR_TYPE_uint##NBITS], 1, 0)); + + DEFINE_SCALAR_PTR_TYPE_NODE (8) + DEFINE_SCALAR_PTR_TYPE_NODE (16) + DEFINE_SCALAR_PTR_TYPE_NODE (32) + DEFINE_SCALAR_PTR_TYPE_NODE (64) + + scalar_pointer_types[VECTOR_TYPE_float32] = float_ptr_type_node; + scalar_pointer_types[VECTOR_TYPE_float64] = double_ptr_type_node; + const_scalar_pointer_types[VECTOR_TYPE_float32] = build_pointer_type ( + build_type_variant (scalar_types[VECTOR_TYPE_float32], 1, 0)); + const_scalar_pointer_types[VECTOR_TYPE_float64] = build_pointer_type ( + build_type_variant (scalar_types[VECTOR_TYPE_float64], 1, 0)); +} + +/* Register the built-in VECTOR ABI types, such as __rvv_int8mf8_t. */ +static void +register_builtin_types () +{ + for (unsigned int i = 0; i < NUM_VECTOR_TYPES; ++i) + { + tree eltype = scalar_types[i]; + scalar_mode elmode = + (eltype == boolean_type_node) ? BImode : SCALAR_TYPE_MODE (eltype); + + for (unsigned int j = 0; j < ARRAY_SIZE (vector_vlmuls); ++j) + { + if (!vector_legal_vlmul (elmode, vector_vlmuls[j].vlmul)) + continue; + + char abi_name[NAME_MAXLEN] = {0}; + char mangled_name[NAME_MAXLEN] = {0}; + bool is_bool; + tree vectype; + unsigned int sew = GET_MODE_BITSIZE (elmode); + machine_mode mode = + vector_builtin_mode (elmode, vector_vlmuls[j].vlmul); + + /* mask type in RVV. */ + vectype = build_vector_type_for_mode (eltype, mode); + + /* NOTE: Reference to 'omp_clause_aligned_alignment' function in + omp-low.c. We don't know why we need this protection, it seems + to make the buildup of GCC more reliable. */ + if (TYPE_MODE (vectype) != mode) + continue; + + if (eltype == boolean_type_node) + { + gcc_assert (VECTOR_MODE_P (TYPE_MODE (vectype)) && + TYPE_MODE (vectype) == mode && + TYPE_MODE (vectype) == TYPE_MODE_RAW (vectype) && + TYPE_ALIGN (vectype) == 8 && + known_eq (tree_to_poly_uint64 (TYPE_SIZE (vectype)), + BITS_PER_RISCV_VECTOR)); + is_bool = true; + } + else + { + gcc_assert (VECTOR_MODE_P (TYPE_MODE (vectype)) && + TYPE_MODE (vectype) == mode && + TYPE_MODE_RAW (vectype) == mode && + TYPE_ALIGN (vectype) <= 128 && + known_eq (tree_to_poly_uint64 (TYPE_SIZE (vectype)), + GET_MODE_BITSIZE (mode))); + is_bool = false; + } + /* These codes copied from ARM. */ + /* abi_name and api_name follows vector type implementation in LLVM. + Take sew = 8, vlmul = 1/8 for example, + abi_name = __rvv_int8mf8_t, + api_name = vint8mf8_t. + The mangle name follows the rule of aarch64 + that is "u" + length of (abi_name) + abi_name. + So that mangle_name = u15__rvv_int8mf8_t. */ + snprintf (abi_name, NAME_MAXLEN, "__rvv_%s%s_t", + vector_type_infos[i].elem_name, + is_bool ? vector_vlmuls[j].boolnum + : vector_vlmuls[j].suffix); + snprintf (mangled_name, NAME_MAXLEN, "u%d__rvv_%s%s_t", + (int)strlen (abi_name), vector_type_infos[i].elem_name, + is_bool ? vector_vlmuls[j].boolnum + : vector_vlmuls[j].suffix); + vectype = build_distinct_type_copy (vectype); + gcc_assert (vectype == TYPE_MAIN_VARIANT (vectype)); + SET_TYPE_STRUCTURAL_EQUALITY (vectype); + TYPE_ARTIFICIAL (vectype) = 1; + TYPE_INDIVISIBLE_P (vectype) = 1; + add_vector_type_attribute (vectype, 1, sew, vector_vlmuls[j].vlmul, is_bool, + mangled_name); + make_type_sizeless (vectype); + internal_vector_types[i][j] = vectype; + lang_hooks.types.register_builtin_type (vectype, abi_name); + } + } +} + /* Initialize all compiler built-ins related to RVV that should be defined at start-up. */ void @@ -116,6 +396,192 @@ init_builtins () { if (!TARGET_VECTOR) return; + + register_general_builtin_types (); + register_builtin_types (); + + if (in_lto_p) + handle_pragma_vector (); +} + +/* These codes copied from ARM. */ +/* Register vector type TYPE under its risv_vector.h name. */ +static void +register_vector_type (unsigned int type, unsigned int lmul) +{ + tree vectype = internal_vector_types[type][lmul]; + char rvv_name[NAME_MAXLEN] = {0}; + snprintf (rvv_name, NAME_MAXLEN, "v%s%s_t", vector_type_infos[type].elem_name, + strcmp (vector_type_infos[type].elem_name, "bool") == 0 + ? vector_vlmuls[lmul].boolnum + : vector_vlmuls[lmul].suffix); + tree id = get_identifier (rvv_name); + tree decl = build_decl (input_location, TYPE_DECL, id, vectype); + decl = lang_hooks.decls.pushdecl (decl); + + /* Record the new RVV type if pushdecl succeeded without error. Use + the ABI type otherwise, so that the type we record at least has the + right form, even if it doesn't have the right name. This should give + better error recovery behavior than installing error_mark_node or + installing an incorrect type. */ + if (decl && TREE_CODE (decl) == TYPE_DECL && + TREE_TYPE (decl) != error_mark_node && + TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == vectype) + vectype = TREE_TYPE (decl); + + vector_types[0][type][lmul] = vectype; + vector_pointer_types[type][lmul] = build_pointer_type (vectype); +} + +/* Implement #pragma riscv intrinsic vector. */ +void +handle_pragma_vector () +{ + if (function_table) + { + error ("duplicate definition of %qs", "vector"); + return; + } + + /* Define the vector and tuple types. */ + for (unsigned int i = 0; i < NUM_VECTOR_TYPES; ++i) + { + tree eltype = scalar_types[i]; + scalar_mode elmode = + (eltype == boolean_type_node) ? BImode : SCALAR_TYPE_MODE (eltype); + + for (unsigned int j = 0; j < ARRAY_SIZE (vector_vlmuls); ++j) + { + if (!vector_legal_vlmul (elmode, vector_vlmuls[j].vlmul)) + continue; + + register_vector_type (i, j); + } + } + + init_def_variables (); + + /* Define the functions. */ + function_table = new hash_table (1023); + + for (unsigned int i = 0; i < NUM_INSN_FUNC; ++i) + all_vector_functions[i]->register_function (); +} + +/* If TYPE is an ABI-defined RVV type, return its attribute descriptor, + otherwise return null. */ +static tree +lookup_rvv_type_attribute (const_tree type) +{ + if (type == error_mark_node) + return NULL_TREE; + return lookup_attribute ("RVV type", TYPE_ATTRIBUTES (type)); +} + +/* Return true if TYPE is a built-in RVV type defined by the ABI or RVV. */ +bool +builtin_type_p (const_tree type) +{ + return lookup_rvv_type_attribute (type); +} + +/* Implement TARGET_VERIFY_TYPE_CONTEXT for RVV types. */ +bool +verify_type_context (location_t loc, type_context_kind context, + const_tree type, bool silent_p) +{ + if (!sizeless_type_p (type)) + return true; + + switch (context) + { + case TCTX_SIZEOF: + case TCTX_STATIC_STORAGE: + if (!silent_p) + error_at (loc, "RVV type %qT does not have a fixed size", type); + + return false; + + case TCTX_ALIGNOF: + if (!silent_p) + error_at (loc, "RVV type %qT does not have a defined alignment", type); + + return false; + + case TCTX_THREAD_STORAGE: + if (!silent_p) + error_at (loc, + "variables of type %qT cannot have thread-local" + " storage duration", + type); + + return false; + + case TCTX_POINTER_ARITH: + if (!silent_p) + error_at (loc, "arithmetic on pointer to RVV type %qT", type); + + return false; + + case TCTX_FIELD: + if (silent_p) + ; + else if (lang_GNU_CXX ()) + error_at (loc, "member variables cannot have RVV type %qT", type); + else + error_at (loc, "fields cannot have RVV type %qT", type); + + return false; + + case TCTX_ARRAY_ELEMENT: + if (!silent_p) + error_at (loc, "array elements cannot have RVV type %qT", type); + + return false; + + case TCTX_ALLOCATION: + if (!silent_p) + error_at (loc, "cannot allocate objects with RVV type %qT", type); + + return false; + + case TCTX_DEALLOCATION: + if (!silent_p) + error_at (loc, "cannot delete objects with RVV type %qT", type); + + return false; + + case TCTX_EXCEPTIONS: + if (!silent_p) + error_at (loc, "cannot throw or catch RVV type %qT", type); + + return false; + + case TCTX_CAPTURE_BY_COPY: + if (!silent_p) + error_at (loc, "capture by copy of RVV type %qT", type); + + return false; + } + + gcc_unreachable (); +} + +/* If TYPE is a built-in type defined by the RVV ABI, return the mangled name, + otherwise return NULL. */ +const char * +mangle_builtin_type (const_tree type) +{ + /* ??? The C++ frontend normally strips qualifiers and attributes before + calling this hook, adding separate mangling for attributes that affect + type identity. Fortunately the type copy will have the same TYPE_NAME + as the original, so we can get the attributes from there. */ + if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL) + type = TREE_TYPE (TYPE_NAME (type)); + if (tree attr = lookup_rvv_type_attribute (type)) + if (tree id = TREE_VALUE (chain_index (4, TREE_VALUE (attr)))) + return IDENTIFIER_POINTER (id); + return NULL; } /* Return the function decl with RVV function subcode CODE, or error_mark_node diff --git a/gcc/config/riscv/riscv-vector-builtins.h b/gcc/config/riscv/riscv-vector-builtins.h index 6bba4c90c3a..ef91248035c 100644 --- a/gcc/config/riscv/riscv-vector-builtins.h +++ b/gcc/config/riscv/riscv-vector-builtins.h @@ -53,6 +53,9 @@ rtx expand_builtin (unsigned int, tree, rtx); bool check_builtin_call (location_t, vec, unsigned int, tree, unsigned int, tree *); machine_mode vector_builtin_mode (scalar_mode, enum vlmul_field_enum); +bool builtin_type_p (const_tree); +bool verify_type_context (location_t, type_context_kind, const_tree, bool); +const char * mangle_builtin_type (const_tree); } // end namespace riscv_vector diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index b82a38da7c9..8c78e726a19 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -67,6 +67,8 @@ along with GCC; see the file COPYING3. If not see #include "tree-vectorizer.h" #include "tree-ssa-loop-niter.h" #include "rtx-vector-builder.h" +#include "riscv-vector-builtins.h" +#include "riscv-vector.h" /* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF. */ #define UNSPEC_ADDRESS_P(X) \ @@ -5780,6 +5782,124 @@ riscv_asan_shadow_offset (void) return TARGET_64BIT ? (HOST_WIDE_INT_1 << 29) : 0; } +/* Implement TARGET_VECTOR_MODE_SUPPORTED_P. */ + +static bool +riscv_vector_mode_supported_p (machine_mode mode) +{ + if (TARGET_VECTOR && rvv_mode_p (mode)) + return true; + + return false; +} + +/* Implement TARGET_VECTOR_ALIGNMENT. */ + +static HOST_WIDE_INT +riscv_vector_alignment (const_tree type) +{ + /* ??? Checking the mode isn't ideal, but VECTOR_BOOLEAN_TYPE_P can + be set for non-predicate vectors of booleans. Modes are the most + direct way we have of identifying real RVV predicate types. */ + /* FIXME: RVV didn't mention the alignment of bool, we uses + one byte align. */ + if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_VECTOR_BOOL) + return 8; + + widest_int min_size = + constant_lower_bound (wi::to_poly_widest (TYPE_SIZE (type))); + return wi::umin (min_size, 128).to_uhwi (); +} + +/* Implement target hook TARGET_VECTORIZE_PREFERRED_VECTOR_ALIGNMENT. */ + +static poly_uint64 +riscv_vectorize_preferred_vector_alignment (const_tree type) +{ + if (rvv_mode_p (TYPE_MODE (type))) + { + /* If the length of the vector is a fixed power of 2, try to align + to that length, otherwise don't try to align at all. */ + HOST_WIDE_INT result; + + if (!GET_MODE_BITSIZE (TYPE_MODE (type)).is_constant (&result) || + !pow2p_hwi (result)) + result = TYPE_ALIGN (TREE_TYPE (type)); + + return result; + } + + return default_preferred_vector_alignment (type); +} + +/* Implement target hook TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE. */ + +static bool +riscv_simd_vector_alignment_reachable (const_tree type, bool is_packed) +{ + if (is_packed) + return false; + + /* For fixed-length vectors, check that the vectorizer will aim for + full-vector alignment. This isn't true for generic GCC vectors + that are wider than the ABI maximum of 128 bits. */ + poly_uint64 preferred_alignment = + riscv_vectorize_preferred_vector_alignment (type); + if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST && + maybe_ne (wi::to_widest (TYPE_SIZE (type)), preferred_alignment)) + return false; + + /* Vectors whose size is <= BIGGEST_ALIGNMENT are naturally aligned. */ + return true; +} + +/* Return true if the vector misalignment factor is supported by the + target. */ + +static bool +riscv_builtin_support_vector_misalignment (machine_mode mode, const_tree type, + int misalignment, bool is_packed) +{ + return default_builtin_support_vector_misalignment (mode, type, misalignment, + is_packed); +} + +/* Implement TARGET_COMPATIBLE_VECTOR_TYPES_P. */ + +static bool +riscv_compatible_vector_types_p (const_tree type1, const_tree type2) +{ + return (riscv_vector::builtin_type_p (type1) == + riscv_vector::builtin_type_p (type2)); +} + +/* Implement TARGET_VERIFY_TYPE_CONTEXT. */ + +static bool +riscv_verify_type_context (location_t loc, type_context_kind context, + const_tree type, bool silent_p) +{ + return riscv_vector::verify_type_context (loc, context, type, silent_p); +} + +/* Implement TARGET_MANGLE_TYPE. */ + +static const char * +riscv_mangle_type (const_tree type) +{ + /* Mangle all vector type for vector extension. */ + /* The mangle name follows the rule of aarch64 + that is "u" + length of (abi_name) + abi_name. */ + if (TYPE_NAME (type) != NULL) + { + const char *res = riscv_vector::mangle_builtin_type (type); + if (res) + return res; + } + /* Use the default mangling. */ + return NULL; +} + /* Initialize the GCC target structure. */ #undef TARGET_ASM_ALIGNED_HI_OP #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t" @@ -5974,6 +6094,30 @@ riscv_asan_shadow_offset (void) #define TARGET_DEFAULT_TARGET_FLAGS (MASK_BIG_ENDIAN) #endif +#undef TARGET_VECTOR_MODE_SUPPORTED_P +#define TARGET_VECTOR_MODE_SUPPORTED_P riscv_vector_mode_supported_p + +#undef TARGET_VECTOR_ALIGNMENT +#define TARGET_VECTOR_ALIGNMENT riscv_vector_alignment + +#undef TARGET_VECTORIZE_PREFERRED_VECTOR_ALIGNMENT +#define TARGET_VECTORIZE_PREFERRED_VECTOR_ALIGNMENT riscv_vectorize_preferred_vector_alignment + +#undef TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE +#define TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE riscv_simd_vector_alignment_reachable + +#undef TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT +#define TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT riscv_builtin_support_vector_misalignment + +#undef TARGET_COMPATIBLE_VECTOR_TYPES_P +#define TARGET_COMPATIBLE_VECTOR_TYPES_P riscv_compatible_vector_types_p + +#undef TARGET_VERIFY_TYPE_CONTEXT +#define TARGET_VERIFY_TYPE_CONTEXT riscv_verify_type_context + +#undef TARGET_MANGLE_TYPE +#define TARGET_MANGLE_TYPE riscv_mangle_type + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-riscv.h"