Message ID | 07b22c71-16bc-f85a-5ff8-1f6009f0056d@rivosinc.com |
---|---|
State | Superseded, archived |
Headers |
Return-Path: <gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org> 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 2E386385B528 for <patchwork@sourceware.org>; Mon, 6 Mar 2023 03:16:22 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-qt1-x835.google.com (mail-qt1-x835.google.com [IPv6:2607:f8b0:4864:20::835]) by sourceware.org (Postfix) with ESMTPS id 4B7803858431 for <gcc-patches@gcc.gnu.org>; Mon, 6 Mar 2023 03:16:03 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 4B7803858431 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=rivosinc.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=rivosinc.com Received: by mail-qt1-x835.google.com with SMTP id c18so9228643qte.5 for <gcc-patches@gcc.gnu.org>; Sun, 05 Mar 2023 19:16:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rivosinc-com.20210112.gappssmtp.com; s=20210112; h=content-transfer-encoding:content-language:to:subject:from :user-agent:mime-version:date:message-id:from:to:cc:subject:date :message-id:reply-to; bh=ddIJe8xUViL4kzkY8ECdK8pr/vpOuF12u10KqwSynI4=; b=40sDl7Trgui4q2QYg5AE4RPu1D9Lfw2HObW0jSEQRbSzNHPc1CRofab2/QCStyukEA kv+UvWsbvmbiVoXTOXz0yVObtcyoK2/TcwCP0foaf/XPlNn7T4bVy/X+ddvcBoQZ660W +7QXyl5HDMOxSJi/vnD1uCC0lPWRkNyW3Ggc2YolMv7INawUThSdTaSi2qoUzR1GqNV3 VlCCteDbbXJOd8mSKPTnHQA2vtm26gz7NENOwvzSa6Qno8sLa2WPozEm79tUQZDpNJAv KKncXc2NbJ8nkU7hDGYapFeN1zg6ZVZ22ckC6L1TFeiw8+eWjx5CSZIsvIITMFqKZSiE RRKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:content-language:to:subject:from :user-agent:mime-version:date:message-id:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=ddIJe8xUViL4kzkY8ECdK8pr/vpOuF12u10KqwSynI4=; b=iRo7Jxf3hLiaIoSfscyWNXk/mvghAwH2kD0bn9kUwkxc3vtiReCDnw2jch+lbZUwBW lmF2buTAfRB7Wb10BvkEjAtiZMvFKyNJdo5n/LcGnEIELp1qMwjC2ZA4VKgnJDP7Flfo xFUAO6kukpf7gMa2bpPeVNhsDyYCc5M+csDGa4yj8oiiMGlrnt5FYCQgF2F4g6KrQntD /Rvs+6QsAmNb3uNJ+F/eWf4d9O17nox5FielOMdXiAm25opUnN13pzuZh7n4riCEXwLi heYSq2Leh+1qZHJ4V//I4PXhdNfzmVpSaWCteQsFp4TtOlCZDADMh/mZHn35kInJf3jC jNWw== X-Gm-Message-State: AO0yUKXmEG5fwEZoqOFSQSjN87f2lSZEGO/gaF6nXyaAruY82BGPm2tc 2IMI5VtilJIr+aubAGMr+wT1IEmdWCrtGZaYTOY= X-Google-Smtp-Source: AK7set+Rg7/8VQsb7bQrG6vQ889WSngaHJNZ/CIab8q9D27UAypZzfOIwEtTVloUV1KTgT96Vg9UJw== X-Received: by 2002:ac8:5dca:0:b0:3b8:6db0:7565 with SMTP id e10-20020ac85dca000000b003b86db07565mr17664154qtx.11.1678072562145; Sun, 05 Mar 2023 19:16:02 -0800 (PST) Received: from [192.168.86.117] ([136.57.172.92]) by smtp.gmail.com with ESMTPSA id t64-20020ae9df43000000b007430d280879sm6771920qkf.35.2023.03.05.19.16.01 for <gcc-patches@gcc.gnu.org> (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 05 Mar 2023 19:16:01 -0800 (PST) Message-ID: <07b22c71-16bc-f85a-5ff8-1f6009f0056d@rivosinc.com> Date: Sun, 5 Mar 2023 22:16:01 -0500 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.7.1 From: Michael Collison <collison@rivosinc.com> Subject: [PATCH v2 05/07] RISC-V: autovec: Add tuning and target vectorization hooks To: gcc-patches <gcc-patches@gcc.gnu.org> Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-11.0 required=5.0 tests=BAYES_00, BODY_8BITS, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, 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 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list <gcc-patches.gcc.gnu.org> List-Unsubscribe: <https://gcc.gnu.org/mailman/options/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe> List-Archive: <https://gcc.gnu.org/pipermail/gcc-patches/> List-Post: <mailto:gcc-patches@gcc.gnu.org> List-Help: <mailto:gcc-patches-request@gcc.gnu.org?subject=help> List-Subscribe: <https://gcc.gnu.org/mailman/listinfo/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe> Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" <gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org> |
Series |
RISC-V: autovec: Add auto-vectorization support
|
|
Commit Message
Michael Collison
March 6, 2023, 3:16 a.m. UTC
This patch adds support for registering target hooks for basic autovectorization support as well as basic tuning information for the vector extension. gcc/ChangeLog: 2023-03-02 Michael Collison <collison@rivosinc.com> Juzhe Zhong <juzhe.zhong@rivai.ai> * config/riscv/riscv-cores.def (RISCV_TUNE): Add VECTOR_TUNE_INFO parameter and * common/config/riscv/riscv-common.cc (RISCV_TUNE): Add VECTOR_TUNE_INFO parameter. * config/riscv/riscv.cc (riscv_vector_tune_param): New struct for vector tuning information. (riscv_tune_info): add vector_tune_param. (vector_tune_param): New static variable. (riscv_vectorization_factor): New variable. (generic_rvv_insn_scale_table): New struct. (generic_rvv_stmt_scale_table): New struct. (generic_rvv_insn_cost_table): New vector insn cost table. (generic_rvv_stmt_cost_table): New vector statement cost table. (generic_rvv_tune_info): New rvv tuning table. (RISCV_TUNE): Add VECTOR_TUNE_INFO parameter. (riscv_rtx_costs): Return vector estimate if vector mode. (riscv_option_override): Set vector_tune_param. (riscv_option_override): Set riscv_vectorization_factor. (riscv_estimated_poly_value): Implement TARGET_ESTIMATED_POLY_VALUE. (riscv_preferred_simd_mode): Implement TARGET_VECTORIZE_PREFERRED_SIMD_MODE. (riscv_autovectorize_vector_modes): Implement TARGET_AUTOVECTORIZE_VECTOR_MODES. (riscv_get_mask_mode): Implement TARGET_VECTORIZE_GET_MASK_MODE. (riscv_empty_mask_is_expensive): Implement TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE. (riscv_builtin_vectorization_cost): Implement TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST. (riscv_vectorize_create_costs): Implement TARGET_VECTORIZE_CREATE_COSTS. (TARGET_ESTIMATED_POLY_VALUE): Register target macro. (TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST): Ditto. (TARGET_VECTORIZE_PREFERRED_SIMD_MODE): Ditto. (TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES): Ditto. (TARGET_VECTORIZE_GET_MASK_MODE): Ditto. (TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE): Ditto. (TARGET_VECTORIZE_LOOP_LEN_OVERRIDE_MASK): Ditto. (TARGET_VECTORIZE_CREATE_COSTS): Ditto --- gcc/common/config/riscv/riscv-common.cc | 2 +- gcc/config/riscv/riscv-cores.def | 14 +- gcc/config/riscv/riscv.cc | 324 +++++++++++++++++++++++- 3 files changed, 328 insertions(+), 12 deletions(-) static tree riscv_handle_type_attribute (tree *, tree, tree, int, bool *); @@ -403,8 +469,8 @@ static const unsigned gpr_save_reg_order[] = { /* A table describing all the processors GCC knows about. */ static const struct riscv_tune_info riscv_tune_info_table[] = { -#define RISCV_TUNE(TUNE_NAME, PIPELINE_MODEL, TUNE_INFO) \ - { TUNE_NAME, PIPELINE_MODEL, & TUNE_INFO}, +#define RISCV_TUNE(TUNE_NAME, PIPELINE_MODEL, TUNE_INFO, VECTOR_TUNE_INFO) \ + { TUNE_NAME, PIPELINE_MODEL, & TUNE_INFO, &VECTOR_TUNE_INFO}, #include "riscv-cores.def" }; @@ -2237,8 +2303,8 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN Cost Model need to be well analyzed and supported in the future. */ if (riscv_v_ext_vector_mode_p (mode)) { - *total = COSTS_N_INSNS (1); - return true; + return vector_tune_param->rvv_insn_costs_table->get_cost (x, mode, total, + speed); } bool float_mode_p = FLOAT_MODE_P (mode); @@ -6080,6 +6146,7 @@ riscv_option_override (void) RISCV_TUNE_STRING_DEFAULT)); riscv_microarchitecture = cpu->microarchitecture; tune_param = optimize_size ? &optimize_size_tune_info : cpu->tune_param; + vector_tune_param = cpu->vector_tune_param; /* Use -mtune's setting for slow_unaligned_access, even when optimizing for size. For architectures that trap and emulate unaligned accesses, @@ -6199,6 +6266,10 @@ riscv_option_override (void) /* Convert -march to a chunks count. */ riscv_vector_chunks = riscv_convert_vector_bits (); + + if (TARGET_VECTOR) + riscv_vectorization_factor = riscv_vector_lmul; + } /* Implement TARGET_CONDITIONAL_REGISTER_USAGE. */ @@ -6893,6 +6964,220 @@ riscv_dwarf_poly_indeterminate_value (unsigned int i, unsigned int *factor, return RISCV_DWARF_VLENB; } +/* Implement TARGET_ESTIMATED_POLY_VALUE. + Look into the tuning structure for an estimate. + KIND specifies the type of requested estimate: min, max or likely. + For cores with a known RVV width all three estimates are the same. + For generic RVV tuning we want to distinguish the maximum estimate from + the minimum and likely ones. + The likely estimate is the same as the minimum in that case to give a + conservative behavior of auto-vectorizing with RVV when it is a win + even for 128-bit RVV. + When RVV width information is available VAL.coeffs[1] is multiplied by + the number of VQ chunks over the initial Advanced SIMD 128 bits. */ + +static HOST_WIDE_INT +riscv_estimated_poly_value (poly_int64 val, + poly_value_estimate_kind kind = POLY_VALUE_LIKELY) +{ + unsigned int width_source = BITS_PER_RISCV_VECTOR.is_constant () + ? (unsigned int) BITS_PER_RISCV_VECTOR.to_constant () + : (unsigned int) RVV_SCALABLE; + + /* If there is no core-specific information then the minimum and likely + values are based on 128-bit vectors and the maximum is based on + the architectural maximum of 2048 bits. */ + if (width_source == RVV_SCALABLE) + switch (kind) + { + case POLY_VALUE_MIN: + case POLY_VALUE_LIKELY: + return val.coeffs[0]; + + case POLY_VALUE_MAX: + return val.coeffs[0] + val.coeffs[1] * 15; + } + + /* Allow BITS_PER_RISCV_VECTOR to be a bitmask of different VL, treating the + lowest as likely. This could be made more general if future -mtune + options need it to be. */ + if (kind == POLY_VALUE_MAX) + width_source = 1 << floor_log2 (width_source); + else + width_source = least_bit_hwi (width_source); + + /* If the core provides width information, use that. */ + HOST_WIDE_INT over_128 = width_source - 128; + return val.coeffs[0] + val.coeffs[1] * over_128 / 128; +} + +/* Implement TARGET_VECTORIZE_PREFERRED_SIMD_MODE. */ + +static machine_mode +riscv_preferred_simd_mode (scalar_mode mode) +{ + machine_mode vmode = + riscv_vector::riscv_vector_preferred_simd_mode (mode, + riscv_vectorization_factor); + if (VECTOR_MODE_P (vmode)) + return vmode; + + return word_mode; +} + +/* Implement TARGET_AUTOVECTORIZE_VECTOR_MODES for RVV. */ +static unsigned int +riscv_autovectorize_vector_modes (vector_modes *modes, bool) +{ + if (!TARGET_VECTOR) + return 0; + + if (riscv_vectorization_factor == RVV_LMUL1) + { + modes->safe_push (VNx16QImode); + modes->safe_push (VNx8QImode); + modes->safe_push (VNx4QImode); + modes->safe_push (VNx2QImode); + } + else if (riscv_vectorization_factor == RVV_LMUL2) + { + modes->safe_push (VNx32QImode); + modes->safe_push (VNx16QImode); + modes->safe_push (VNx8QImode); + modes->safe_push (VNx4QImode); + } + else if (riscv_vectorization_factor == RVV_LMUL4) + { + modes->safe_push (VNx64QImode); + modes->safe_push (VNx32QImode); + modes->safe_push (VNx16QImode); + modes->safe_push (VNx8QImode); + } + else + { + modes->safe_push (VNx64QImode); + modes->safe_push (VNx32QImode); + modes->safe_push (VNx16QImode); + } + + return 0; +} + +/* Implement TARGET_VECTORIZE_GET_MASK_MODE. */ + +static opt_machine_mode +riscv_get_mask_mode (machine_mode mode) +{ + machine_mode mask_mode = VOIDmode; + if (TARGET_VECTOR + && riscv_vector::riscv_vector_get_mask_mode (mode).exists (&mask_mode)) + return mask_mode; + + return default_get_mask_mode (mode); +} + +/* Implement TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE. Assume for now that + it isn't worth branching around empty masked ops (including masked + stores). */ + +static bool +riscv_empty_mask_is_expensive (unsigned) +{ + return false; +} + +/* Implement targetm.vectorize.builtin_vectorization_cost. */ +int +riscv_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost, + tree vectype, int misalign ATTRIBUTE_UNUSED) +{ + unsigned elements; + bool fp = false; + rtx x = NULL_RTX; + machine_mode mode = VOIDmode; + + if (vectype != NULL) + { + fp = FLOAT_TYPE_P (vectype); + mode = TYPE_MODE (vectype); + } + + switch (type_of_cost) + { + case scalar_stmt: + return fp ? vector_tune_param->rvv_stmt_costs_table->scalar_fp->cost (x, + mode) + : vector_tune_param->rvv_stmt_costs_table->scalar_int->cost (x, + mode); + + case scalar_load: + return vector_tune_param->rvv_stmt_costs_table->scalar_load->cost (x, + mode); + + case scalar_store: + return vector_tune_param->rvv_stmt_costs_table->scalar_store->cost (x, + mode); + + case vector_stmt: + return fp ? vector_tune_param->rvv_stmt_costs_table->vec_fp->cost (x, + mode) + : vector_tune_param->rvv_stmt_costs_table->vec_int->cost (x, + mode); + + case vector_load: + return vector_tune_param->rvv_stmt_costs_table->vec_align_load->cost (x, + mode); + + case vector_store: + return vector_tune_param->rvv_stmt_costs_table->vec_store->cost (x, mode); + + case vec_to_scalar: + return vector_tune_param->rvv_stmt_costs_table->vec_to_scalar->cost (x, + mode); + + case scalar_to_vec: + return vector_tune_param->rvv_stmt_costs_table->scalar_to_vec->cost (x, + mode); + + case unaligned_load: + case vector_gather_load: + return vector_tune_param->rvv_stmt_costs_table->vec_unalign_load->cost (x, + mode); + + case unaligned_store: + case vector_scatter_store: + return vector_tune_param->rvv_stmt_costs_table->vec_unalign_store->cost ( + x, + mode); + + case cond_branch_taken: + return vector_tune_param->rvv_stmt_costs_table->cond_taken_branch->cost ( + x, + mode); + + case cond_branch_not_taken: + return vector_tune_param->rvv_stmt_costs_table->cond_not_taken_branch + ->cost (x, mode); + + case vec_perm: + return vector_tune_param->rvv_stmt_costs_table->vec_permute->cost (x, + mode); + + case vec_promote_demote: + return fp ? vector_tune_param->rvv_stmt_costs_table->vec_fp->cost (x, + mode) + : vector_tune_param->rvv_stmt_costs_table->vec_int->cost (x, + mode); + + case vec_construct: + elements = estimated_poly_value (TYPE_VECTOR_SUBPARTS (vectype)); + return elements / 2 + 1; + + default: + gcc_unreachable (); + } +} + /* Return true if a shift-amount matches the trailing cleared bits on a bitmask. */ @@ -6902,6 +7187,13 @@ riscv_shamt_matches_mask_p (int shamt, HOST_WIDE_INT mask) return shamt == ctz_hwi (mask); } +/* Implement TARGET_VECTORIZE_CREATE_COSTS. */ +vector_costs * +riscv_vectorize_create_costs (vec_info *vinfo, bool costing_for_scalar) +{ + return new riscv_vector_costs (vinfo, costing_for_scalar); +} + /* Initialize the GCC target structure. */ #undef TARGET_ASM_ALIGNED_HI_OP #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t" @@ -7144,6 +7436,30 @@ riscv_shamt_matches_mask_p (int shamt, HOST_WIDE_INT mask) #undef TARGET_VERIFY_TYPE_CONTEXT #define TARGET_VERIFY_TYPE_CONTEXT riscv_verify_type_context +#undef TARGET_ESTIMATED_POLY_VALUE +#define TARGET_ESTIMATED_POLY_VALUE riscv_estimated_poly_value + +#undef TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST +#define TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST riscv_builtin_vectorization_cost + +#undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE +#define TARGET_VECTORIZE_PREFERRED_SIMD_MODE riscv_preferred_simd_mode + +#undef TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES +#define TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES riscv_autovectorize_vector_modes + +#undef TARGET_VECTORIZE_GET_MASK_MODE +#define TARGET_VECTORIZE_GET_MASK_MODE riscv_get_mask_mode + +#undef TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE +#define TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE riscv_empty_mask_is_expensive + +#undef TARGET_VECTORIZE_LOOP_LEN_OVERRIDE_MASK +#define TARGET_VECTORIZE_LOOP_LEN_OVERRIDE_MASK riscv_loop_len_override_mask + +#undef TARGET_VECTORIZE_CREATE_COSTS +#define TARGET_VECTORIZE_CREATE_COSTS riscv_vectorize_create_costs + #undef TARGET_VECTOR_ALIGNMENT #define TARGET_VECTOR_ALIGNMENT riscv_vector_alignment
Comments
On Mon, Mar 6, 2023 at 4:16 AM Michael Collison <collison@rivosinc.com> wrote: > > This patch adds support for registering target hooks for basic > autovectorization support as well as basic tuning information for the > vector extension. Btw, during the state tuning isn't established or autovect support being limited I would suggest to make the costing hooks reject all vectorization and thus vectorize with -fno-vect-cost-model only (that's what the basic vect.exp testsuite uses). That allows collaborative development on trunk while not surprising users with not profitable vectorization. I agree that loads and stores are the first priority for any autovect attempts because there you learn about the details and you get pushed on the right track. Richard. > gcc/ChangeLog: > > 2023-03-02 Michael Collison <collison@rivosinc.com> > Juzhe Zhong <juzhe.zhong@rivai.ai> > > * config/riscv/riscv-cores.def (RISCV_TUNE): > Add VECTOR_TUNE_INFO parameter and > * common/config/riscv/riscv-common.cc (RISCV_TUNE): > Add VECTOR_TUNE_INFO parameter. > * config/riscv/riscv.cc (riscv_vector_tune_param): > New struct for vector tuning information. > (riscv_tune_info): add vector_tune_param. > (vector_tune_param): New static variable. > (riscv_vectorization_factor): New variable. > (generic_rvv_insn_scale_table): New struct. > (generic_rvv_stmt_scale_table): New struct. > (generic_rvv_insn_cost_table): New vector insn cost table. > (generic_rvv_stmt_cost_table): New vector statement > cost table. > (generic_rvv_tune_info): New rvv tuning table. > (RISCV_TUNE): Add VECTOR_TUNE_INFO parameter. > (riscv_rtx_costs): Return vector estimate if vector mode. > (riscv_option_override): Set vector_tune_param. > (riscv_option_override): Set riscv_vectorization_factor. > (riscv_estimated_poly_value): Implement > TARGET_ESTIMATED_POLY_VALUE. > (riscv_preferred_simd_mode): Implement > TARGET_VECTORIZE_PREFERRED_SIMD_MODE. > (riscv_autovectorize_vector_modes): Implement > TARGET_AUTOVECTORIZE_VECTOR_MODES. > (riscv_get_mask_mode): Implement > TARGET_VECTORIZE_GET_MASK_MODE. > (riscv_empty_mask_is_expensive): Implement > TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE. > (riscv_builtin_vectorization_cost): Implement > TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST. > (riscv_vectorize_create_costs): Implement > TARGET_VECTORIZE_CREATE_COSTS. > (TARGET_ESTIMATED_POLY_VALUE): Register target macro. > (TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST): Ditto. > (TARGET_VECTORIZE_PREFERRED_SIMD_MODE): Ditto. > (TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES): Ditto. > (TARGET_VECTORIZE_GET_MASK_MODE): Ditto. > (TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE): Ditto. > (TARGET_VECTORIZE_LOOP_LEN_OVERRIDE_MASK): Ditto. > (TARGET_VECTORIZE_CREATE_COSTS): Ditto > > --- > gcc/common/config/riscv/riscv-common.cc | 2 +- > gcc/config/riscv/riscv-cores.def | 14 +- > gcc/config/riscv/riscv.cc | 324 +++++++++++++++++++++++- > 3 files changed, 328 insertions(+), 12 deletions(-) > > diff --git a/gcc/common/config/riscv/riscv-common.cc > b/gcc/common/config/riscv/riscv-common.cc > index ebc1ed7d7e4..6b8d92af986 100644 > --- a/gcc/common/config/riscv/riscv-common.cc > +++ b/gcc/common/config/riscv/riscv-common.cc > @@ -246,7 +246,7 @@ static const riscv_cpu_info riscv_cpu_tables[] = > > static const char *riscv_tunes[] = > { > -#define RISCV_TUNE(TUNE_NAME, PIPELINE_MODEL, TUNE_INFO) \ > +#define RISCV_TUNE(TUNE_NAME, PIPELINE_MODEL, TUNE_INFO, > VECTOR_TUNE_INFO) \ > TUNE_NAME, > #include "../../../config/riscv/riscv-cores.def" > NULL > diff --git a/gcc/config/riscv/riscv-cores.def > b/gcc/config/riscv/riscv-cores.def > index 2a834cae21d..4feb0366222 100644 > --- a/gcc/config/riscv/riscv-cores.def > +++ b/gcc/config/riscv/riscv-cores.def > @@ -30,15 +30,15 @@ > identifier, reference to riscv.cc. */ > > #ifndef RISCV_TUNE > -#define RISCV_TUNE(TUNE_NAME, PIPELINE_MODEL, TUNE_INFO) > +#define RISCV_TUNE(TUNE_NAME, PIPELINE_MODEL, TUNE_INFO, VECTOR_TUNE_INFO) > #endif > > -RISCV_TUNE("rocket", generic, rocket_tune_info) > -RISCV_TUNE("sifive-3-series", generic, rocket_tune_info) > -RISCV_TUNE("sifive-5-series", generic, rocket_tune_info) > -RISCV_TUNE("sifive-7-series", sifive_7, sifive_7_tune_info) > -RISCV_TUNE("thead-c906", generic, thead_c906_tune_info) > -RISCV_TUNE("size", generic, optimize_size_tune_info) > +RISCV_TUNE("rocket", generic, rocket_tune_info, generic_rvv_tune_info) > +RISCV_TUNE("sifive-3-series", generic, rocket_tune_info, > generic_rvv_tune_info) > +RISCV_TUNE("sifive-5-series", generic, rocket_tune_info, > generic_rvv_tune_info) > +RISCV_TUNE("sifive-7-series", sifive_7, sifive_7_tune_info, > generic_rvv_tune_info) > +RISCV_TUNE("thead-c906", generic, thead_c906_tune_info, > generic_rvv_tune_info) > +RISCV_TUNE("size", generic, optimize_size_tune_info, generic_rvv_tune_info) > > #undef RISCV_TUNE > > diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc > index befb9b498b7..44659062070 100644 > --- a/gcc/config/riscv/riscv.cc > +++ b/gcc/config/riscv/riscv.cc > @@ -60,6 +60,16 @@ along with GCC; see the file COPYING3. If not see > #include "opts.h" > #include "tm-constrs.h" > #include "rtl-iter.h" > +#include "gimple.h" > +#include "cfghooks.h" > +#include "cfgloop.h" > +#include "cfgrtl.h" > +#include "sel-sched.h" > +#include "fold-const.h" > +#include "gimple-iterator.h" > +#include "gimple-expr.h" > +#include "tree-vectorizer.h" > +#include "riscv-vector-cost.h" > > /* This file should be included last. */ > #include "target-def.h" > @@ -238,6 +248,12 @@ struct riscv_tune_param > bool slow_unaligned_access; > }; > > +/* Cost for vector insn classes. */ > +struct riscv_vector_tune_param { > + const vector_insn_cost_table* rvv_insn_costs_table; > + const vector_stmt_cost_table* rvv_stmt_costs_table; > +}; > + > /* Information about one micro-arch we know about. */ > struct riscv_tune_info { > /* This micro-arch canonical name. */ > @@ -248,6 +264,9 @@ struct riscv_tune_info { > > /* Tuning parameters for this micro-arch. */ > const struct riscv_tune_param *tune_param; > + > + /* Tuning vector parameters for this micro-arch. */ > + const struct riscv_vector_tune_param *vector_tune_param; > }; > > /* Global variables for machine-dependent things. */ > @@ -266,6 +285,9 @@ static int epilogue_cfa_sp_offset; > /* Which tuning parameters to use. */ > static const struct riscv_tune_param *tune_param; > > +/* Which vector tuning parameters to use. */ > +static const struct riscv_vector_tune_param *vector_tune_param; > + > /* Which automaton to use for tuning. */ > enum riscv_microarchitecture_type riscv_microarchitecture; > > @@ -275,6 +297,9 @@ poly_uint16 riscv_vector_chunks; > /* The number of bytes in a vector chunk. */ > unsigned riscv_bytes_per_vector_chunk; > > +/* Prefer vf for auto-vectorizer. */ > +unsigned riscv_vectorization_factor; > + > /* Index R is the smallest register class that contains register R. */ > const enum reg_class riscv_regno_to_class[FIRST_PSEUDO_REGISTER] = { > GR_REGS, GR_REGS, GR_REGS, GR_REGS, > @@ -367,6 +392,47 @@ static const struct riscv_tune_param > optimize_size_tune_info = { > false, /* slow_unaligned_access */ > }; > > +static const vector_insn_scale_table generic_rvv_insn_scale_table = { > + 4, /* load */ > + 1, /* store */ > + 1, /* alu */ > + 1, /* mult */ > + 1, /* movi */ > + 1, /* dup */ > + 1, /* extract */ > + 1, /* if_then_else */ > +}; > + > +static const vector_stmt_scale_table generic_rvv_stmt_scale_table = { > + 1, /* scalar_int_stmt_cost */ > + 1, /* scalar_fp_stmt_cost */ > + 1, /* scalar_load_cost */ > + 1, /* scalar_store_cost */ > + 1, /* vec_int_stmt_cost */ > + 1, /* vec_fp_stmt_cost */ > + 1, /* vec_permute_cost */ > + 1, /* vec_to_scalar_cost */ > + 1, /* scalar_to_vec_cost */ > + 1, /* vec_align_load_cost */ > + 1, /* vec_unalign_load_cost */ > + 1, /* vec_unalign_store_cost */ > + 1, /* vec_store_cost */ > + 1, /* cond_taken_branch_cost */ > + 1 /* cond_not_taken_branch_cost */ > +}; > + > +static const vector_insn_cost_table* generic_rvv_insn_cost_table = > + new vector_insn_cost_table (&generic_rvv_insn_scale_table); > + > +static const vector_stmt_cost_table* generic_rvv_stmt_cost_table = > + new vector_stmt_cost_table (&generic_rvv_stmt_scale_table); > + > +/* Costs to use when optimizing for riscv vector. */ > +static const struct riscv_vector_tune_param generic_rvv_tune_info = { > + generic_rvv_insn_cost_table, > + generic_rvv_stmt_cost_table > +}; > + > static tree riscv_handle_fndecl_attribute (tree *, tree, tree, int, > bool *); > static tree riscv_handle_type_attribute (tree *, tree, tree, int, bool *); > > @@ -403,8 +469,8 @@ static const unsigned gpr_save_reg_order[] = { > > /* A table describing all the processors GCC knows about. */ > static const struct riscv_tune_info riscv_tune_info_table[] = { > -#define RISCV_TUNE(TUNE_NAME, PIPELINE_MODEL, TUNE_INFO) \ > - { TUNE_NAME, PIPELINE_MODEL, & TUNE_INFO}, > +#define RISCV_TUNE(TUNE_NAME, PIPELINE_MODEL, TUNE_INFO, > VECTOR_TUNE_INFO) \ > + { TUNE_NAME, PIPELINE_MODEL, & TUNE_INFO, &VECTOR_TUNE_INFO}, > #include "riscv-cores.def" > }; > > @@ -2237,8 +2303,8 @@ riscv_rtx_costs (rtx x, machine_mode mode, int > outer_code, int opno ATTRIBUTE_UN > Cost Model need to be well analyzed and supported in the future. */ > if (riscv_v_ext_vector_mode_p (mode)) > { > - *total = COSTS_N_INSNS (1); > - return true; > + return vector_tune_param->rvv_insn_costs_table->get_cost (x, > mode, total, > + speed); > } > > bool float_mode_p = FLOAT_MODE_P (mode); > @@ -6080,6 +6146,7 @@ riscv_option_override (void) > RISCV_TUNE_STRING_DEFAULT)); > riscv_microarchitecture = cpu->microarchitecture; > tune_param = optimize_size ? &optimize_size_tune_info : cpu->tune_param; > + vector_tune_param = cpu->vector_tune_param; > > /* Use -mtune's setting for slow_unaligned_access, even when optimizing > for size. For architectures that trap and emulate unaligned > accesses, > @@ -6199,6 +6266,10 @@ riscv_option_override (void) > > /* Convert -march to a chunks count. */ > riscv_vector_chunks = riscv_convert_vector_bits (); > + > + if (TARGET_VECTOR) > + riscv_vectorization_factor = riscv_vector_lmul; > + > } > > /* Implement TARGET_CONDITIONAL_REGISTER_USAGE. */ > @@ -6893,6 +6964,220 @@ riscv_dwarf_poly_indeterminate_value (unsigned > int i, unsigned int *factor, > return RISCV_DWARF_VLENB; > } > > +/* Implement TARGET_ESTIMATED_POLY_VALUE. > + Look into the tuning structure for an estimate. > + KIND specifies the type of requested estimate: min, max or likely. > + For cores with a known RVV width all three estimates are the same. > + For generic RVV tuning we want to distinguish the maximum estimate from > + the minimum and likely ones. > + The likely estimate is the same as the minimum in that case to give a > + conservative behavior of auto-vectorizing with RVV when it is a win > + even for 128-bit RVV. > + When RVV width information is available VAL.coeffs[1] is multiplied by > + the number of VQ chunks over the initial Advanced SIMD 128 bits. */ > + > +static HOST_WIDE_INT > +riscv_estimated_poly_value (poly_int64 val, > + poly_value_estimate_kind kind = POLY_VALUE_LIKELY) > +{ > + unsigned int width_source = BITS_PER_RISCV_VECTOR.is_constant () > + ? (unsigned int) BITS_PER_RISCV_VECTOR.to_constant () > + : (unsigned int) RVV_SCALABLE; > + > + /* If there is no core-specific information then the minimum and likely > + values are based on 128-bit vectors and the maximum is based on > + the architectural maximum of 2048 bits. */ > + if (width_source == RVV_SCALABLE) > + switch (kind) > + { > + case POLY_VALUE_MIN: > + case POLY_VALUE_LIKELY: > + return val.coeffs[0]; > + > + case POLY_VALUE_MAX: > + return val.coeffs[0] + val.coeffs[1] * 15; > + } > + > + /* Allow BITS_PER_RISCV_VECTOR to be a bitmask of different VL, > treating the > + lowest as likely. This could be made more general if future -mtune > + options need it to be. */ > + if (kind == POLY_VALUE_MAX) > + width_source = 1 << floor_log2 (width_source); > + else > + width_source = least_bit_hwi (width_source); > + > + /* If the core provides width information, use that. */ > + HOST_WIDE_INT over_128 = width_source - 128; > + return val.coeffs[0] + val.coeffs[1] * over_128 / 128; > +} > + > +/* Implement TARGET_VECTORIZE_PREFERRED_SIMD_MODE. */ > + > +static machine_mode > +riscv_preferred_simd_mode (scalar_mode mode) > +{ > + machine_mode vmode = > + riscv_vector::riscv_vector_preferred_simd_mode (mode, > + riscv_vectorization_factor); > + if (VECTOR_MODE_P (vmode)) > + return vmode; > + > + return word_mode; > +} > + > +/* Implement TARGET_AUTOVECTORIZE_VECTOR_MODES for RVV. */ > +static unsigned int > +riscv_autovectorize_vector_modes (vector_modes *modes, bool) > +{ > + if (!TARGET_VECTOR) > + return 0; > + > + if (riscv_vectorization_factor == RVV_LMUL1) > + { > + modes->safe_push (VNx16QImode); > + modes->safe_push (VNx8QImode); > + modes->safe_push (VNx4QImode); > + modes->safe_push (VNx2QImode); > + } > + else if (riscv_vectorization_factor == RVV_LMUL2) > + { > + modes->safe_push (VNx32QImode); > + modes->safe_push (VNx16QImode); > + modes->safe_push (VNx8QImode); > + modes->safe_push (VNx4QImode); > + } > + else if (riscv_vectorization_factor == RVV_LMUL4) > + { > + modes->safe_push (VNx64QImode); > + modes->safe_push (VNx32QImode); > + modes->safe_push (VNx16QImode); > + modes->safe_push (VNx8QImode); > + } > + else > + { > + modes->safe_push (VNx64QImode); > + modes->safe_push (VNx32QImode); > + modes->safe_push (VNx16QImode); > + } > + > + return 0; > +} > + > +/* Implement TARGET_VECTORIZE_GET_MASK_MODE. */ > + > +static opt_machine_mode > +riscv_get_mask_mode (machine_mode mode) > +{ > + machine_mode mask_mode = VOIDmode; > + if (TARGET_VECTOR > + && riscv_vector::riscv_vector_get_mask_mode (mode).exists > (&mask_mode)) > + return mask_mode; > + > + return default_get_mask_mode (mode); > +} > + > +/* Implement TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE. Assume for now that > + it isn't worth branching around empty masked ops (including masked > + stores). */ > + > +static bool > +riscv_empty_mask_is_expensive (unsigned) > +{ > + return false; > +} > + > +/* Implement targetm.vectorize.builtin_vectorization_cost. */ > +int > +riscv_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost, > + tree vectype, int misalign ATTRIBUTE_UNUSED) > +{ > + unsigned elements; > + bool fp = false; > + rtx x = NULL_RTX; > + machine_mode mode = VOIDmode; > + > + if (vectype != NULL) > + { > + fp = FLOAT_TYPE_P (vectype); > + mode = TYPE_MODE (vectype); > + } > + > + switch (type_of_cost) > + { > + case scalar_stmt: > + return fp ? > vector_tune_param->rvv_stmt_costs_table->scalar_fp->cost (x, > + mode) > + : vector_tune_param->rvv_stmt_costs_table->scalar_int->cost (x, > + mode); > + > + case scalar_load: > + return vector_tune_param->rvv_stmt_costs_table->scalar_load->cost (x, > + mode); > + > + case scalar_store: > + return > vector_tune_param->rvv_stmt_costs_table->scalar_store->cost (x, > + mode); > + > + case vector_stmt: > + return fp ? vector_tune_param->rvv_stmt_costs_table->vec_fp->cost (x, > + mode) > + : vector_tune_param->rvv_stmt_costs_table->vec_int->cost (x, > + mode); > + > + case vector_load: > + return > vector_tune_param->rvv_stmt_costs_table->vec_align_load->cost (x, > + mode); > + > + case vector_store: > + return vector_tune_param->rvv_stmt_costs_table->vec_store->cost > (x, mode); > + > + case vec_to_scalar: > + return > vector_tune_param->rvv_stmt_costs_table->vec_to_scalar->cost (x, > + mode); > + > + case scalar_to_vec: > + return > vector_tune_param->rvv_stmt_costs_table->scalar_to_vec->cost (x, > + mode); > + > + case unaligned_load: > + case vector_gather_load: > + return > vector_tune_param->rvv_stmt_costs_table->vec_unalign_load->cost (x, > + mode); > + > + case unaligned_store: > + case vector_scatter_store: > + return > vector_tune_param->rvv_stmt_costs_table->vec_unalign_store->cost ( > + x, > + mode); > + > + case cond_branch_taken: > + return > vector_tune_param->rvv_stmt_costs_table->cond_taken_branch->cost ( > + x, > + mode); > + > + case cond_branch_not_taken: > + return vector_tune_param->rvv_stmt_costs_table->cond_not_taken_branch > + ->cost (x, mode); > + > + case vec_perm: > + return vector_tune_param->rvv_stmt_costs_table->vec_permute->cost (x, > + mode); > + > + case vec_promote_demote: > + return fp ? vector_tune_param->rvv_stmt_costs_table->vec_fp->cost (x, > + mode) > + : vector_tune_param->rvv_stmt_costs_table->vec_int->cost (x, > + mode); > + > + case vec_construct: > + elements = estimated_poly_value (TYPE_VECTOR_SUBPARTS (vectype)); > + return elements / 2 + 1; > + > + default: > + gcc_unreachable (); > + } > +} > + > /* Return true if a shift-amount matches the trailing cleared bits on > a bitmask. */ > > @@ -6902,6 +7187,13 @@ riscv_shamt_matches_mask_p (int shamt, > HOST_WIDE_INT mask) > return shamt == ctz_hwi (mask); > } > > +/* Implement TARGET_VECTORIZE_CREATE_COSTS. */ > +vector_costs * > +riscv_vectorize_create_costs (vec_info *vinfo, bool costing_for_scalar) > +{ > + return new riscv_vector_costs (vinfo, costing_for_scalar); > +} > + > /* Initialize the GCC target structure. */ > #undef TARGET_ASM_ALIGNED_HI_OP > #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t" > @@ -7144,6 +7436,30 @@ riscv_shamt_matches_mask_p (int shamt, > HOST_WIDE_INT mask) > #undef TARGET_VERIFY_TYPE_CONTEXT > #define TARGET_VERIFY_TYPE_CONTEXT riscv_verify_type_context > > +#undef TARGET_ESTIMATED_POLY_VALUE > +#define TARGET_ESTIMATED_POLY_VALUE riscv_estimated_poly_value > + > +#undef TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST > +#define TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST > riscv_builtin_vectorization_cost > + > +#undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE > +#define TARGET_VECTORIZE_PREFERRED_SIMD_MODE riscv_preferred_simd_mode > + > +#undef TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES > +#define TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES > riscv_autovectorize_vector_modes > + > +#undef TARGET_VECTORIZE_GET_MASK_MODE > +#define TARGET_VECTORIZE_GET_MASK_MODE riscv_get_mask_mode > + > +#undef TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE > +#define TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE > riscv_empty_mask_is_expensive > + > +#undef TARGET_VECTORIZE_LOOP_LEN_OVERRIDE_MASK > +#define TARGET_VECTORIZE_LOOP_LEN_OVERRIDE_MASK > riscv_loop_len_override_mask > + > +#undef TARGET_VECTORIZE_CREATE_COSTS > +#define TARGET_VECTORIZE_CREATE_COSTS riscv_vectorize_create_costs > + > #undef TARGET_VECTOR_ALIGNMENT > #define TARGET_VECTOR_ALIGNMENT riscv_vector_alignment > > -- > 2.34.1 > >
diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc index ebc1ed7d7e4..6b8d92af986 100644 --- a/gcc/common/config/riscv/riscv-common.cc +++ b/gcc/common/config/riscv/riscv-common.cc @@ -246,7 +246,7 @@ static const riscv_cpu_info riscv_cpu_tables[] = static const char *riscv_tunes[] = { -#define RISCV_TUNE(TUNE_NAME, PIPELINE_MODEL, TUNE_INFO) \ +#define RISCV_TUNE(TUNE_NAME, PIPELINE_MODEL, TUNE_INFO, VECTOR_TUNE_INFO) \ TUNE_NAME, #include "../../../config/riscv/riscv-cores.def" NULL diff --git a/gcc/config/riscv/riscv-cores.def b/gcc/config/riscv/riscv-cores.def index 2a834cae21d..4feb0366222 100644 --- a/gcc/config/riscv/riscv-cores.def +++ b/gcc/config/riscv/riscv-cores.def @@ -30,15 +30,15 @@ identifier, reference to riscv.cc. */ #ifndef RISCV_TUNE -#define RISCV_TUNE(TUNE_NAME, PIPELINE_MODEL, TUNE_INFO) +#define RISCV_TUNE(TUNE_NAME, PIPELINE_MODEL, TUNE_INFO, VECTOR_TUNE_INFO) #endif -RISCV_TUNE("rocket", generic, rocket_tune_info) -RISCV_TUNE("sifive-3-series", generic, rocket_tune_info) -RISCV_TUNE("sifive-5-series", generic, rocket_tune_info) -RISCV_TUNE("sifive-7-series", sifive_7, sifive_7_tune_info) -RISCV_TUNE("thead-c906", generic, thead_c906_tune_info) -RISCV_TUNE("size", generic, optimize_size_tune_info) +RISCV_TUNE("rocket", generic, rocket_tune_info, generic_rvv_tune_info) +RISCV_TUNE("sifive-3-series", generic, rocket_tune_info, generic_rvv_tune_info) +RISCV_TUNE("sifive-5-series", generic, rocket_tune_info, generic_rvv_tune_info) +RISCV_TUNE("sifive-7-series", sifive_7, sifive_7_tune_info, generic_rvv_tune_info) +RISCV_TUNE("thead-c906", generic, thead_c906_tune_info, generic_rvv_tune_info) +RISCV_TUNE("size", generic, optimize_size_tune_info, generic_rvv_tune_info) #undef RISCV_TUNE diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index befb9b498b7..44659062070 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -60,6 +60,16 @@ along with GCC; see the file COPYING3. If not see #include "opts.h" #include "tm-constrs.h" #include "rtl-iter.h" +#include "gimple.h" +#include "cfghooks.h" +#include "cfgloop.h" +#include "cfgrtl.h" +#include "sel-sched.h" +#include "fold-const.h" +#include "gimple-iterator.h" +#include "gimple-expr.h" +#include "tree-vectorizer.h" +#include "riscv-vector-cost.h" /* This file should be included last. */ #include "target-def.h" @@ -238,6 +248,12 @@ struct riscv_tune_param bool slow_unaligned_access; }; +/* Cost for vector insn classes. */ +struct riscv_vector_tune_param { + const vector_insn_cost_table* rvv_insn_costs_table; + const vector_stmt_cost_table* rvv_stmt_costs_table; +}; + /* Information about one micro-arch we know about. */ struct riscv_tune_info { /* This micro-arch canonical name. */ @@ -248,6 +264,9 @@ struct riscv_tune_info { /* Tuning parameters for this micro-arch. */ const struct riscv_tune_param *tune_param; + + /* Tuning vector parameters for this micro-arch. */ + const struct riscv_vector_tune_param *vector_tune_param; }; /* Global variables for machine-dependent things. */ @@ -266,6 +285,9 @@ static int epilogue_cfa_sp_offset; /* Which tuning parameters to use. */ static const struct riscv_tune_param *tune_param; +/* Which vector tuning parameters to use. */ +static const struct riscv_vector_tune_param *vector_tune_param; + /* Which automaton to use for tuning. */ enum riscv_microarchitecture_type riscv_microarchitecture; @@ -275,6 +297,9 @@ poly_uint16 riscv_vector_chunks; /* The number of bytes in a vector chunk. */ unsigned riscv_bytes_per_vector_chunk; +/* Prefer vf for auto-vectorizer. */ +unsigned riscv_vectorization_factor; + /* Index R is the smallest register class that contains register R. */ const enum reg_class riscv_regno_to_class[FIRST_PSEUDO_REGISTER] = { GR_REGS, GR_REGS, GR_REGS, GR_REGS, @@ -367,6 +392,47 @@ static const struct riscv_tune_param optimize_size_tune_info = { false, /* slow_unaligned_access */ }; +static const vector_insn_scale_table generic_rvv_insn_scale_table = { + 4, /* load */ + 1, /* store */ + 1, /* alu */ + 1, /* mult */ + 1, /* movi */ + 1, /* dup */ + 1, /* extract */ + 1, /* if_then_else */ +}; + +static const vector_stmt_scale_table generic_rvv_stmt_scale_table = { + 1, /* scalar_int_stmt_cost */ + 1, /* scalar_fp_stmt_cost */ + 1, /* scalar_load_cost */ + 1, /* scalar_store_cost */ + 1, /* vec_int_stmt_cost */ + 1, /* vec_fp_stmt_cost */ + 1, /* vec_permute_cost */ + 1, /* vec_to_scalar_cost */ + 1, /* scalar_to_vec_cost */ + 1, /* vec_align_load_cost */ + 1, /* vec_unalign_load_cost */ + 1, /* vec_unalign_store_cost */ + 1, /* vec_store_cost */ + 1, /* cond_taken_branch_cost */ + 1 /* cond_not_taken_branch_cost */ +}; + +static const vector_insn_cost_table* generic_rvv_insn_cost_table = + new vector_insn_cost_table (&generic_rvv_insn_scale_table); + +static const vector_stmt_cost_table* generic_rvv_stmt_cost_table = + new vector_stmt_cost_table (&generic_rvv_stmt_scale_table); + +/* Costs to use when optimizing for riscv vector. */ +static const struct riscv_vector_tune_param generic_rvv_tune_info = { + generic_rvv_insn_cost_table, + generic_rvv_stmt_cost_table +}; + static tree riscv_handle_fndecl_attribute (tree *, tree, tree, int, bool *);