From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-ej1-x635.google.com (mail-ej1-x635.google.com [IPv6:2a00:1450:4864:20::635]) by sourceware.org (Postfix) with ESMTPS id 84763385740B for ; Fri, 21 Oct 2022 04:23:25 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 84763385740B Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ej1-x635.google.com with SMTP id bj12so4178638ejb.13 for ; Thu, 20 Oct 2022 21:23:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=7lMdJ7H9EzMLY8UwC0qA8RReAnSYaBbK6AXtUI0hs6A=; b=f5+bQ7CJqI+HkyRh+QjesnISMCbIkmtIlsSJEpJ9p1/cB40FNkfs76aX1J+YE4jwMG T8jniCdL1dc3IBKVNxYKBZ1gsSOS5A4f3nP4XocD7nQky0KfPQh4YVMVmw16HmHbBx9N BN3DhWUZh/MjhFxQ0kyBJ4KLVl+MgfBuKJtjlyDsSy4UFseBMsRvn+vhWD7/OZa08FV6 ljT1PR8a6bgpAMxcIG5K/aSAvGZ2FJfcjD1t7zIb2SXBXJgLfXIOiLxRpboy3OFg6Ao2 YH1MnV+IsZ2e7T9SObnriFHcDNOvfXhgByucRgF94uWSsBtNx2LzBr4qWoJUG+ls+fYv pthw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=7lMdJ7H9EzMLY8UwC0qA8RReAnSYaBbK6AXtUI0hs6A=; b=MeepTZwRnwatlEr/KaDs3iEBBVBZCGUXbJhH00qsXPfxPlS0UHFOMi6ot7B42ke10s TTKcnvY0ULNXZBN85Q1wrAJK5vzueojJmPVWlStMKJ40f02aKeyygInblVRT3PgNQKEl jgaUW5adu3mx7FJLUcYWgCo3sJvYTr2Uc+QO5jEC+KgeLfeUgc64LiAZZrv6gvXkuy9+ 1+1ZYSIpU3FSxB8/nXfazdBaOjCf9m1D25FTSG9yBVFKiYKtJ/v1waoGFaNb4UTMI419 48XWvM/DewSJUTIQKuKQoRighUiNITLFVCr3KmXxQosXMQOaV8CfdfTdJrIF+4ouglVz HQbw== X-Gm-Message-State: ACrzQf1a2TF6Qmj1bYvZB5jjPJnwHIoczA4GrIVEdHasfDLRgDgrMshR Nro+x2lOG3gPJ78afpxJVlc/pCRhDz19h4CTk7Lbv9PY X-Google-Smtp-Source: AMsMyM76dkiE0k6GhZ/4fhh7hzr4N/ZrzBje+SJPHauo/akBi7q4+iQd4zW/FJ80N8dzM7mAfOizKkFnlOL41IZGHoA= X-Received: by 2002:a17:907:6e93:b0:78d:dff1:71e3 with SMTP id sh19-20020a1709076e9300b0078ddff171e3mr13087893ejc.94.1666326203252; Thu, 20 Oct 2022 21:23:23 -0700 (PDT) MIME-Version: 1.0 References: <20221017082043.114653-1-juzhe.zhong@rivai.ai> In-Reply-To: <20221017082043.114653-1-juzhe.zhong@rivai.ai> From: Kito Cheng Date: Fri, 21 Oct 2022 12:23:10 +0800 Message-ID: Subject: Re: [PATCH] RISC-V: Add RVV intrinsic basic framework. To: juzhe.zhong@rivai.ai Cc: gcc-patches@gcc.gnu.org Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-8.5 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,GIT_PATCH_0,KAM_SHORT,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP 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: Verified, committed to trunk. On Mon, Oct 17, 2022 at 4:21 PM wrote: > > From: Ju-Zhe Zhong > > gcc/ChangeLog: > > * config.gcc: Add gt files since function_instance is GTY ((user)). > * config/riscv/riscv-builtins.cc (riscv_init_builtins): Add RVV intrinsic framework. > (riscv_builtin_decl): Ditto. > (riscv_expand_builtin): Ditto. > * config/riscv/riscv-protos.h (builtin_decl): New function. > (expand_builtin): Ditto. > (enum riscv_builtin_class): New enum to classify RVV intrinsic and RISC-V general built-in. > * config/riscv/riscv-vector-builtins.cc (class GTY): New declaration. > (struct registered_function_hasher): New struct. > (DEF_RVV_OP_TYPE): New macro. > (DEF_RVV_TYPE): Ditto. > (DEF_RVV_PRED_TYPE): Ditto. > (GTY): New declaration. > (add_attribute): New function. > (check_required_extensions): Ditto. > (rvv_arg_type_info::get_tree_type): Ditto. > (function_instance::function_instance): Ditto. > (function_instance::operator==): Ditto. > (function_instance::any_type_float_p): Ditto. > (function_instance::get_return_type): Ditto. > (function_instance::get_arg_type): Ditto. > (function_instance::hash): Ditto. > (function_instance::call_properties): Ditto. > (function_instance::reads_global_state_p): Ditto. > (function_instance::modifies_global_state_p): Ditto. > (function_instance::could_trap_p): Ditto. > (function_builder::function_builder): Ditto. > (function_builder::~function_builder): Ditto. > (function_builder::allocate_argument_types): Ditto. > (function_builder::register_function_group): Ditto. > (function_builder::append_name): Ditto. > (function_builder::finish_name): Ditto. > (function_builder::get_attributes): Ditto. > (function_builder::add_function): Ditto. > (function_builder::add_unique_function): Ditto. > (function_call_info::function_call_info): Ditto. > (function_expander::function_expander): Ditto. > (function_expander::add_input_operand): Ditto. > (function_expander::generate_insn): Ditto. > (registered_function_hasher::hash): Ditto. > (registered_function_hasher::equal): Ditto. > (builtin_decl): Ditto. > (expand_builtin): Ditto. > (gt_ggc_mx): Define for using GCC garbage collect. > (gt_pch_nx): Define for using GCC garbage collect. > * config/riscv/riscv-vector-builtins.def (DEF_RVV_OP_TYPE): New macro. > (DEF_RVV_PRED_TYPE): Ditto. > (vbool64_t): Add suffix. > (vbool32_t): Ditto. > (vbool16_t): Ditto. > (vbool8_t): Ditto. > (vbool4_t): Ditto. > (vbool2_t): Ditto. > (vbool1_t): Ditto. > (vint8mf8_t): Ditto. > (vuint8mf8_t): Ditto. > (vint8mf4_t): Ditto. > (vuint8mf4_t): Ditto. > (vint8mf2_t): Ditto. > (vuint8mf2_t): Ditto. > (vint8m1_t): Ditto. > (vuint8m1_t): Ditto. > (vint8m2_t): Ditto. > (vuint8m2_t): Ditto. > (vint8m4_t): Ditto. > (vuint8m4_t): Ditto. > (vint8m8_t): Ditto. > (vuint8m8_t): Ditto. > (vint16mf4_t): Ditto. > (vuint16mf4_t): Ditto. > (vint16mf2_t): Ditto. > (vuint16mf2_t): Ditto. > (vint16m1_t): Ditto. > (vuint16m1_t): Ditto. > (vint16m2_t): Ditto. > (vuint16m2_t): Ditto. > (vint16m4_t): Ditto. > (vuint16m4_t): Ditto. > (vint16m8_t): Ditto. > (vuint16m8_t): Ditto. > (vint32mf2_t): Ditto. > (vuint32mf2_t): Ditto. > (vint32m1_t): Ditto. > (vuint32m1_t): Ditto. > (vint32m2_t): Ditto. > (vuint32m2_t): Ditto. > (vint32m4_t): Ditto. > (vuint32m4_t): Ditto. > (vint32m8_t): Ditto. > (vuint32m8_t): Ditto. > (vint64m1_t): Ditto. > (vuint64m1_t): Ditto. > (vint64m2_t): Ditto. > (vuint64m2_t): Ditto. > (vint64m4_t): Ditto. > (vuint64m4_t): Ditto. > (vint64m8_t): Ditto. > (vuint64m8_t): Ditto. > (vfloat32mf2_t): Ditto. > (vfloat32m1_t): Ditto. > (vfloat32m2_t): Ditto. > (vfloat32m4_t): Ditto. > (vfloat32m8_t): Ditto. > (vfloat64m1_t): Ditto. > (vfloat64m2_t): Ditto. > (vfloat64m4_t): Ditto. > (vfloat64m8_t): Ditto. > (vv): Ditto. > (vx): Ditto. > (v): Ditto. > (wv): Ditto. > (wx): Ditto. > (x_x_v): Ditto. > (vf2): Ditto. > (vf4): Ditto. > (vf8): Ditto. > (vvm): Ditto. > (vxm): Ditto. > (x_x_w): Ditto. > (v_v): Ditto. > (v_x): Ditto. > (vs): Ditto. > (mm): Ditto. > (m): Ditto. > (vf): Ditto. > (vm): Ditto. > (wf): Ditto. > (vfm): Ditto. > (v_f): Ditto. > (ta): Ditto. > (tu): Ditto. > (ma): Ditto. > (mu): Ditto. > (tama): Ditto. > (tamu): Ditto. > (tuma): Ditto. > (tumu): Ditto. > (tam): Ditto. > (tum): Ditto. > * config/riscv/riscv-vector-builtins.h (GCC_RISCV_VECTOR_BUILTINS_H): New macro. > (RVV_REQUIRE_RV64BIT): Ditto. > (RVV_REQUIRE_ZVE64): Ditto. > (RVV_REQUIRE_ELEN_FP_32): Ditto. > (RVV_REQUIRE_ELEN_FP_64): Ditto. > (enum operand_type_index): New enum. > (DEF_RVV_OP_TYPE): New macro. > (enum predication_type_index): New enum. > (DEF_RVV_PRED_TYPE): New macro. > (enum rvv_base_type): New enum. > (struct rvv_builtin_suffixes): New struct. > (struct rvv_arg_type_info): Ditto. > (struct rvv_type_info): Ditto. > (struct rvv_op_info): Ditto. > (class registered_function): New class. > (class function_base): Ditto. > (class function_shape): Ditto. > (struct function_group_info): New struct. > (class GTY): New class. > (class function_builder): Ditto. > (class function_call_info): Ditto. > (function_call_info::function_returns_void_p): New function. > (class function_expander): New class. > (function_instance::operator!=): New function. > (function_expander::expand): Ditto. > (function_expander::add_input_operand): Ditto. > (function_base::call_properties): Ditto. > > --- > gcc/config.gcc | 2 + > gcc/config/riscv/riscv-builtins.cc | 44 +- > gcc/config/riscv/riscv-protos.h | 17 + > gcc/config/riscv/riscv-vector-builtins.cc | 475 ++++++++++++++++++++- > gcc/config/riscv/riscv-vector-builtins.def | 245 ++++++++--- > gcc/config/riscv/riscv-vector-builtins.h | 363 ++++++++++++++++ > 6 files changed, 1065 insertions(+), 81 deletions(-) > > diff --git a/gcc/config.gcc b/gcc/config.gcc > index 8d5972fecf7..486e8790544 100644 > --- a/gcc/config.gcc > +++ b/gcc/config.gcc > @@ -519,6 +519,8 @@ riscv*) > extra_objs="${extra_objs} riscv-vector-builtins.o" > d_target_objs="riscv-d.o" > extra_headers="riscv_vector.h" > + target_gtfiles="$target_gtfiles \$(srcdir)/config/riscv/riscv-vector-builtins.cc" > + target_gtfiles="$target_gtfiles \$(srcdir)/config/riscv/riscv-vector-builtins.h" > ;; > rs6000*-*-*) > extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt" > diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc > index 14865d70955..9930340d32b 100644 > --- a/gcc/config/riscv/riscv-builtins.cc > +++ b/gcc/config/riscv/riscv-builtins.cc > @@ -223,7 +223,10 @@ riscv_init_builtins (void) > { > tree type = riscv_build_function_type (d->prototype); > riscv_builtin_decls[i] > - = add_builtin_function (d->name, type, i, BUILT_IN_MD, NULL, NULL); > + = add_builtin_function (d->name, type, > + (i << RISCV_BUILTIN_SHIFT) > + + RISCV_BUILTIN_GENERAL, > + BUILT_IN_MD, NULL, NULL); > riscv_builtin_decl_index[d->icode] = i; > } > } > @@ -234,9 +237,18 @@ riscv_init_builtins (void) > tree > riscv_builtin_decl (unsigned int code, bool initialize_p ATTRIBUTE_UNUSED) > { > - if (code >= ARRAY_SIZE (riscv_builtins)) > - return error_mark_node; > - return riscv_builtin_decls[code]; > + unsigned int subcode = code >> RISCV_BUILTIN_SHIFT; > + switch (code & RISCV_BUILTIN_CLASS) > + { > + case RISCV_BUILTIN_GENERAL: > + if (subcode >= ARRAY_SIZE (riscv_builtins)) > + return error_mark_node; > + return riscv_builtin_decls[subcode]; > + > + case RISCV_BUILTIN_VECTOR: > + return riscv_vector::builtin_decl (subcode, initialize_p); > + } > + return error_mark_node; > } > > /* Take argument ARGNO from EXP's argument list and convert it into > @@ -303,15 +315,23 @@ riscv_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, > { > tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); > unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl); > - const struct riscv_builtin_description *d = &riscv_builtins[fcode]; > - > - switch (d->builtin_type) > + unsigned int subcode = fcode >> RISCV_BUILTIN_SHIFT; > + switch (fcode & RISCV_BUILTIN_CLASS) > { > - case RISCV_BUILTIN_DIRECT: > - return riscv_expand_builtin_direct (d->icode, target, exp, true); > - > - case RISCV_BUILTIN_DIRECT_NO_TARGET: > - return riscv_expand_builtin_direct (d->icode, target, exp, false); > + case RISCV_BUILTIN_VECTOR: > + return riscv_vector::expand_builtin (subcode, exp, target); > + case RISCV_BUILTIN_GENERAL: { > + const struct riscv_builtin_description *d = &riscv_builtins[subcode]; > + > + switch (d->builtin_type) > + { > + case RISCV_BUILTIN_DIRECT: > + return riscv_expand_builtin_direct (d->icode, target, exp, true); > + > + case RISCV_BUILTIN_DIRECT_NO_TARGET: > + return riscv_expand_builtin_direct (d->icode, target, exp, false); > + } > + } > } > > gcc_unreachable (); > diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h > index a44b34d1278..f8c9932ff89 100644 > --- a/gcc/config/riscv/riscv-protos.h > +++ b/gcc/config/riscv/riscv-protos.h > @@ -124,6 +124,23 @@ extern const char *mangle_builtin_type (const_tree); > extern bool verify_type_context (location_t, type_context_kind, const_tree, bool); > #endif > extern void handle_pragma_vector (void); > +extern tree builtin_decl (unsigned, bool); > +extern rtx expand_builtin (unsigned int, tree, rtx); > } > > +/* We classify builtin types into two classes: > + 1. General builtin class which is defined in riscv_builtins. > + 2. Vector builtin class which is a special builtin architecture > + that implement intrinsic short into "pragma". */ > +enum riscv_builtin_class > +{ > + RISCV_BUILTIN_GENERAL, > + RISCV_BUILTIN_VECTOR > +}; > + > +const unsigned int RISCV_BUILTIN_SHIFT = 1; > + > +/* Mask that selects the riscv_builtin_class part of a function code. */ > +const unsigned int RISCV_BUILTIN_CLASS = (1 << RISCV_BUILTIN_SHIFT) - 1; > + > #endif /* ! GCC_RISCV_PROTOS_H */ > diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc > index 55d45651618..5c20788b3ab 100644 > --- a/gcc/config/riscv/riscv-vector-builtins.cc > +++ b/gcc/config/riscv/riscv-vector-builtins.cc > @@ -66,13 +66,55 @@ struct vector_type_info > const char *mangled_name; > }; > > -/* Information about each RVV type. */ > +/* Describes a function decl. */ > +class GTY (()) registered_function > +{ > +public: > + function_instance GTY ((skip)) instance; > + > + /* The decl itself. */ > + tree GTY ((skip)) decl; > +}; > + > +/* Hash traits for registered_function. */ > +struct registered_function_hasher : nofree_ptr_hash > +{ > + typedef function_instance compare_type; > + > + static hashval_t hash (value_type); > + static bool equal (value_type, const compare_type &); > +}; > + > +/* Static information about each RVV type. */ > static CONSTEXPR const vector_type_info vector_types[] = { > #define DEF_RVV_TYPE(NAME, NCHARS, ABI_NAME, ARGS...) \ > {#NAME, #ABI_NAME, "u" #NCHARS #ABI_NAME}, > #include "riscv-vector-builtins.def" > }; > > +/* Static information about operand suffix for each RVV type. */ > +const char *const operand_suffixes[NUM_OP_TYPES] = { > + "", /* OP_TYPE_none. */ > +#define DEF_RVV_OP_TYPE(NAME) "_" # NAME, > +#include "riscv-vector-builtins.def" > +}; > + > +/* Static information about type suffix for each RVV type. */ > +const rvv_builtin_suffixes type_suffixes[NUM_VECTOR_TYPES + 1] = { > +#define DEF_RVV_TYPE(NAME, NCHARS, ABI_NAME, SCALAR_TYPE, VECTOR_MODE, \ > + VECTOR_MODE_MIN_VLEN_32, VECTOR_SUFFIX, SCALAR_SUFFIX, \ > + VSETVL_SUFFIX) \ > + {#VECTOR_SUFFIX, #SCALAR_SUFFIX, #VSETVL_SUFFIX}, > +#include "riscv-vector-builtins.def" > +}; > + > +/* Static information about predication suffix for each RVV type. */ > +const char *const predication_suffixes[NUM_PRED_TYPES] = { > + "", /* PRED_TYPE_none. */ > +#define DEF_RVV_PRED_TYPE(NAME) "_" # NAME, > +#include "riscv-vector-builtins.def" > +}; > + > /* The RVV types, with their built-in > "__rvv..._t" name. Allow an index of NUM_VECTOR_TYPES, which always > yields a null tree. */ > @@ -82,6 +124,14 @@ static GTY (()) tree abi_vector_types[NUM_VECTOR_TYPES + 1]; > extern GTY (()) rvv_builtin_types_t builtin_types[NUM_VECTOR_TYPES + 1]; > rvv_builtin_types_t builtin_types[NUM_VECTOR_TYPES + 1]; > > +/* The list of all registered function decls, indexed by code. */ > +static GTY (()) vec *registered_functions; > + > +/* All registered function decls, hashed on the function_instance > + that they implement. This is used for looking up implementations of > + overloaded functions. */ > +static hash_table *function_table; > + > /* RAII class for enabling enough RVV features to define the built-in > types and implement the riscv_vector.h pragma. > > @@ -118,6 +168,13 @@ rvv_switcher::~rvv_switcher () > sizeof (have_regs_of_mode)); > } > > +/* Add attribute NAME to ATTRS. */ > +static tree > +add_attribute (const char *name, tree attrs) > +{ > + return tree_cons (get_identifier (name), NULL_TREE, attrs); > +} > + > /* Add type attributes to builtin type tree, currently only the mangled name. */ > static void > add_vector_type_attribute (tree type, const char *mangled_name) > @@ -215,6 +272,7 @@ static void > register_vector_type (vector_type_index type) > { > tree vectype = abi_vector_types[type]; > + > /* When vectype is NULL, the corresponding builtin type > is disabled according to '-march'. */ > if (!vectype) > @@ -237,6 +295,386 @@ register_vector_type (vector_type_index type) > builtin_types[type].vector_ptr = build_pointer_type (vectype); > } > > +/* Check whether all the RVV_REQUIRE_* values in REQUIRED_EXTENSIONS are > + enabled. */ > +static bool > +check_required_extensions (uint64_t required_extensions) > +{ > + uint64_t riscv_isa_flags = 0; > + > + if (TARGET_VECTOR_ELEN_FP_32) > + riscv_isa_flags |= RVV_REQUIRE_ELEN_FP_32; > + if (TARGET_VECTOR_ELEN_FP_64) > + riscv_isa_flags |= RVV_REQUIRE_ELEN_FP_64; > + if (TARGET_MIN_VLEN > 32) > + riscv_isa_flags |= RVV_REQUIRE_ZVE64; > + if (TARGET_64BIT) > + riscv_isa_flags |= RVV_REQUIRE_RV64BIT; > + > + uint64_t missing_extensions = required_extensions & ~riscv_isa_flags; > + if (missing_extensions != 0) > + return false; > + return true; > +} > + > +tree > +rvv_arg_type_info::get_tree_type (vector_type_index type_idx) const > +{ > + switch (base_type) > + { > + case RVV_BASE_vector: > + return builtin_types[type_idx].vector; > + case RVV_BASE_scalar: > + return builtin_types[type_idx].scalar; > + case RVV_BASE_vector_ptr: > + return builtin_types[type_idx].vector_ptr; > + case RVV_BASE_scalar_ptr: > + return builtin_types[type_idx].scalar_ptr; > + case RVV_BASE_scalar_const_ptr: > + return builtin_types[type_idx].scalar_const_ptr; > + case RVV_BASE_void: > + return void_type_node; > + case RVV_BASE_size: > + return size_type_node; > + case RVV_BASE_ptrdiff: > + return ptrdiff_type_node; > + case RVV_BASE_unsigned_long: > + return long_unsigned_type_node; > + case RVV_BASE_long: > + return long_integer_type_node; > + default: > + gcc_unreachable (); > + } > +} > + > +function_instance::function_instance (const char *base_name_in, > + const function_base *base_in, > + const function_shape *shape_in, > + rvv_type_info type_in, > + predication_type_index pred_in, > + const rvv_op_info *op_info_in) > + : base_name (base_name_in), base (base_in), shape (shape_in), type (type_in), > + pred (pred_in), op_info (op_info_in) > +{ > +} > + > +bool > +function_instance::operator== (const function_instance &other) const > +{ > + for (unsigned int i = 0; op_info->args[i].base_type != NUM_BASE_TYPES; ++i) > + if (op_info->args[i].base_type != other.op_info->args[i].base_type) > + return false; > + return (base == other.base && shape == other.shape > + && type.index == other.type.index && op_info->op == other.op_info->op > + && pred == other.pred > + && op_info->ret.base_type == other.op_info->ret.base_type); > +} > + > +bool > +function_instance::any_type_float_p () const > +{ > + if (FLOAT_MODE_P (TYPE_MODE (get_return_type ()))) > + return true; > + > + for (int i = 0; op_info->args[i].base_type != NUM_BASE_TYPES; ++i) > + if (FLOAT_MODE_P (TYPE_MODE (get_arg_type (i)))) > + return true; > + > + return false; > +} > + > +tree > +function_instance::get_return_type () const > +{ > + return op_info->ret.get_tree_type (type.index); > +} > + > +tree > +function_instance::get_arg_type (unsigned opno) const > +{ > + return op_info->args[opno].get_tree_type (type.index); > +} > + > +/* Return a hash code for a function_instance. */ > +hashval_t > +function_instance::hash () const > +{ > + inchash::hash h; > + /* BASE uniquely determines BASE_NAME, so we don't need to hash both. */ > + h.add_ptr (base); > + h.add_ptr (shape); > + h.add_int (type.index); > + h.add_int (op_info->op); > + h.add_int (pred); > + h.add_int (op_info->ret.base_type); > + for (unsigned int i = 0; op_info->args[i].base_type != NUM_BASE_TYPES; ++i) > + h.add_int (op_info->args[i].base_type); > + return h.end (); > +} > + > +/* Return a set of CP_* flags that describe what the function could do, > + taking the command-line flags into account. */ > +unsigned int > +function_instance::call_properties () const > +{ > + unsigned int flags = base->call_properties (*this); > + > + /* -fno-trapping-math means that we can assume any FP exceptions > + are not user-visible. */ > + if (!flag_trapping_math) > + flags &= ~CP_RAISE_FP_EXCEPTIONS; > + > + return flags; > +} > + > +/* Return true if calls to the function could read some form of > + global state. */ > +bool > +function_instance::reads_global_state_p () const > +{ > + unsigned int flags = call_properties (); > + > + /* Preserve any dependence on rounding mode, flush to zero mode, etc. > + There is currently no way of turning this off; in particular, > + -fno-rounding-math (which is the default) means that we should make > + the usual assumptions about rounding mode, which for intrinsics means > + acting as the instructions do. */ > + if (flags & CP_READ_FPCR) > + return true; > + > + /* Handle direct reads of global state. */ > + return flags & (CP_READ_MEMORY | CP_READ_CSR); > +} > + > +/* Return true if calls to the function could modify some form of > + global state. */ > +bool > +function_instance::modifies_global_state_p () const > +{ > + unsigned int flags = call_properties (); > + > + /* Preserve any exception state written back to the FPCR, > + unless -fno-trapping-math says this is unnecessary. */ > + if (flags & CP_RAISE_FP_EXCEPTIONS) > + return true; > + > + /* Handle direct modifications of global state. */ > + return flags & (CP_WRITE_MEMORY | CP_WRITE_CSR); > +} > + > +/* Return true if calls to the function could raise a signal. */ > +bool > +function_instance::could_trap_p () const > +{ > + unsigned int flags = call_properties (); > + > + /* Handle functions that could raise SIGFPE. */ > + if (flags & CP_RAISE_FP_EXCEPTIONS) > + return true; > + > + /* Handle functions that could raise SIGBUS or SIGSEGV. */ > + if (flags & (CP_READ_MEMORY | CP_WRITE_MEMORY)) > + return true; > + > + return false; > +} > + > +function_builder::function_builder () > +{ > + m_direct_overloads = lang_GNU_CXX (); > + gcc_obstack_init (&m_string_obstack); > +} > + > +function_builder::~function_builder () > +{ > + obstack_free (&m_string_obstack, NULL); > +} > + > +/* Allocate arguments of the function. */ > +void > +function_builder::allocate_argument_types (const function_instance &instance, > + vec &argument_types) const > +{ > + for (unsigned int i = 0; > + instance.op_info->args[i].base_type != NUM_BASE_TYPES; ++i) > + argument_types.quick_push ( > + instance.op_info->args[i].get_tree_type (instance.type.index)); > +} > + > +/* Register all the functions in GROUP. */ > +void > +function_builder::register_function_group (const function_group_info &group) > +{ > + (*group.shape)->build (*this, group); > +} > + > +/* Add NAME to the end of the function name being built. */ > +void > +function_builder::append_name (const char *name) > +{ > + obstack_grow (&m_string_obstack, name, strlen (name)); > +} > + > +/* Zero-terminate and complete the function name being built. */ > +char * > +function_builder::finish_name () > +{ > + obstack_1grow (&m_string_obstack, 0); > + return (char *) obstack_finish (&m_string_obstack); > +} > + > +/* Return the appropriate function attributes for INSTANCE. */ > +tree > +function_builder::get_attributes (const function_instance &instance) > +{ > + tree attrs = NULL_TREE; > + > + if (!instance.modifies_global_state_p ()) > + { > + if (instance.reads_global_state_p ()) > + attrs = add_attribute ("pure", attrs); > + else > + attrs = add_attribute ("const", attrs); > + } > + > + if (!flag_non_call_exceptions || !instance.could_trap_p ()) > + attrs = add_attribute ("nothrow", attrs); > + > + return add_attribute ("leaf", attrs); > +} > + > +/* Add a function called NAME with type FNTYPE and attributes ATTRS. > + INSTANCE describes what the function does. */ > +registered_function & > +function_builder::add_function (const function_instance &instance, > + const char *name, tree fntype, tree attrs, > + bool placeholder_p) > +{ > + unsigned int code = vec_safe_length (registered_functions); > + code = (code << RISCV_BUILTIN_SHIFT) + RISCV_BUILTIN_VECTOR; > + > + /* We need to be able to generate placeholders to enusre that we have a > + consistent numbering scheme for function codes between the C and C++ > + frontends, so that everything ties up in LTO. > + > + Currently, tree-streamer-in.c:unpack_ts_function_decl_value_fields > + validates that tree nodes returned by TARGET_BUILTIN_DECL are non-NULL and > + some node other than error_mark_node. This is a holdover from when builtin > + decls were streamed by code rather than by value. > + > + Ultimately, we should be able to remove this validation of BUILT_IN_MD > + nodes and remove the target hook. For now, however, we need to appease the > + validation and return a non-NULL, non-error_mark_node node, so we > + arbitrarily choose integer_zero_node. */ > + tree decl = placeholder_p > + ? integer_zero_node > + : simulate_builtin_function_decl (input_location, name, fntype, > + code, NULL, attrs); > + > + registered_function &rfn = *ggc_alloc (); > + rfn.instance = instance; > + rfn.decl = decl; > + vec_safe_push (registered_functions, &rfn); > + > + return rfn; > +} > + > +/* Add a built-in function for INSTANCE, with the argument types given > + by ARGUMENT_TYPES and the return type given by RETURN_TYPE. NAME is > + the "full" name for C function. OVERLOAD_NAME is the "short" name for > + C++ overloaded function. OVERLOAD_NAME can be nullptr because some > + instance doesn't have C++ overloaded function. */ > +void > +function_builder::add_unique_function (const function_instance &instance, > + const function_shape *shape, > + tree return_type, > + vec &argument_types) > +{ > + /* Do not add this function if it is invalid. */ > + if (!check_required_extensions (instance.type.required_extensions)) > + return; > + > + /* Add the function under its full (unique) name. */ > + char *name = shape->get_name (*this, instance, false); > + tree fntype > + = build_function_type_array (return_type, argument_types.length (), > + argument_types.address ()); > + tree attrs = get_attributes (instance); > + registered_function &rfn > + = add_function (instance, name, fntype, attrs, false); > + > + /* Enter the function into the hash table. */ > + hashval_t hash = instance.hash (); > + registered_function **rfn_slot > + = function_table->find_slot_with_hash (instance, hash, INSERT); > + gcc_assert (!*rfn_slot); > + *rfn_slot = &rfn; > + > + /* Also add the function under its overloaded alias, if we want > + a separate decl for each instance of an overloaded function. */ > + char *overload_name = shape->get_name (*this, instance, true); > + if (overload_name) > + { > + /* Attribute lists shouldn't be shared. */ > + tree attrs = get_attributes (instance); > + bool placeholder_p = !m_direct_overloads; > + add_function (instance, overload_name, fntype, attrs, placeholder_p); > + } > + obstack_free (&m_string_obstack, name); > +} > + > +function_call_info::function_call_info (location_t location_in, > + const function_instance &instance_in, > + tree fndecl_in) > + : function_instance (instance_in), location (location_in), fndecl (fndecl_in) > +{} > + > +function_expander::function_expander (const function_instance &instance, > + tree fndecl_in, tree exp_in, > + rtx target_in) > + : function_call_info (EXPR_LOCATION (exp_in), instance, fndecl_in), > + exp (exp_in), target (target_in), opno (0) > +{ > + if (!function_returns_void_p ()) > + create_output_operand (&m_ops[opno++], target, TYPE_MODE (TREE_TYPE (exp))); > +} > + > +/* Take argument ARGNO from EXP's argument list and convert it into > + an expand operand. Store the operand in *M_OPS. */ > +void > +function_expander::add_input_operand (unsigned argno) > +{ > + tree arg = CALL_EXPR_ARG (exp, argno); > + rtx x = expand_normal (arg); > + add_input_operand (TYPE_MODE (TREE_TYPE (arg)), x); > +} > + > +/* Generate instruction ICODE, given that its operands have already > + been added to M_OPS. Return the value of the first operand. */ > +rtx > +function_expander::generate_insn (insn_code icode) > +{ > + gcc_assert (opno == insn_data[icode].n_generator_args); > + if (!maybe_expand_insn (icode, opno, m_ops)) > + { > + error ("invalid argument to built-in function"); > + return NULL_RTX; > + } > + return function_returns_void_p () ? const0_rtx : m_ops[0].value; > +} > + > +inline hashval_t > +registered_function_hasher::hash (value_type value) > +{ > + return value->instance.hash (); > +} > + > +inline bool > +registered_function_hasher::equal (value_type value, const compare_type &key) > +{ > + return value->instance == key; > +} > + > /* If TYPE is a built-in type defined by the RVV ABI, return the mangled name, > otherwise return NULL. */ > const char * > @@ -356,4 +794,39 @@ handle_pragma_vector () > register_vector_type ((enum vector_type_index) type_i); > } > > +/* Return the function decl with RVV function subcode CODE, or error_mark_node > + if no such function exists. */ > +tree > +builtin_decl (unsigned int code, bool) > +{ > + if (code >= vec_safe_length (registered_functions)) > + return error_mark_node; > + > + return (*registered_functions)[code]->decl; > +} > + > +/* Expand a call to the RVV function with subcode CODE. EXP is the call > + expression and TARGET is the preferred location for the result. > + Return the value of the lhs. */ > +rtx > +expand_builtin (unsigned int code, tree exp, rtx target) > +{ > + registered_function &rfn = *(*registered_functions)[code]; > + return function_expander (rfn.instance, rfn.decl, exp, target).expand (); > +} > + > } // end namespace riscv_vector > + > +inline void > +gt_ggc_mx (function_instance *) > +{} > + > +inline void > +gt_pch_nx (function_instance *) > +{} > + > +inline void > +gt_pch_nx (function_instance *, gt_pointer_operator, void *) > +{} > + > +#include "gt-riscv-vector-builtins.h" > diff --git a/gcc/config/riscv/riscv-vector-builtins.def b/gcc/config/riscv/riscv-vector-builtins.def > index 83603fedd57..b7a633ed376 100644 > --- a/gcc/config/riscv/riscv-vector-builtins.def > +++ b/gcc/config/riscv/riscv-vector-builtins.def > @@ -19,181 +19,290 @@ along with GCC; see the file COPYING3. If not see > . */ > > /* Use "DEF_RVV_TYPE" macro to define RVV datatype builtins. > - 1.The 1 argument is the name exposed to users. > + 1.The 'NAME' argument is the name exposed to users. > For example, "vint32m1_t". > - 2.The 2 argument is the length of ABI-name. > + 2.The 'NCHARS' argument is the length of ABI-name. > For example, length of "__rvv_int32m1_t" is 15. > - 3.The 3 argument is the ABI-name. For example, "__rvv_int32m1_t". > - 4.The 4 argument is associated scalar type which is used in > + 3.The 'ABI_NAME' argument is the ABI-name. For example, "__rvv_int32m1_t". > + 4.The 'SCALAR_TYPE' argument is associated scalar type which is used in > "build_vector_type_for_mode". For "vint32m1_t", we use "intSI_type_node" in > RV64. Otherwise, we use "long_integer_type_node". > - 5.The 5 and 6 argument are the machine modes of corresponding RVV type used > - in "build_vector_type_for_mode". For "vint32m1_t", we use VNx2SImode when > - TARGET_MIN_VLEN > 32. Otherwise the machine mode is VNx1SImode. */ > + 5.The 'VECTOR_MODE' is the machine modes of corresponding RVV type used > + in "build_vector_type_for_mode" when TARGET_MIN_VLEN > 32. > + For example: VECTOR_MODE = VNx2SI for "vint32m1_t". > + 6.The 'VECTOR_MODE_MIN_VLEN_32' is the machine modes of corresponding RVV > + type used in "build_vector_type_for_mode" when TARGET_MIN_VLEN = 32. For > + example: VECTOR_MODE_MIN_VLEN_32 = VNx1SI for "vint32m1_t". > + 7.The 'VECTOR_SUFFIX' define mode suffix for vector type. > + For example: type_suffixes[VECTOR_TYPE_vin32m1_t].vector = i32m1. > + 8.The 'SCALAR_SUFFIX' define mode suffix for scalar type. > + For example: type_suffixes[VECTOR_TYPE_vin32m1_t].scalar = i32. > + 9.The 'VSETVL_SUFFIX' define mode suffix for vsetvli instruction. > + For example: type_suffixes[VECTOR_TYPE_vin32m1_t].vsetvl = e32m1. > +*/ > > #ifndef DEF_RVV_TYPE > #define DEF_RVV_TYPE(NAME, NCHARS, ABI_NAME, SCALAR_TYPE, VECTOR_MODE, \ > - VECTOR_MODE_MIN_VLEN_32) > + VECTOR_MODE_MIN_VLEN_32, VECTOR_SUFFIX, SCALAR_SUFFIX, \ > + VSETVL_SUFFIX) > +#endif > + > +/* Use "DEF_RVV_OP_TYPE" macro to define RVV operand types. > + The 'NAME' will be concatenated into intrinsic function name. */ > +#ifndef DEF_RVV_OP_TYPE > +#define DEF_RVV_OP_TYPE(NAME) > +#endif > + > +/* Use "DEF_RVV_PRED_TYPE" macro to define RVV predication types. > + The 'NAME' will be concatenated into intrinsic function name. */ > +#ifndef DEF_RVV_PRED_TYPE > +#define DEF_RVV_PRED_TYPE(NAME) > #endif > > /* SEW/LMUL = 64: > Only enable when TARGET_MIN_VLEN > 32 and machine mode = VNx1BImode. */ > -DEF_RVV_TYPE (vbool64_t, 14, __rvv_bool64_t, boolean, VNx1BI, VOID) > +DEF_RVV_TYPE (vbool64_t, 14, __rvv_bool64_t, boolean, VNx1BI, VOID, _b64, , ) > /* SEW/LMUL = 32: > Machine mode = VNx2BImode when TARGET_MIN_VLEN > 32. > Machine mode = VNx1BImode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vbool32_t, 14, __rvv_bool32_t, boolean, VNx2BI, VNx1BI) > +DEF_RVV_TYPE (vbool32_t, 14, __rvv_bool32_t, boolean, VNx2BI, VNx1BI, _b32, , ) > /* SEW/LMUL = 16: > Machine mode = VNx2BImode when TARGET_MIN_VLEN = 32. > Machine mode = VNx4BImode when TARGET_MIN_VLEN > 32. */ > -DEF_RVV_TYPE (vbool16_t, 14, __rvv_bool16_t, boolean, VNx4BI, VNx2BI) > +DEF_RVV_TYPE (vbool16_t, 14, __rvv_bool16_t, boolean, VNx4BI, VNx2BI, _b16, , ) > /* SEW/LMUL = 8: > Machine mode = VNx8BImode when TARGET_MIN_VLEN > 32. > Machine mode = VNx4BImode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vbool8_t, 13, __rvv_bool8_t, boolean, VNx8BI, VNx4BI) > +DEF_RVV_TYPE (vbool8_t, 13, __rvv_bool8_t, boolean, VNx8BI, VNx4BI, _b8, , ) > /* SEW/LMUL = 4: > Machine mode = VNx16BImode when TARGET_MIN_VLEN > 32. > Machine mode = VNx8BImode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vbool4_t, 13, __rvv_bool4_t, boolean, VNx16BI, VNx8BI) > +DEF_RVV_TYPE (vbool4_t, 13, __rvv_bool4_t, boolean, VNx16BI, VNx8BI, _b4, , ) > /* SEW/LMUL = 2: > Machine mode = VNx32BImode when TARGET_MIN_VLEN > 32. > Machine mode = VNx16BImode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vbool2_t, 13, __rvv_bool2_t, boolean, VNx32BI, VNx16BI) > +DEF_RVV_TYPE (vbool2_t, 13, __rvv_bool2_t, boolean, VNx32BI, VNx16BI, _b2, , ) > /* SEW/LMUL = 1: > Machine mode = VNx64BImode when TARGET_MIN_VLEN > 32. > Machine mode = VNx32BImode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vbool1_t, 13, __rvv_bool1_t, boolean, VNx64BI, VNx32BI) > +DEF_RVV_TYPE (vbool1_t, 13, __rvv_bool1_t, boolean, VNx64BI, VNx32BI, _b1, , ) > > /* LMUL = 1/8: > Only enble when TARGET_MIN_VLEN > 32 and machine mode = VNx1QImode. */ > -DEF_RVV_TYPE (vint8mf8_t, 15, __rvv_int8mf8_t, intQI, VNx1QI, VOID) > -DEF_RVV_TYPE (vuint8mf8_t, 16, __rvv_uint8mf8_t, unsigned_intQI, VNx1QI, VOID) > +DEF_RVV_TYPE (vint8mf8_t, 15, __rvv_int8mf8_t, intQI, VNx1QI, VOID, _i8mf8, _i8, > + _e8mf8) > +DEF_RVV_TYPE (vuint8mf8_t, 16, __rvv_uint8mf8_t, unsigned_intQI, VNx1QI, VOID, > + _u8mf8, _u8, _e8mf8) > /* LMUL = 1/4: > Machine mode = VNx2QImode when TARGET_MIN_VLEN > 32. > Machine mode = VNx1QImode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vint8mf4_t, 15, __rvv_int8mf4_t, intQI, VNx2QI, VNx1QI) > -DEF_RVV_TYPE (vuint8mf4_t, 16, __rvv_uint8mf4_t, unsigned_intQI, VNx2QI, VNx1QI) > +DEF_RVV_TYPE (vint8mf4_t, 15, __rvv_int8mf4_t, intQI, VNx2QI, VNx1QI, _i8mf4, > + _i8, _e8mf4) > +DEF_RVV_TYPE (vuint8mf4_t, 16, __rvv_uint8mf4_t, unsigned_intQI, VNx2QI, VNx1QI, > + _u8mf4, _u8, _e8mf4) > /* LMUL = 1/2: > Machine mode = VNx4QImode when TARGET_MIN_VLEN > 32. > Machine mode = VNx2QImode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vint8mf2_t, 15, __rvv_int8mf2_t, intQI, VNx4QI, VNx2QI) > -DEF_RVV_TYPE (vuint8mf2_t, 16, __rvv_uint8mf2_t, unsigned_intQI, VNx4QI, VNx2QI) > +DEF_RVV_TYPE (vint8mf2_t, 15, __rvv_int8mf2_t, intQI, VNx4QI, VNx2QI, _i8mf2, > + _i8, _e8mf2) > +DEF_RVV_TYPE (vuint8mf2_t, 16, __rvv_uint8mf2_t, unsigned_intQI, VNx4QI, VNx2QI, > + _u8mf2, _u8, _e8mf2) > /* LMUL = 1: > Machine mode = VNx8QImode when TARGET_MIN_VLEN > 32. > Machine mode = VNx4QImode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vint8m1_t, 14, __rvv_int8m1_t, intQI, VNx8QI, VNx4QI) > -DEF_RVV_TYPE (vuint8m1_t, 15, __rvv_uint8m1_t, unsigned_intQI, VNx8QI, VNx4QI) > +DEF_RVV_TYPE (vint8m1_t, 14, __rvv_int8m1_t, intQI, VNx8QI, VNx4QI, _i8m1, _i8, > + _e8m1) > +DEF_RVV_TYPE (vuint8m1_t, 15, __rvv_uint8m1_t, unsigned_intQI, VNx8QI, VNx4QI, > + _u8m1, _u8, _e8m1) > /* LMUL = 2: > Machine mode = VNx16QImode when TARGET_MIN_VLEN > 32. > Machine mode = VNx8QImode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vint8m2_t, 14, __rvv_int8m2_t, intQI, VNx16QI, VNx8QI) > -DEF_RVV_TYPE (vuint8m2_t, 15, __rvv_uint8m2_t, unsigned_intQI, VNx16QI, VNx8QI) > +DEF_RVV_TYPE (vint8m2_t, 14, __rvv_int8m2_t, intQI, VNx16QI, VNx8QI, _i8m2, _i8, > + _e8m2) > +DEF_RVV_TYPE (vuint8m2_t, 15, __rvv_uint8m2_t, unsigned_intQI, VNx16QI, VNx8QI, > + _u8m2, _u8, _e8m2) > /* LMUL = 4: > Machine mode = VNx32QImode when TARGET_MIN_VLEN > 32. > Machine mode = VNx16QImode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vint8m4_t, 14, __rvv_int8m4_t, intQI, VNx32QI, VNx16QI) > -DEF_RVV_TYPE (vuint8m4_t, 15, __rvv_uint8m4_t, unsigned_intQI, VNx32QI, VNx16QI) > +DEF_RVV_TYPE (vint8m4_t, 14, __rvv_int8m4_t, intQI, VNx32QI, VNx16QI, _i8m4, > + _i8, _e8m4) > +DEF_RVV_TYPE (vuint8m4_t, 15, __rvv_uint8m4_t, unsigned_intQI, VNx32QI, VNx16QI, > + _u8m4, _u8, _e8m4) > /* LMUL = 8: > Machine mode = VNx64QImode when TARGET_MIN_VLEN > 32. > Machine mode = VNx32QImode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vint8m8_t, 14, __rvv_int8m8_t, intQI, VNx64QI, VNx32QI) > -DEF_RVV_TYPE (vuint8m8_t, 15, __rvv_uint8m8_t, unsigned_intQI, VNx64QI, VNx32QI) > +DEF_RVV_TYPE (vint8m8_t, 14, __rvv_int8m8_t, intQI, VNx64QI, VNx32QI, _i8m8, > + _i8, _e8m8) > +DEF_RVV_TYPE (vuint8m8_t, 15, __rvv_uint8m8_t, unsigned_intQI, VNx64QI, VNx32QI, > + _u8m8, _u8, _e8m8) > > /* LMUL = 1/4: > Only enble when TARGET_MIN_VLEN > 32 and machine mode = VNx1HImode. */ > -DEF_RVV_TYPE (vint16mf4_t, 16, __rvv_int16mf4_t, intHI, VNx1HI, VOID) > -DEF_RVV_TYPE (vuint16mf4_t, 17, __rvv_uint16mf4_t, unsigned_intHI, VNx1HI, VOID) > +DEF_RVV_TYPE (vint16mf4_t, 16, __rvv_int16mf4_t, intHI, VNx1HI, VOID, _i16mf4, > + _i16, _e16mf4) > +DEF_RVV_TYPE (vuint16mf4_t, 17, __rvv_uint16mf4_t, unsigned_intHI, VNx1HI, VOID, > + _u16mf4, _u16, _e16mf4) > /* LMUL = 1/2: > Machine mode = VNx2HImode when TARGET_MIN_VLEN > 32. > Machine mode = VNx1HImode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vint16mf2_t, 16, __rvv_int16mf2_t, intHI, VNx2HI, VNx1HI) > +DEF_RVV_TYPE (vint16mf2_t, 16, __rvv_int16mf2_t, intHI, VNx2HI, VNx1HI, _i16mf2, > + _i16, _e16mf2) > DEF_RVV_TYPE (vuint16mf2_t, 17, __rvv_uint16mf2_t, unsigned_intHI, VNx2HI, > - VNx1HI) > + VNx1HI, _u16mf2, _u16, _e16mf2) > /* LMUL = 1: > Machine mode = VNx4HImode when TARGET_MIN_VLEN > 32. > Machine mode = VNx2HImode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vint16m1_t, 15, __rvv_int16m1_t, intHI, VNx4HI, VNx2HI) > -DEF_RVV_TYPE (vuint16m1_t, 16, __rvv_uint16m1_t, unsigned_intHI, VNx4HI, VNx2HI) > +DEF_RVV_TYPE (vint16m1_t, 15, __rvv_int16m1_t, intHI, VNx4HI, VNx2HI, _i16m1, > + _i16, _e16m1) > +DEF_RVV_TYPE (vuint16m1_t, 16, __rvv_uint16m1_t, unsigned_intHI, VNx4HI, VNx2HI, > + _u16m1, _u16, _e16m1) > /* LMUL = 2: > Machine mode = VNx8HImode when TARGET_MIN_VLEN > 32. > Machine mode = VNx4HImode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vint16m2_t, 15, __rvv_int16m2_t, intHI, VNx8HI, VNx4HI) > -DEF_RVV_TYPE (vuint16m2_t, 16, __rvv_uint16m2_t, unsigned_intHI, VNx8HI, VNx4HI) > +DEF_RVV_TYPE (vint16m2_t, 15, __rvv_int16m2_t, intHI, VNx8HI, VNx4HI, _i16m2, > + _i16, _e16m2) > +DEF_RVV_TYPE (vuint16m2_t, 16, __rvv_uint16m2_t, unsigned_intHI, VNx8HI, VNx4HI, > + _u16m2, _u16, _e16m2) > /* LMUL = 4: > Machine mode = VNx16HImode when TARGET_MIN_VLEN > 32. > Machine mode = VNx8HImode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vint16m4_t, 15, __rvv_int16m4_t, intHI, VNx16HI, VNx8HI) > +DEF_RVV_TYPE (vint16m4_t, 15, __rvv_int16m4_t, intHI, VNx16HI, VNx8HI, _i16m4, > + _i16, _e16m4) > DEF_RVV_TYPE (vuint16m4_t, 16, __rvv_uint16m4_t, unsigned_intHI, VNx16HI, > - VNx8HI) > + VNx8HI, _u16m4, _u16, _e16m4) > /* LMUL = 8: > Machine mode = VNx32HImode when TARGET_MIN_VLEN > 32. > Machine mode = VNx16HImode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vint16m8_t, 15, __rvv_int16m8_t, intHI, VNx32HI, VNx16HI) > +DEF_RVV_TYPE (vint16m8_t, 15, __rvv_int16m8_t, intHI, VNx32HI, VNx16HI, _i16m8, > + _i16, _e16m8) > DEF_RVV_TYPE (vuint16m8_t, 16, __rvv_uint16m8_t, unsigned_intHI, VNx32HI, > - VNx16HI) > + VNx16HI, _u16m8, _u16, _e16m8) > > /* LMUL = 1/2: > Only enble when TARGET_MIN_VLEN > 32 and machine mode = VNx1SImode. */ > -DEF_RVV_TYPE (vint32mf2_t, 16, __rvv_int32mf2_t, int32, VNx1SI, VOID) > -DEF_RVV_TYPE (vuint32mf2_t, 17, __rvv_uint32mf2_t, unsigned_int32, VNx1SI, VOID) > +DEF_RVV_TYPE (vint32mf2_t, 16, __rvv_int32mf2_t, int32, VNx1SI, VOID, _i32mf2, > + _i32, _e32mf2) > +DEF_RVV_TYPE (vuint32mf2_t, 17, __rvv_uint32mf2_t, unsigned_int32, VNx1SI, VOID, > + _u32mf2, _u32, _e32mf2) > /* LMUL = 1: > Machine mode = VNx2SImode when TARGET_MIN_VLEN > 32. > Machine mode = VNx1SImode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vint32m1_t, 15, __rvv_int32m1_t, int32, VNx2SI, VNx1SI) > -DEF_RVV_TYPE (vuint32m1_t, 16, __rvv_uint32m1_t, unsigned_int32, VNx2SI, VNx1SI) > +DEF_RVV_TYPE (vint32m1_t, 15, __rvv_int32m1_t, int32, VNx2SI, VNx1SI, _i32m1, > + _i32, _e32m1) > +DEF_RVV_TYPE (vuint32m1_t, 16, __rvv_uint32m1_t, unsigned_int32, VNx2SI, VNx1SI, > + _u32m1, _u32, _e32m1) > /* LMUL = 2: > Machine mode = VNx4SImode when TARGET_MIN_VLEN > 32. > Machine mode = VNx2SImode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vint32m2_t, 15, __rvv_int32m2_t, int32, VNx4SI, VNx2SI) > -DEF_RVV_TYPE (vuint32m2_t, 16, __rvv_uint32m2_t, unsigned_int32, VNx4SI, VNx2SI) > +DEF_RVV_TYPE (vint32m2_t, 15, __rvv_int32m2_t, int32, VNx4SI, VNx2SI, _i32m2, > + _i32, _e32m2) > +DEF_RVV_TYPE (vuint32m2_t, 16, __rvv_uint32m2_t, unsigned_int32, VNx4SI, VNx2SI, > + _u32m2, _u32, _e32m2) > /* LMUL = 4: > Machine mode = VNx8SImode when TARGET_MIN_VLEN > 32. > Machine mode = VNx4SImode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vint32m4_t, 15, __rvv_int32m4_t, int32, VNx8SI, VNx4SI) > -DEF_RVV_TYPE (vuint32m4_t, 16, __rvv_uint32m4_t, unsigned_int32, VNx8SI, VNx4SI) > +DEF_RVV_TYPE (vint32m4_t, 15, __rvv_int32m4_t, int32, VNx8SI, VNx4SI, _i32m4, > + _i32, _e32m4) > +DEF_RVV_TYPE (vuint32m4_t, 16, __rvv_uint32m4_t, unsigned_int32, VNx8SI, VNx4SI, > + _u32m4, _u32, _e32m4) > /* LMUL = 8: > Machine mode = VNx16SImode when TARGET_MIN_VLEN > 32. > Machine mode = VNx8SImode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vint32m8_t, 15, __rvv_int32m8_t, int32, VNx16SI, VNx8SI) > +DEF_RVV_TYPE (vint32m8_t, 15, __rvv_int32m8_t, int32, VNx16SI, VNx8SI, _i32m8, > + _i32, _e32m8) > DEF_RVV_TYPE (vuint32m8_t, 16, __rvv_uint32m8_t, unsigned_int32, VNx16SI, > - VNx8SI) > + VNx8SI, _u32m8, _u32, _e32m8) > > /* SEW = 64: > Disable when TARGET_MIN_VLEN > 32. */ > -DEF_RVV_TYPE (vint64m1_t, 15, __rvv_int64m1_t, intDI, VNx1DI, VOID) > -DEF_RVV_TYPE (vuint64m1_t, 16, __rvv_uint64m1_t, unsigned_intDI, VNx1DI, VOID) > -DEF_RVV_TYPE (vint64m2_t, 15, __rvv_int64m2_t, intDI, VNx2DI, VOID) > -DEF_RVV_TYPE (vuint64m2_t, 16, __rvv_uint64m2_t, unsigned_intDI, VNx2DI, VOID) > -DEF_RVV_TYPE (vint64m4_t, 15, __rvv_int64m4_t, intDI, VNx4DI, VOID) > -DEF_RVV_TYPE (vuint64m4_t, 16, __rvv_uint64m4_t, unsigned_intDI, VNx4DI, VOID) > -DEF_RVV_TYPE (vint64m8_t, 15, __rvv_int64m8_t, intDI, VNx8DI, VOID) > -DEF_RVV_TYPE (vuint64m8_t, 16, __rvv_uint64m8_t, unsigned_intDI, VNx8DI, VOID) > +DEF_RVV_TYPE (vint64m1_t, 15, __rvv_int64m1_t, intDI, VNx1DI, VOID, _i64m1, > + _i64, _e64m1) > +DEF_RVV_TYPE (vuint64m1_t, 16, __rvv_uint64m1_t, unsigned_intDI, VNx1DI, VOID, > + _u64m1, _u64, _e64m1) > +DEF_RVV_TYPE (vint64m2_t, 15, __rvv_int64m2_t, intDI, VNx2DI, VOID, _i64m2, > + _i64, _e64m2) > +DEF_RVV_TYPE (vuint64m2_t, 16, __rvv_uint64m2_t, unsigned_intDI, VNx2DI, VOID, > + _u64m2, _u64, _e64m2) > +DEF_RVV_TYPE (vint64m4_t, 15, __rvv_int64m4_t, intDI, VNx4DI, VOID, _i64m4, > + _i64, _e64m4) > +DEF_RVV_TYPE (vuint64m4_t, 16, __rvv_uint64m4_t, unsigned_intDI, VNx4DI, VOID, > + _u64m4, _u64, _e64m4) > +DEF_RVV_TYPE (vint64m8_t, 15, __rvv_int64m8_t, intDI, VNx8DI, VOID, _i64m8, > + _i64, _e64m8) > +DEF_RVV_TYPE (vuint64m8_t, 16, __rvv_uint64m8_t, unsigned_intDI, VNx8DI, VOID, > + _u64m8, _u64, _e64m8) > > /* LMUL = 1/2: > Only enble when TARGET_MIN_VLEN > 32 and machine mode = VNx1SFmode. */ > -DEF_RVV_TYPE (vfloat32mf2_t, 18, __rvv_float32mf2_t, float, VNx1SF, VOID) > +DEF_RVV_TYPE (vfloat32mf2_t, 18, __rvv_float32mf2_t, float, VNx1SF, VOID, > + _f32mf2, _f32, _e32mf2) > /* LMUL = 1: > Machine mode = VNx2SFmode when TARGET_MIN_VLEN > 32. > Machine mode = VNx1SFmode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vfloat32m1_t, 17, __rvv_float32m1_t, float, VNx2SF, VNx1SF) > +DEF_RVV_TYPE (vfloat32m1_t, 17, __rvv_float32m1_t, float, VNx2SF, VNx1SF, > + _f32m1, _f32, _e32m1) > /* LMUL = 2: > Machine mode = VNx4SFmode when TARGET_MIN_VLEN > 32. > Machine mode = VNx2SFmode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vfloat32m2_t, 17, __rvv_float32m2_t, float, VNx4SF, VNx2SF) > +DEF_RVV_TYPE (vfloat32m2_t, 17, __rvv_float32m2_t, float, VNx4SF, VNx2SF, > + _f32m2, _f32, _e32m2) > /* LMUL = 4: > Machine mode = VNx8SFmode when TARGET_MIN_VLEN > 32. > Machine mode = VNx4SFmode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vfloat32m4_t, 17, __rvv_float32m4_t, float, VNx8SF, VNx4SF) > +DEF_RVV_TYPE (vfloat32m4_t, 17, __rvv_float32m4_t, float, VNx8SF, VNx4SF, > + _f32m4, _f32, _e32m4) > /* LMUL = 8: > Machine mode = VNx16SFmode when TARGET_MIN_VLEN > 32. > Machine mode = VNx8SFmode when TARGET_MIN_VLEN = 32. */ > -DEF_RVV_TYPE (vfloat32m8_t, 17, __rvv_float32m8_t, float, VNx16SF, VNx8SF) > +DEF_RVV_TYPE (vfloat32m8_t, 17, __rvv_float32m8_t, float, VNx16SF, VNx8SF, > + _f32m8, _f32, _e32m8) > > /* SEW = 64: > Disable when TARGET_VECTOR_FP64. */ > -DEF_RVV_TYPE (vfloat64m1_t, 17, __rvv_float64m1_t, double, VNx1DF, VOID) > -DEF_RVV_TYPE (vfloat64m2_t, 17, __rvv_float64m2_t, double, VNx2DF, VOID) > -DEF_RVV_TYPE (vfloat64m4_t, 17, __rvv_float64m4_t, double, VNx4DF, VOID) > -DEF_RVV_TYPE (vfloat64m8_t, 17, __rvv_float64m8_t, double, VNx8DF, VOID) > +DEF_RVV_TYPE (vfloat64m1_t, 17, __rvv_float64m1_t, double, VNx1DF, VOID, _f64m1, > + _f64, _e64m1) > +DEF_RVV_TYPE (vfloat64m2_t, 17, __rvv_float64m2_t, double, VNx2DF, VOID, _f64m2, > + _f64, _e64m2) > +DEF_RVV_TYPE (vfloat64m4_t, 17, __rvv_float64m4_t, double, VNx4DF, VOID, _f64m4, > + _f64, _e64m4) > +DEF_RVV_TYPE (vfloat64m8_t, 17, __rvv_float64m8_t, double, VNx8DF, VOID, _f64m8, > + _f64, _e64m8) > + > +DEF_RVV_OP_TYPE (vv) > +DEF_RVV_OP_TYPE (vx) > +DEF_RVV_OP_TYPE (v) > +DEF_RVV_OP_TYPE (wv) > +DEF_RVV_OP_TYPE (wx) > +DEF_RVV_OP_TYPE (x_x_v) > +DEF_RVV_OP_TYPE (vf2) > +DEF_RVV_OP_TYPE (vf4) > +DEF_RVV_OP_TYPE (vf8) > +DEF_RVV_OP_TYPE (vvm) > +DEF_RVV_OP_TYPE (vxm) > +DEF_RVV_OP_TYPE (x_x_w) > +DEF_RVV_OP_TYPE (v_v) > +DEF_RVV_OP_TYPE (v_x) > +DEF_RVV_OP_TYPE (vs) > +DEF_RVV_OP_TYPE (mm) > +DEF_RVV_OP_TYPE (m) > +DEF_RVV_OP_TYPE (vf) > +DEF_RVV_OP_TYPE (vm) > +DEF_RVV_OP_TYPE (wf) > +DEF_RVV_OP_TYPE (vfm) > +DEF_RVV_OP_TYPE (v_f) > + > +DEF_RVV_PRED_TYPE (ta) > +DEF_RVV_PRED_TYPE (tu) > +DEF_RVV_PRED_TYPE (ma) > +DEF_RVV_PRED_TYPE (mu) > +DEF_RVV_PRED_TYPE (tama) > +DEF_RVV_PRED_TYPE (tamu) > +DEF_RVV_PRED_TYPE (tuma) > +DEF_RVV_PRED_TYPE (tumu) > +DEF_RVV_PRED_TYPE (m) > +DEF_RVV_PRED_TYPE (tam) > +DEF_RVV_PRED_TYPE (tum) > > +#undef DEF_RVV_PRED_TYPE > +#undef DEF_RVV_OP_TYPE > #undef DEF_RVV_TYPE > diff --git a/gcc/config/riscv/riscv-vector-builtins.h b/gcc/config/riscv/riscv-vector-builtins.h > index ea67da9905c..425da12326c 100644 > --- a/gcc/config/riscv/riscv-vector-builtins.h > +++ b/gcc/config/riscv/riscv-vector-builtins.h > @@ -21,8 +21,101 @@ > #ifndef GCC_RISCV_VECTOR_BUILTINS_H > #define GCC_RISCV_VECTOR_BUILTINS_H > > +/* The full name of an RVV intrinsic function is the concatenation of: > + > + - the base name ("vadd", etc.) > + - the operand suffix ("_vv", "_vx", etc.) > + - the type suffix ("_i32m1", "_i32mf2", etc.) > + - the predication suffix ("_tamu", "_tumu", etc.) > + > + Each piece of information is individually useful, so we retain this > + classification throughout: > + > + - function_base represents the base name. > + > + - operand_type_index can be used as an index to get operand suffix. > + > + - rvv_op_info can be used as an index to get argument suffix. > + > + - predication_type_index can be used as an index to get predication suffix. > + > + In addition to its unique full name, a function may have a shorter > + overloaded alias. This alias removes pieces of the suffixes that > + can be inferred from the arguments, such as by shortening the mode > + suffix or dropping some of the type suffixes. The base name and the > + predication suffix stay the same. > + > + - The function_instance class describes contains all properties of each > + individual function. Such these information will be used by > + function_builder, function_base, function_shape, gimple_folder, > + function_expander, etc. > + > + - The function_builder class provides several helper function to add an > + intrinsic function. > + > + - The function_shape class describes how that instruction has been presented > + at the language level: > + > + 1. Determine the function name for C and C++ overload function which can > + be recognized by compiler at language level for each instruction > + according to members of function_instance (base name, operand suffix, > + type suffix, predication suffix, etc.). > + > + 2. Specify the arguments type and return type of each function to > + describe how that instruction has presented at language level. > + > + - The function_base describes how the underlying instruction behaves. > + > + The static list of functions uses function_group to describe a group > + of related functions. The function_builder class is responsible for > + expanding this static description into a list of individual functions > + and registering the associated built-in functions. function_instance > + describes one of these individual functions in terms of the properties > + described above. > + > + The classes involved in compiling a function call are: > + > + - function_resolver, which resolves an overloaded function call to a > + specific function_instance and its associated function decl. > + > + - function_checker, which checks whether the values of the arguments > + conform to the RVV ISA specification. > + > + - gimple_folder, which tries to fold a function call at the gimple level > + > + - function_expander, which expands a function call into rtl instructions > + > + function_resolver and function_checker operate at the language level > + and so are associated with the function_shape. gimple_folder and > + function_expander are concerned with the behavior of the function > + and so are associated with the function_base. */ > + > namespace riscv_vector { > > +/* Flags that describe what a function might do, in addition to reading > + its arguments and returning a result. */ > +static const unsigned int CP_READ_FPCR = 1U << 0; > +static const unsigned int CP_RAISE_FP_EXCEPTIONS = 1U << 1; > +static const unsigned int CP_READ_MEMORY = 1U << 2; > +static const unsigned int CP_WRITE_MEMORY = 1U << 3; > +static const unsigned int CP_READ_CSR = 1U << 4; > +static const unsigned int CP_WRITE_CSR = 1U << 5; > + > +/* Bit values used to identify required extensions for RVV intrinsics. */ > +#define RVV_REQUIRE_RV64BIT (1 << 0) /* Require RV64. */ > +#define RVV_REQUIRE_ZVE64 (1 << 1) /* Require TARGET_MIN_VLEN > 32. */ > +#define RVV_REQUIRE_ELEN_FP_32 (1 << 2) /* Require FP ELEN >= 32. */ > +#define RVV_REQUIRE_ELEN_FP_64 (1 << 3) /* Require FP ELEN >= 64. */ > + > +/* Enumerates the RVV operand types. */ > +enum operand_type_index > +{ > + OP_TYPE_none, > +#define DEF_RVV_OP_TYPE(NAME) OP_TYPE_##NAME, > +#include "riscv-vector-builtins.def" > + NUM_OP_TYPES > +}; > + > /* Enumerates the RVV types, together called > "vector types" for brevity. */ > enum vector_type_index > @@ -32,6 +125,31 @@ enum vector_type_index > NUM_VECTOR_TYPES > }; > > +/* Enumerates the RVV governing predication types. */ > +enum predication_type_index > +{ > + PRED_TYPE_none, > +#define DEF_RVV_PRED_TYPE(NAME) PRED_TYPE_##NAME, > +#include "riscv-vector-builtins.def" > + NUM_PRED_TYPES > +}; > + > +/* Enumerates the RVV base types. */ > +enum rvv_base_type > +{ > + RVV_BASE_vector, > + RVV_BASE_scalar, > + RVV_BASE_vector_ptr, > + RVV_BASE_scalar_ptr, > + RVV_BASE_scalar_const_ptr, > + RVV_BASE_void, > + RVV_BASE_size, > + RVV_BASE_ptrdiff, > + RVV_BASE_unsigned_long, > + RVV_BASE_long, > + NUM_BASE_TYPES > +}; > + > /* Builtin types that are used to register RVV intrinsics. */ > struct GTY (()) rvv_builtin_types_t > { > @@ -42,6 +160,251 @@ struct GTY (()) rvv_builtin_types_t > tree scalar_const_ptr; > }; > > +/* Builtin suffix that are used to register RVV intrinsics. */ > +struct rvv_builtin_suffixes > +{ > + const char *vector; > + const char *scalar; > + const char *vsetvl; > +}; > + > +/* RVV Builtin argument information. */ > +struct rvv_arg_type_info > +{ > + CONSTEXPR rvv_arg_type_info (rvv_base_type base_type_in) > + : base_type (base_type_in) > + {} > + enum rvv_base_type base_type; > + > + tree get_tree_type (vector_type_index) const; > +}; > + > +/* Static information for each operand. */ > +struct rvv_type_info > +{ > + enum vector_type_index index; > + uint64_t required_extensions; > +}; > + > +/* RVV Builtin operands information. */ > +struct rvv_op_info > +{ > + const rvv_type_info *types; > + const operand_type_index op; > + rvv_arg_type_info ret; > + const rvv_arg_type_info *args; > +}; > + > +class registered_function; > +class function_base; > +class function_shape; > + > +/* Static information about a set of functions. */ > +struct function_group_info > +{ > + /* The base name, as a string. */ > + const char *base_name; > + > + /* Describes the behavior associated with the function base name. */ > + const function_base *const *base; > + > + /* The shape of the functions, as described above the class definition. > + It's possible to have entries with the same base name but different > + shapes. */ > + const function_shape *const *shape; > + > + /* A list of the available operand types, predication types, > + and of the available operand datatype. > + The function supports every combination of the two. > + The list of predication is terminated by two NUM_PRED_TYPES, > + while the list of operand info is terminated by NUM_BASE_TYPES. > + The list of these type suffix is lexicographically ordered based > + on the index value. */ > + const predication_type_index *preds; > + const rvv_op_info ops_infos; > +}; > + > +class GTY ((user)) function_instance > +{ > +public: > + function_instance (const char *, const function_base *, > + const function_shape *, rvv_type_info, > + predication_type_index, const rvv_op_info *); > + > + bool operator== (const function_instance &) const; > + bool operator!= (const function_instance &) const; > + hashval_t hash () const; > + > + unsigned int call_properties () const; > + bool reads_global_state_p () const; > + bool modifies_global_state_p () const; > + bool could_trap_p () const; > + > + /* Return true if return type or arguments are floating point type. */ > + bool any_type_float_p () const; > + > + tree get_return_type () const; > + tree get_arg_type (unsigned opno) const; > + > + /* The properties of the function. (The explicit "enum"s are required > + for gengtype.) */ > + const char *base_name; > + const function_base *base; > + const function_shape *shape; > + rvv_type_info type; > + enum predication_type_index pred; > + const rvv_op_info *op_info; > +}; > + > +/* A class for building and registering function decls. */ > +class function_builder > +{ > +public: > + function_builder (); > + ~function_builder (); > + > + void allocate_argument_types (const function_instance &, vec &) const; > + void add_unique_function (const function_instance &, const function_shape *, > + tree, vec &); > + void register_function_group (const function_group_info &); > + void append_name (const char *); > + char *finish_name (); > + > +private: > + tree get_attributes (const function_instance &); > + > + registered_function &add_function (const function_instance &, const char *, > + tree, tree, bool); > + > + /* True if we should create a separate decl for each instance of an > + overloaded function, instead of using function_builder. */ > + bool m_direct_overloads; > + > + /* Used for building up function names. */ > + obstack m_string_obstack; > +}; > + > +/* A base class for handling calls to built-in functions. */ > +class function_call_info : public function_instance > +{ > +public: > + function_call_info (location_t, const function_instance &, tree); > + > + bool function_returns_void_p (); > + > + /* The location of the call. */ > + location_t location; > + > + /* The FUNCTION_DECL that is being called. */ > + tree fndecl; > +}; > + > +/* Return true if the function has no return value. */ > +inline bool > +function_call_info::function_returns_void_p () > +{ > + return TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node; > +} > + > +/* A class for expanding a function call into RTL. */ > +class function_expander : public function_call_info > +{ > +public: > + function_expander (const function_instance &, tree, tree, rtx); > + rtx expand (); > + > + void add_input_operand (machine_mode, rtx); > + void add_input_operand (unsigned argno); > + rtx generate_insn (insn_code); > + > + /* The function call expression. */ > + tree exp; > + > + /* For functions that return a value, this is the preferred location > + of that value. It could be null or could have a different mode > + from the function return type. */ > + rtx target; > + > + /* The number of the operands. */ > + int opno; > + > +private: > + /* Used to build up the operands to an instruction. */ > + struct expand_operand m_ops[MAX_RECOG_OPERANDS]; > +}; > + > +/* Provides information about a particular function base name, and handles > + tasks related to the base name. */ > +class function_base > +{ > +public: > + /* Return a set of CP_* flags that describe what the function might do, > + in addition to reading its arguments and returning a result. */ > + virtual unsigned int call_properties (const function_instance &) const; > + > + /* Expand the given call into rtl. Return the result of the function, > + or an arbitrary value if the function doesn't return a result. */ > + virtual rtx expand (function_expander &) const = 0; > +}; > + > +/* Classifies functions into "shapes" base on: > + > + - Base name of the intrinsic function. > + > + - Operand types list. > + > + - Argument type list. > + > + - Predication type list. */ > +class function_shape > +{ > +public: > + /* Shape the function name according to function_instance. */ > + virtual char *get_name (function_builder &, const function_instance &, > + bool) const > + = 0; > + > + /* Define all functions associated with the given group. */ > + virtual void build (function_builder &, const function_group_info &) const > + = 0; > +}; > + > +extern const char *const operand_suffixes[NUM_OP_TYPES]; > +extern const rvv_builtin_suffixes type_suffixes[NUM_VECTOR_TYPES + 1]; > +extern const char *const predication_suffixes[NUM_PRED_TYPES]; > +extern rvv_builtin_types_t builtin_types[NUM_VECTOR_TYPES + 1]; > + > +inline bool > +function_instance::operator!= (const function_instance &other) const > +{ > + return !operator== (other); > +} > + > +/* Expand the call and return its lhs. */ > +inline rtx > +function_expander::expand () > +{ > + return base->expand (*this); > +} > + > +/* Create op and add it into M_OPS and increase OPNO. */ > +inline void > +function_expander::add_input_operand (machine_mode mode, rtx op) > +{ > + create_input_operand (&m_ops[opno++], op, mode); > +} > + > +/* Default implementation of function_base::call_properties, with conservatively > + correct behavior for floating-point instructions. */ > +inline unsigned int > +function_base::call_properties (const function_instance &instance) const > +{ > + unsigned int flags = 0; > + if (instance.any_type_float_p ()) > + return flags | CP_READ_FPCR | CP_RAISE_FP_EXCEPTIONS; > + return flags; > +} > + > } // end namespace riscv_vector > > #endif > -- > 2.36.1 >