On Tue, Jul 22, 2025 at 12:50 PM Andrew Pinski <pins...@gmail.com> wrote: > > On Thu, Jul 17, 2025 at 10:35 PM <soum...@nvidia.com> wrote: > > > > From: Soumya AR <soum...@nvidia.com> > > > > This patch adds functionality to dump AArch64 CPU tuning parameters to a > > JSON > > file. The new '-fdump-tuning-model=' flag allows users to export the current > > tuning model configuration to a JSON file. > > > > This patch was bootstrapped and regtested on aarch64-linux-gnu, no > > regression. > > > > Signed-off-by: Soumya AR <soum...@nvidia.com> > > > > gcc/ChangeLog: > > > > * config.gcc: Add aarch64-json-tunings-printer.o. > > * config/aarch64/aarch64.cc (aarch64_override_options_internal): > > Invoke > > aarch64_print_tune_params if -fdump-tuning-model= is specified. > > * config/aarch64/aarch64.opt: New option. > > * config/aarch64/t-aarch64 (aarch64-json-tunings-printer.o): New > > define. > > * config/aarch64/aarch64-json-tunings-printer.cc: New file. > > * config/aarch64/aarch64-json-tunings-printer.h: New file. > > --- > > gcc/config.gcc | 2 +- > > .../aarch64/aarch64-json-tunings-printer.cc | 653 ++++++++++++++++++ > > .../aarch64/aarch64-json-tunings-printer.h | 28 + > > gcc/config/aarch64/aarch64.cc | 4 + > > gcc/config/aarch64/aarch64.opt | 4 + > > gcc/config/aarch64/t-aarch64 | 9 + > > 6 files changed, 699 insertions(+), 1 deletion(-) > > create mode 100644 gcc/config/aarch64/aarch64-json-tunings-printer.cc > > create mode 100644 gcc/config/aarch64/aarch64-json-tunings-printer.h > > > > diff --git a/gcc/config.gcc b/gcc/config.gcc > > index 8ed111392bb..11660e699bd 100644 > > --- a/gcc/config.gcc > > +++ b/gcc/config.gcc > > @@ -351,7 +351,7 @@ aarch64*-*-*) > > c_target_objs="aarch64-c.o" > > cxx_target_objs="aarch64-c.o" > > d_target_objs="aarch64-d.o" > > - extra_objs="aarch64-builtins.o aarch-common.o > > aarch64-elf-metadata.o aarch64-sve-builtins.o aarch64-sve-builtins-shapes.o > > aarch64-sve-builtins-base.o aarch64-sve-builtins-sve2.o > > aarch64-sve-builtins-sme.o cortex-a57-fma-steering.o aarch64-speculation.o > > aarch-bti-insert.o aarch64-cc-fusion.o aarch64-early-ra.o > > aarch64-ldp-fusion.o" > > + extra_objs="aarch64-builtins.o aarch-common.o > > aarch64-elf-metadata.o aarch64-sve-builtins.o aarch64-sve-builtins-shapes.o > > aarch64-sve-builtins-base.o aarch64-sve-builtins-sve2.o > > aarch64-sve-builtins-sme.o cortex-a57-fma-steering.o aarch64-speculation.o > > aarch-bti-insert.o aarch64-cc-fusion.o aarch64-early-ra.o > > aarch64-ldp-fusion.o aarch64-json-tunings-printer.o" > > target_gtfiles="\$(srcdir)/config/aarch64/aarch64-protos.h > > \$(srcdir)/config/aarch64/aarch64-builtins.h > > \$(srcdir)/config/aarch64/aarch64-builtins.cc > > \$(srcdir)/config/aarch64/aarch64-sve-builtins.h > > \$(srcdir)/config/aarch64/aarch64-sve-builtins.cc" > > You don't need to change this for this patch but these 2 lines seem > really long and could be split up into a few lines. > > > > target_has_targetm_common=yes > > ;; > > diff --git a/gcc/config/aarch64/aarch64-json-tunings-printer.cc > > b/gcc/config/aarch64/aarch64-json-tunings-printer.cc > > new file mode 100644 > > index 00000000000..926829886a4 > > --- /dev/null > > +++ b/gcc/config/aarch64/aarch64-json-tunings-printer.cc > > @@ -0,0 +1,653 @@ > > +/* Routines to print the AArch64 tuning parameters to a JSON file. > > + Copyright The GNU Toolchain Authors. > > + > > + This file is part of GCC. > > + > > + GCC is free software; you can redistribute it and/or modify it > > + under the terms of the GNU General Public License as published by > > + the Free Software Foundation; either version 3, or (at your option) > > + any later version. > > + > > + GCC is distributed in the hope that it will be useful, but > > + WITHOUT ANY WARRANTY; without even the implied warranty of > > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > > + General Public License for more details. > > + > > + You should have received a copy of the GNU General Public License > > + along with GCC; see the file COPYING3. If not see > > + <http://www.gnu.org/licenses/>. */ > > + > > +#define INCLUDE_TYPE_TRAITS > > +#include "config.h" > > +#include "system.h" > > +#include "coretypes.h" > > +#include "pretty-print.h" > > +#include "tm.h" > > +#include "diagnostic-core.h" > > +#include "aarch64-json-tunings-printer.h" > > +#include "aarch64-protos.h" > > +#include "config/arm/aarch-common-protos.h" > > +#include "json.h" > > + > > +#define SERIALIZE_INTEGER_FIELD(obj, key, member) > > \ > > + (obj)->set_integer ((key), (member)) > > + > > +#define SERIALIZE_BOOLEAN_FIELD(obj, key, member) > > \ > > + (obj)->set_bool ((key), (member)) > > + > > +#define SERIALIZE_STRING_FIELD(obj, key, member) > > \ > > + (obj)->set_string ((key), (member)) > > + > > +#define SERIALIZE_OBJECT(obj, key, member, serialize_func) > > \ > > + { > > \ > > + auto field_obj = serialize_object_helper ((member), (serialize_func)); > > \ > > + if (field_obj) > > \ > > + (obj)->set ((key), std::move (field_obj)); > > \ > > + } > > + > > +#define SERIALIZE_ARRAY_FIELD(obj, key, member, size, serialize_func) > > \ > > + { > > \ > > + auto field_array = std::make_unique<json::array> (); > > \ > > + for (int i = 0; i < (size); ++i) > > \ > > + { > > \ > > + auto element_obj = serialize_func ((member)[i]); > > \ > > + if (element_obj) > > \ > > + field_array->append (std::move (element_obj)); > > \ > > + } > > \ > > + (obj)->set ((key), std::move (field_array)); > > \ > > + } > > + > > +#define SERIALIZE_ENUM_FIELD(obj, key, member, mappings) > > \ > > + (obj)->set_string ((key), serialize_enum ((member), (mappings), > > \ > > + sizeof (mappings) > > \ > > + / sizeof (mappings[0]))) > > + > > +/* Serialize JSON object from non-pointer members. */ > > +template <typename T> > > +static typename std::enable_if<!std::is_pointer<T>::value, > > + std::unique_ptr<json::object>>::type > > +serialize_object_helper ( > > + const T &member, std::unique_ptr<json::object> (*serialize_func) (const > > T &)) > > Maybe you could do: > ``` > template<typename T> > using serialize_func_type = std::unique_ptr<json::object> > (*serialize_func) (const typename std::remove_pointer<T>::type &); > > serialize_object_helper ( > const T &member, serialize_func_type<T> serialize_func) > ``` > Since std::remove_pointer<T>::type will T if T is not a pointer. > > > > +{ > > + return serialize_func (member); > > +} > > + > > +/* Serialize JSON object from pointer members. */ > > +template <typename T> > > +static typename std::enable_if<std::is_pointer<T>::value, > > + std::unique_ptr<json::object>>::type > > +serialize_object_helper (const T &member, > > + std::unique_ptr<json::object> (*serialize_func) ( > > + const typename std::remove_pointer<T>::type &)) > > And then here just do : > ``` > serialize_object_helper ( > const T &member, serialize_func_type<T> serialize_func) > ``` > > A little less writing and in my mind easier to understand what the > type of serialize_func is. > > > +{ > > + if (member) > > + return serialize_func (*member); > > + return std::make_unique<json::object> (); > > +} > > + > > +/* Mapping structure for enum-to-string conversion. */ > > +template <typename EnumType> struct enum_mapping > > +{ > > + const char *name; > > + EnumType value; > > +}; > > + > > +static const enum_mapping<tune_params::aarch64_autoprefetch_model> > > + autoprefetcher_model_mappings[] > > + = {{"AUTOPREFETCHER_OFF", tune_params::AUTOPREFETCHER_OFF}, > > + {"AUTOPREFETCHER_WEAK", tune_params::AUTOPREFETCHER_WEAK}, > > + {"AUTOPREFETCHER_STRONG", tune_params::AUTOPREFETCHER_STRONG}}; > > + > > +static const enum_mapping<aarch64_ldp_stp_policy> > > ldp_policy_model_mappings[] > > + = {{"AARCH64_LDP_STP_POLICY_DEFAULT", AARCH64_LDP_STP_POLICY_DEFAULT}, > > + {"AARCH64_LDP_STP_POLICY_ALIGNED", AARCH64_LDP_STP_POLICY_ALIGNED}, > > + {"AARCH64_LDP_STP_POLICY_ALWAYS", AARCH64_LDP_STP_POLICY_ALWAYS}, > > + {"AARCH64_LDP_STP_POLICY_NEVER", AARCH64_LDP_STP_POLICY_NEVER}}; > > + > > +static const enum_mapping<aarch64_ldp_stp_policy> > > stp_policy_model_mappings[] > > + = {{"AARCH64_LDP_STP_POLICY_DEFAULT", AARCH64_LDP_STP_POLICY_DEFAULT}, > > + {"AARCH64_LDP_STP_POLICY_ALIGNED", AARCH64_LDP_STP_POLICY_ALIGNED}, > > + {"AARCH64_LDP_STP_POLICY_ALWAYS", AARCH64_LDP_STP_POLICY_ALWAYS}, > > + {"AARCH64_LDP_STP_POLICY_NEVER", AARCH64_LDP_STP_POLICY_NEVER}}; > > Is there a way to generate these structs automatically? maybe from a > quick awk script that parses the aarch64.opt file? Note I am not going > to hold this patchset up because of this though.
Oh I just noticed that part 6 of this patchset actually does that. So that is good news. Thanks, Andrew > > > + > > +/* Convert enum value to string using enum-to-string mappings. */ > > +template <typename EnumType> > > +static const char * > > +serialize_enum (EnumType enum_value, const enum_mapping<EnumType> > > *mappings, > > + size_t num_mappings) > > +{ > > + for (size_t i = 0; i < num_mappings; ++i) > > + if (enum_value == mappings[i].value) > > + return mappings[i].name; > > + return mappings[0].name; > > +} > > + > > +template <typename T> > > +static std::unique_ptr<json::object> > > +serialize_insn_extra_cost_alu (const T &alu) > > +{ > > + auto alu_obj = std::make_unique<json::object> (); > > + > > + SERIALIZE_INTEGER_FIELD (alu_obj, "arith", alu.arith); > > + SERIALIZE_INTEGER_FIELD (alu_obj, "logical", alu.logical); > > + SERIALIZE_INTEGER_FIELD (alu_obj, "shift", alu.shift); > > + SERIALIZE_INTEGER_FIELD (alu_obj, "shift_reg", alu.shift_reg); > > + SERIALIZE_INTEGER_FIELD (alu_obj, "arith_shift", alu.arith_shift); > > + SERIALIZE_INTEGER_FIELD (alu_obj, "arith_shift_reg", > > alu.arith_shift_reg); > > + SERIALIZE_INTEGER_FIELD (alu_obj, "log_shift", alu.log_shift); > > + SERIALIZE_INTEGER_FIELD (alu_obj, "log_shift_reg", alu.log_shift_reg); > > + SERIALIZE_INTEGER_FIELD (alu_obj, "extend", alu.extend); > > + SERIALIZE_INTEGER_FIELD (alu_obj, "extend_arith", alu.extend_arith); > > + SERIALIZE_INTEGER_FIELD (alu_obj, "bfi", alu.bfi); > > + SERIALIZE_INTEGER_FIELD (alu_obj, "bfx", alu.bfx); > > + SERIALIZE_INTEGER_FIELD (alu_obj, "clz", alu.clz); > > + SERIALIZE_INTEGER_FIELD (alu_obj, "rev", alu.rev); > > + SERIALIZE_INTEGER_FIELD (alu_obj, "non_exec", alu.non_exec); > > + SERIALIZE_BOOLEAN_FIELD (alu_obj, "non_exec_costs_exec", > > + alu.non_exec_costs_exec); > > Seems like this could be generated automatically too. Maybe place the > cpu_cost_table and related structs into its own header file and have a > simple parser for that. Or use defines to define the struct. > Again this is just an enhancement for the future to make sure the > above output and structures don't get out of sync'ed. > > The rest looks ok, and the same comment about generating automatically. > > Thanks, > Andrew Pinski > > > + > > + return alu_obj; > > +} > > + > > +template <typename T> > > +static std::unique_ptr<json::object> > > +serialize_insn_extra_cost_mult_element (const T &mult_element) > > +{ > > + auto mult_element_obj = std::make_unique<json::object> (); > > + > > + SERIALIZE_INTEGER_FIELD (mult_element_obj, "simple", > > mult_element.simple); > > + SERIALIZE_INTEGER_FIELD (mult_element_obj, "flag_setting", > > + mult_element.flag_setting); > > + SERIALIZE_INTEGER_FIELD (mult_element_obj, "extend", > > mult_element.extend); > > + SERIALIZE_INTEGER_FIELD (mult_element_obj, "add", mult_element.add); > > + SERIALIZE_INTEGER_FIELD (mult_element_obj, "extend_add", > > + mult_element.extend_add); > > + SERIALIZE_INTEGER_FIELD (mult_element_obj, "idiv", mult_element.idiv); > > + > > + return mult_element_obj; > > +} > > + > > +template <typename T> > > +static std::unique_ptr<json::object> > > +serialize_insn_extra_cost_ldst (const T &ldst) > > +{ > > + auto ldst_obj = std::make_unique<json::object> (); > > + > > + SERIALIZE_INTEGER_FIELD (ldst_obj, "load", ldst.load); > > + SERIALIZE_INTEGER_FIELD (ldst_obj, "load_sign_extend", > > ldst.load_sign_extend); > > + SERIALIZE_INTEGER_FIELD (ldst_obj, "ldrd", ldst.ldrd); > > + SERIALIZE_INTEGER_FIELD (ldst_obj, "ldm_1st", ldst.ldm_1st); > > + SERIALIZE_INTEGER_FIELD (ldst_obj, "ldm_regs_per_insn_1st", > > + ldst.ldm_regs_per_insn_1st); > > + SERIALIZE_INTEGER_FIELD (ldst_obj, "ldm_regs_per_insn_subsequent", > > + ldst.ldm_regs_per_insn_subsequent); > > + SERIALIZE_INTEGER_FIELD (ldst_obj, "loadf", ldst.loadf); > > + SERIALIZE_INTEGER_FIELD (ldst_obj, "loadd", ldst.loadd); > > + SERIALIZE_INTEGER_FIELD (ldst_obj, "load_unaligned", > > ldst.load_unaligned); > > + SERIALIZE_INTEGER_FIELD (ldst_obj, "store", ldst.store); > > + SERIALIZE_INTEGER_FIELD (ldst_obj, "strd", ldst.strd); > > + SERIALIZE_INTEGER_FIELD (ldst_obj, "stm_1st", ldst.stm_1st); > > + SERIALIZE_INTEGER_FIELD (ldst_obj, "stm_regs_per_insn_1st", > > + ldst.stm_regs_per_insn_1st); > > + SERIALIZE_INTEGER_FIELD (ldst_obj, "stm_regs_per_insn_subsequent", > > + ldst.stm_regs_per_insn_subsequent); > > + SERIALIZE_INTEGER_FIELD (ldst_obj, "storef", ldst.storef); > > + SERIALIZE_INTEGER_FIELD (ldst_obj, "stored", ldst.stored); > > + SERIALIZE_INTEGER_FIELD (ldst_obj, "store_unaligned", > > ldst.store_unaligned); > > + SERIALIZE_INTEGER_FIELD (ldst_obj, "loadv", ldst.loadv); > > + SERIALIZE_INTEGER_FIELD (ldst_obj, "storev", ldst.storev); > > + > > + return ldst_obj; > > +} > > + > > +template <typename T> > > +static std::unique_ptr<json::object> > > +serialize_insn_extra_cost_fp_element (const T &fp_element) > > +{ > > + auto fp_element_obj = std::make_unique<json::object> (); > > + > > + SERIALIZE_INTEGER_FIELD (fp_element_obj, "div", fp_element.div); > > + SERIALIZE_INTEGER_FIELD (fp_element_obj, "mult", fp_element.mult); > > + SERIALIZE_INTEGER_FIELD (fp_element_obj, "mult_addsub", > > + fp_element.mult_addsub); > > + SERIALIZE_INTEGER_FIELD (fp_element_obj, "fma", fp_element.fma); > > + SERIALIZE_INTEGER_FIELD (fp_element_obj, "addsub", fp_element.addsub); > > + SERIALIZE_INTEGER_FIELD (fp_element_obj, "fpconst", fp_element.fpconst); > > + SERIALIZE_INTEGER_FIELD (fp_element_obj, "neg", fp_element.neg); > > + SERIALIZE_INTEGER_FIELD (fp_element_obj, "compare", fp_element.compare); > > + SERIALIZE_INTEGER_FIELD (fp_element_obj, "widen", fp_element.widen); > > + SERIALIZE_INTEGER_FIELD (fp_element_obj, "narrow", fp_element.narrow); > > + SERIALIZE_INTEGER_FIELD (fp_element_obj, "toint", fp_element.toint); > > + SERIALIZE_INTEGER_FIELD (fp_element_obj, "fromint", fp_element.fromint); > > + SERIALIZE_INTEGER_FIELD (fp_element_obj, "roundint", > > fp_element.roundint); > > + > > + return fp_element_obj; > > +} > > + > > +template <typename T> > > +static std::unique_ptr<json::object> > > +serialize_insn_extra_cost_vect (const T &vect) > > +{ > > + auto vect_obj = std::make_unique<json::object> (); > > + > > + SERIALIZE_INTEGER_FIELD (vect_obj, "alu", vect.alu); > > + SERIALIZE_INTEGER_FIELD (vect_obj, "mult", vect.mult); > > + SERIALIZE_INTEGER_FIELD (vect_obj, "movi", vect.movi); > > + SERIALIZE_INTEGER_FIELD (vect_obj, "dup", vect.dup); > > + SERIALIZE_INTEGER_FIELD (vect_obj, "extract", vect.extract); > > + > > + return vect_obj; > > +} > > + > > +template <typename T> > > +static std::unique_ptr<json::object> > > +serialize_addr_cost_addr_scale_costs (const T &addr_scale_costs) > > +{ > > + auto addr_scale_costs_obj = std::make_unique<json::object> (); > > + > > + SERIALIZE_INTEGER_FIELD (addr_scale_costs_obj, "hi", > > addr_scale_costs.hi); > > + SERIALIZE_INTEGER_FIELD (addr_scale_costs_obj, "si", > > addr_scale_costs.si); > > + SERIALIZE_INTEGER_FIELD (addr_scale_costs_obj, "di", > > addr_scale_costs.di); > > + SERIALIZE_INTEGER_FIELD (addr_scale_costs_obj, "ti", > > addr_scale_costs.ti); > > + > > + return addr_scale_costs_obj; > > +} > > + > > +template <typename T> > > +static std::unique_ptr<json::object> > > +serialize_regmove_cost (const T ®move_cost) > > +{ > > + auto regmove_cost_obj = std::make_unique<json::object> (); > > + > > + SERIALIZE_INTEGER_FIELD (regmove_cost_obj, "GP2GP", regmove_cost.GP2GP); > > + SERIALIZE_INTEGER_FIELD (regmove_cost_obj, "GP2FP", regmove_cost.GP2FP); > > + SERIALIZE_INTEGER_FIELD (regmove_cost_obj, "FP2GP", regmove_cost.FP2GP); > > + SERIALIZE_INTEGER_FIELD (regmove_cost_obj, "FP2FP", regmove_cost.FP2FP); > > + > > + return regmove_cost_obj; > > +} > > + > > +template <typename T> > > +static std::unique_ptr<json::object> > > +serialize_vec_costs_advsimd (const T &advsimd) > > +{ > > + auto advsimd_obj = std::make_unique<json::object> (); > > + > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "int_stmt_cost", > > advsimd.int_stmt_cost); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "fp_stmt_cost", > > advsimd.fp_stmt_cost); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "ld2_st2_permute_cost", > > + advsimd.ld2_st2_permute_cost); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "ld3_st3_permute_cost", > > + advsimd.ld3_st3_permute_cost); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "ld4_st4_permute_cost", > > + advsimd.ld4_st4_permute_cost); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "permute_cost", > > advsimd.permute_cost); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "reduc_i8_cost", > > advsimd.reduc_i8_cost); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "reduc_i16_cost", > > + advsimd.reduc_i16_cost); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "reduc_i32_cost", > > + advsimd.reduc_i32_cost); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "reduc_i64_cost", > > + advsimd.reduc_i64_cost); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "reduc_f16_cost", > > + advsimd.reduc_f16_cost); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "reduc_f32_cost", > > + advsimd.reduc_f32_cost); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "reduc_f64_cost", > > + advsimd.reduc_f64_cost); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "store_elt_extra_cost", > > + advsimd.store_elt_extra_cost); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "vec_to_scalar_cost", > > + advsimd.vec_to_scalar_cost); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "scalar_to_vec_cost", > > + advsimd.scalar_to_vec_cost); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "align_load_cost", > > + advsimd.align_load_cost); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "unalign_load_cost", > > + advsimd.unalign_load_cost); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "unalign_store_cost", > > + advsimd.unalign_store_cost); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "store_cost", advsimd.store_cost); > > + > > + return advsimd_obj; > > +} > > + > > +template <typename T> > > +static std::unique_ptr<json::object> > > +serialize_vec_costs_sve (const T &sve) > > +{ > > + auto sve_obj = std::make_unique<json::object> (); > > + > > + SERIALIZE_INTEGER_FIELD (sve_obj, "clast_cost", sve.clast_cost); > > + SERIALIZE_INTEGER_FIELD (sve_obj, "fadda_f16_cost", sve.fadda_f16_cost); > > + SERIALIZE_INTEGER_FIELD (sve_obj, "fadda_f32_cost", sve.fadda_f32_cost); > > + SERIALIZE_INTEGER_FIELD (sve_obj, "fadda_f64_cost", sve.fadda_f64_cost); > > + SERIALIZE_INTEGER_FIELD (sve_obj, "gather_load_x32_cost", > > + sve.gather_load_x32_cost); > > + SERIALIZE_INTEGER_FIELD (sve_obj, "gather_load_x64_cost", > > + sve.gather_load_x64_cost); > > + SERIALIZE_INTEGER_FIELD (sve_obj, "gather_load_x32_init_cost", > > + sve.gather_load_x32_init_cost); > > + SERIALIZE_INTEGER_FIELD (sve_obj, "gather_load_x64_init_cost", > > + sve.gather_load_x64_init_cost); > > + SERIALIZE_INTEGER_FIELD (sve_obj, "scatter_store_elt_cost", > > + sve.scatter_store_elt_cost); > > + > > + return sve_obj; > > +} > > + > > +template <typename T> > > +static std::unique_ptr<json::object> > > +serialize_vec_costs_issue_info_scalar (const T &scalar) > > +{ > > + auto scalar_obj = std::make_unique<json::object> (); > > + > > + SERIALIZE_INTEGER_FIELD (scalar_obj, "loads_stores_per_cycle", > > + scalar.loads_stores_per_cycle); > > + SERIALIZE_INTEGER_FIELD (scalar_obj, "stores_per_cycle", > > + scalar.stores_per_cycle); > > + SERIALIZE_INTEGER_FIELD (scalar_obj, "general_ops_per_cycle", > > + scalar.general_ops_per_cycle); > > + SERIALIZE_INTEGER_FIELD (scalar_obj, "fp_simd_load_general_ops", > > + scalar.fp_simd_load_general_ops); > > + SERIALIZE_INTEGER_FIELD (scalar_obj, "fp_simd_store_general_ops", > > + scalar.fp_simd_store_general_ops); > > + > > + return scalar_obj; > > +} > > + > > +template <typename T> > > +static std::unique_ptr<json::object> > > +serialize_vec_costs_issue_info_advsimd (const T &advsimd) > > +{ > > + auto advsimd_obj = std::make_unique<json::object> (); > > + > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "loads_stores_per_cycle", > > + advsimd.loads_stores_per_cycle); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "stores_per_cycle", > > + advsimd.stores_per_cycle); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "general_ops_per_cycle", > > + advsimd.general_ops_per_cycle); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "fp_simd_load_general_ops", > > + advsimd.fp_simd_load_general_ops); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "fp_simd_store_general_ops", > > + advsimd.fp_simd_store_general_ops); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "ld2_st2_general_ops", > > + advsimd.ld2_st2_general_ops); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "ld3_st3_general_ops", > > + advsimd.ld3_st3_general_ops); > > + SERIALIZE_INTEGER_FIELD (advsimd_obj, "ld4_st4_general_ops", > > + advsimd.ld4_st4_general_ops); > > + > > + return advsimd_obj; > > +} > > + > > +template <typename T> > > +static std::unique_ptr<json::object> > > +serialize_vec_costs_issue_info_sve (const T &sve) > > +{ > > + auto sve_obj = std::make_unique<json::object> (); > > + > > + SERIALIZE_INTEGER_FIELD (sve_obj, "loads_stores_per_cycle", > > + sve.loads_stores_per_cycle); > > + SERIALIZE_INTEGER_FIELD (sve_obj, "stores_per_cycle", > > sve.stores_per_cycle); > > + SERIALIZE_INTEGER_FIELD (sve_obj, "general_ops_per_cycle", > > + sve.general_ops_per_cycle); > > + SERIALIZE_INTEGER_FIELD (sve_obj, "fp_simd_load_general_ops", > > + sve.fp_simd_load_general_ops); > > + SERIALIZE_INTEGER_FIELD (sve_obj, "fp_simd_store_general_ops", > > + sve.fp_simd_store_general_ops); > > + SERIALIZE_INTEGER_FIELD (sve_obj, "ld2_st2_general_ops", > > + sve.ld2_st2_general_ops); > > + SERIALIZE_INTEGER_FIELD (sve_obj, "ld3_st3_general_ops", > > + sve.ld3_st3_general_ops); > > + SERIALIZE_INTEGER_FIELD (sve_obj, "ld4_st4_general_ops", > > + sve.ld4_st4_general_ops); > > + SERIALIZE_INTEGER_FIELD (sve_obj, "pred_ops_per_cycle", > > + sve.pred_ops_per_cycle); > > + SERIALIZE_INTEGER_FIELD (sve_obj, "while_pred_ops", sve.while_pred_ops); > > + SERIALIZE_INTEGER_FIELD (sve_obj, "int_cmp_pred_ops", > > sve.int_cmp_pred_ops); > > + SERIALIZE_INTEGER_FIELD (sve_obj, "fp_cmp_pred_ops", > > sve.fp_cmp_pred_ops); > > + SERIALIZE_INTEGER_FIELD (sve_obj, "gather_scatter_pair_general_ops", > > + sve.gather_scatter_pair_general_ops); > > + SERIALIZE_INTEGER_FIELD (sve_obj, "gather_scatter_pair_pred_ops", > > + sve.gather_scatter_pair_pred_ops); > > + > > + return sve_obj; > > +} > > + > > +template <typename T> > > +static std::unique_ptr<json::object> > > +serialize_branch_costs (const T &branch_costs) > > +{ > > + auto branch_costs_obj = std::make_unique<json::object> (); > > + > > + SERIALIZE_INTEGER_FIELD (branch_costs_obj, "predictable", > > + branch_costs.predictable); > > + SERIALIZE_INTEGER_FIELD (branch_costs_obj, "unpredictable", > > + branch_costs.unpredictable); > > + > > + return branch_costs_obj; > > +} > > + > > +template <typename T> > > +static std::unique_ptr<json::object> > > +serialize_approx_modes (const T &approx_modes) > > +{ > > + auto approx_modes_obj = std::make_unique<json::object> (); > > + > > + SERIALIZE_INTEGER_FIELD (approx_modes_obj, "division", > > approx_modes.division); > > + SERIALIZE_INTEGER_FIELD (approx_modes_obj, "sqrt", approx_modes.sqrt); > > + SERIALIZE_INTEGER_FIELD (approx_modes_obj, "recip_sqrt", > > + approx_modes.recip_sqrt); > > + > > + return approx_modes_obj; > > +} > > + > > +template <typename T> > > +static std::unique_ptr<json::object> > > +serialize_memmov_cost (const T &memmov_cost) > > +{ > > + auto memmov_cost_obj = std::make_unique<json::object> (); > > + > > + SERIALIZE_INTEGER_FIELD (memmov_cost_obj, "load_int", > > memmov_cost.load_int); > > + SERIALIZE_INTEGER_FIELD (memmov_cost_obj, "store_int", > > memmov_cost.store_int); > > + SERIALIZE_INTEGER_FIELD (memmov_cost_obj, "load_fp", > > memmov_cost.load_fp); > > + SERIALIZE_INTEGER_FIELD (memmov_cost_obj, "store_fp", > > memmov_cost.store_fp); > > + SERIALIZE_INTEGER_FIELD (memmov_cost_obj, "load_pred", > > memmov_cost.load_pred); > > + SERIALIZE_INTEGER_FIELD (memmov_cost_obj, "store_pred", > > + memmov_cost.store_pred); > > + > > + return memmov_cost_obj; > > +} > > + > > +template <typename T> > > +static std::unique_ptr<json::object> > > +serialize_prefetch (const T &prefetch) > > +{ > > + auto prefetch_obj = std::make_unique<json::object> (); > > + > > + SERIALIZE_INTEGER_FIELD (prefetch_obj, "num_slots", prefetch.num_slots); > > + SERIALIZE_INTEGER_FIELD (prefetch_obj, "l1_cache_size", > > + prefetch.l1_cache_size); > > + SERIALIZE_INTEGER_FIELD (prefetch_obj, "l1_cache_line_size", > > + prefetch.l1_cache_line_size); > > + SERIALIZE_INTEGER_FIELD (prefetch_obj, "l2_cache_size", > > + prefetch.l2_cache_size); > > + SERIALIZE_BOOLEAN_FIELD (prefetch_obj, "prefetch_dynamic_strides", > > + prefetch.prefetch_dynamic_strides); > > + SERIALIZE_INTEGER_FIELD (prefetch_obj, "minimum_stride", > > + prefetch.minimum_stride); > > + SERIALIZE_INTEGER_FIELD (prefetch_obj, "default_opt_level", > > + prefetch.default_opt_level); > > + > > + return prefetch_obj; > > +} > > + > > +template <typename T> > > +static std::unique_ptr<json::object> > > +serialize_insn_extra_cost (const T &insn_extra_cost) > > +{ > > + auto insn_extra_cost_obj = std::make_unique<json::object> (); > > + > > + SERIALIZE_OBJECT (insn_extra_cost_obj, "alu", insn_extra_cost.alu, > > + serialize_insn_extra_cost_alu); > > + SERIALIZE_ARRAY_FIELD (insn_extra_cost_obj, "mult", > > insn_extra_cost.mult, 2, > > + serialize_insn_extra_cost_mult_element); > > + SERIALIZE_OBJECT (insn_extra_cost_obj, "ldst", insn_extra_cost.ldst, > > + serialize_insn_extra_cost_ldst); > > + SERIALIZE_ARRAY_FIELD (insn_extra_cost_obj, "fp", insn_extra_cost.fp, 2, > > + serialize_insn_extra_cost_fp_element); > > + SERIALIZE_OBJECT (insn_extra_cost_obj, "vect", insn_extra_cost.vect, > > + serialize_insn_extra_cost_vect); > > + > > + return insn_extra_cost_obj; > > +} > > + > > +template <typename T> > > +static std::unique_ptr<json::object> > > +serialize_addr_cost (const T &addr_cost) > > +{ > > + auto addr_cost_obj = std::make_unique<json::object> (); > > + > > + SERIALIZE_OBJECT (addr_cost_obj, "addr_scale_costs", > > + addr_cost.addr_scale_costs, > > + serialize_addr_cost_addr_scale_costs); > > + SERIALIZE_INTEGER_FIELD (addr_cost_obj, "pre_modify", > > addr_cost.pre_modify); > > + SERIALIZE_INTEGER_FIELD (addr_cost_obj, "post_modify", > > addr_cost.post_modify); > > + SERIALIZE_INTEGER_FIELD (addr_cost_obj, "post_modify_ld3_st3", > > + addr_cost.post_modify_ld3_st3); > > + SERIALIZE_INTEGER_FIELD (addr_cost_obj, "post_modify_ld4_st4", > > + addr_cost.post_modify_ld4_st4); > > + SERIALIZE_INTEGER_FIELD (addr_cost_obj, "register_offset", > > + addr_cost.register_offset); > > + SERIALIZE_INTEGER_FIELD (addr_cost_obj, "register_sextend", > > + addr_cost.register_sextend); > > + SERIALIZE_INTEGER_FIELD (addr_cost_obj, "register_zextend", > > + addr_cost.register_zextend); > > + SERIALIZE_INTEGER_FIELD (addr_cost_obj, "imm_offset", > > addr_cost.imm_offset); > > + > > + return addr_cost_obj; > > +} > > + > > +template <typename T> > > +static std::unique_ptr<json::object> > > +serialize_vec_costs_issue_info (const T &issue_info) > > +{ > > + auto issue_info_obj = std::make_unique<json::object> (); > > + > > + SERIALIZE_OBJECT (issue_info_obj, "scalar", issue_info.scalar, > > + serialize_vec_costs_issue_info_scalar); > > + SERIALIZE_OBJECT (issue_info_obj, "advsimd", issue_info.advsimd, > > + serialize_vec_costs_issue_info_advsimd); > > + SERIALIZE_OBJECT (issue_info_obj, "sve", issue_info.sve, > > + serialize_vec_costs_issue_info_sve); > > + > > + return issue_info_obj; > > +} > > + > > +template <typename T> > > +static std::unique_ptr<json::object> > > +serialize_vec_costs (const T &vec_costs) > > +{ > > + auto vec_costs_obj = std::make_unique<json::object> (); > > + > > + SERIALIZE_INTEGER_FIELD (vec_costs_obj, "scalar_int_stmt_cost", > > + vec_costs.scalar_int_stmt_cost); > > + SERIALIZE_INTEGER_FIELD (vec_costs_obj, "scalar_fp_stmt_cost", > > + vec_costs.scalar_fp_stmt_cost); > > + SERIALIZE_INTEGER_FIELD (vec_costs_obj, "scalar_load_cost", > > + vec_costs.scalar_load_cost); > > + SERIALIZE_INTEGER_FIELD (vec_costs_obj, "scalar_store_cost", > > + vec_costs.scalar_store_cost); > > + SERIALIZE_INTEGER_FIELD (vec_costs_obj, "cond_taken_branch_cost", > > + vec_costs.cond_taken_branch_cost); > > + SERIALIZE_INTEGER_FIELD (vec_costs_obj, "cond_not_taken_branch_cost", > > + vec_costs.cond_not_taken_branch_cost); > > + SERIALIZE_OBJECT (vec_costs_obj, "advsimd", vec_costs.advsimd, > > + serialize_vec_costs_advsimd); > > + SERIALIZE_OBJECT (vec_costs_obj, "sve", vec_costs.sve, > > + serialize_vec_costs_sve); > > + SERIALIZE_OBJECT (vec_costs_obj, "issue_info", vec_costs.issue_info, > > + serialize_vec_costs_issue_info); > > + > > + return vec_costs_obj; > > +} > > + > > +template <typename T> > > +static std::unique_ptr<json::object> > > +serialize_tunings (const T &tunings) > > +{ > > + auto tunings_obj = std::make_unique<json::object> (); > > + > > + SERIALIZE_OBJECT (tunings_obj, "insn_extra_cost", > > tunings.insn_extra_cost, > > + serialize_insn_extra_cost); > > + SERIALIZE_OBJECT (tunings_obj, "addr_cost", tunings.addr_cost, > > + serialize_addr_cost); > > + SERIALIZE_OBJECT (tunings_obj, "regmove_cost", tunings.regmove_cost, > > + serialize_regmove_cost); > > + SERIALIZE_OBJECT (tunings_obj, "vec_costs", tunings.vec_costs, > > + serialize_vec_costs); > > + SERIALIZE_OBJECT (tunings_obj, "branch_costs", tunings.branch_costs, > > + serialize_branch_costs); > > + SERIALIZE_OBJECT (tunings_obj, "approx_modes", tunings.approx_modes, > > + serialize_approx_modes); > > + SERIALIZE_INTEGER_FIELD (tunings_obj, "sve_width", tunings.sve_width); > > + SERIALIZE_OBJECT (tunings_obj, "memmov_cost", tunings.memmov_cost, > > + serialize_memmov_cost); > > + SERIALIZE_INTEGER_FIELD (tunings_obj, "issue_rate", tunings.issue_rate); > > + SERIALIZE_INTEGER_FIELD (tunings_obj, "fusible_ops", > > tunings.fusible_ops); > > + SERIALIZE_STRING_FIELD (tunings_obj, "function_align", > > + tunings.function_align); > > + SERIALIZE_STRING_FIELD (tunings_obj, "jump_align", tunings.jump_align); > > + SERIALIZE_STRING_FIELD (tunings_obj, "loop_align", tunings.loop_align); > > + SERIALIZE_INTEGER_FIELD (tunings_obj, "int_reassoc_width", > > + tunings.int_reassoc_width); > > + SERIALIZE_INTEGER_FIELD (tunings_obj, "fp_reassoc_width", > > + tunings.fp_reassoc_width); > > + SERIALIZE_INTEGER_FIELD (tunings_obj, "fma_reassoc_width", > > + tunings.fma_reassoc_width); > > + SERIALIZE_INTEGER_FIELD (tunings_obj, "vec_reassoc_width", > > + tunings.vec_reassoc_width); > > + SERIALIZE_INTEGER_FIELD (tunings_obj, "min_div_recip_mul_sf", > > + tunings.min_div_recip_mul_sf); > > + SERIALIZE_INTEGER_FIELD (tunings_obj, "min_div_recip_mul_df", > > + tunings.min_div_recip_mul_df); > > + SERIALIZE_INTEGER_FIELD (tunings_obj, "max_case_values", > > + tunings.max_case_values); > > + SERIALIZE_ENUM_FIELD (tunings_obj, "autoprefetcher_model", > > + tunings.autoprefetcher_model, > > + autoprefetcher_model_mappings); > > + SERIALIZE_INTEGER_FIELD (tunings_obj, "extra_tuning_flags", > > + tunings.extra_tuning_flags); > > + SERIALIZE_OBJECT (tunings_obj, "prefetch", tunings.prefetch, > > + serialize_prefetch); > > + SERIALIZE_ENUM_FIELD (tunings_obj, "ldp_policy_model", > > + tunings.ldp_policy_model, > > ldp_policy_model_mappings); > > + SERIALIZE_ENUM_FIELD (tunings_obj, "stp_policy_model", > > + tunings.stp_policy_model, > > stp_policy_model_mappings); > > + > > + return tunings_obj; > > +} > > + > > +/* Print tune_params structure to JSON file. */ > > +void > > +aarch64_print_tune_params (const tune_params ¶ms, const char *filename) > > +{ > > + auto aarch64_tune_params_json = std::make_unique<json::object> (); > > + aarch64_tune_params_json->set ("tune_params", serialize_tunings > > (params)); > > + > > + pretty_printer pp; > > + aarch64_tune_params_json->print (&pp, true); > > + > > + FILE *outputFile = fopen (filename, "w"); > > + if (!outputFile) > > + { > > + error ("Error opening file %s", filename); > > + return; > > + } > > + > > + fprintf (outputFile, "%s", pp_formatted_text (&pp)); > > + fclose (outputFile); > > + return; > > +} > > \ No newline at end of file > > diff --git a/gcc/config/aarch64/aarch64-json-tunings-printer.h > > b/gcc/config/aarch64/aarch64-json-tunings-printer.h > > new file mode 100644 > > index 00000000000..a65c005d9fe > > --- /dev/null > > +++ b/gcc/config/aarch64/aarch64-json-tunings-printer.h > > @@ -0,0 +1,28 @@ > > +/* Routine to print the AArch64 tuning parameters to a JSON file. > > + Copyright The GNU Toolchain Authors. > > + > > + This file is part of GCC. > > + > > + GCC is free software; you can redistribute it and/or modify it > > + under the terms of the GNU General Public License as published by > > + the Free Software Foundation; either version 3, or (at your option) > > + any later version. > > + > > + GCC is distributed in the hope that it will be useful, but > > + WITHOUT ANY WARRANTY; without even the implied warranty of > > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > > + General Public License for more details. > > + > > + You should have received a copy of the GNU General Public License > > + along with GCC; see the file COPYING3. If not see > > + <http://www.gnu.org/licenses/>. */ > > + > > +#ifndef AARCH64_JSON_TUNINGS_PRINTER_H > > +#define AARCH64_JSON_TUNINGS_PRINTER_H > > + > > +#include "aarch64-protos.h" > > + > > +void > > +aarch64_print_tune_params (const tune_params ¶ms, const char > > *filename); > > + > > +#endif > > \ No newline at end of file > > diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc > > index 0485f695941..fe3971d7ae7 100644 > > --- a/gcc/config/aarch64/aarch64.cc > > +++ b/gcc/config/aarch64/aarch64.cc > > @@ -98,6 +98,7 @@ > > #include "ipa-prop.h" > > #include "ipa-fnsummary.h" > > #include "hash-map.h" > > +#include "aarch64-json-tunings-printer.h" > > > > /* This file should be included last. */ > > #include "target-def.h" > > @@ -18875,6 +18876,9 @@ aarch64_override_options_internal (struct > > gcc_options *opts) > > if (opts->x_aarch64_stp_policy_param) > > aarch64_tune_params.stp_policy_model = > > opts->x_aarch64_stp_policy_param; > > > > + if (opts->x_fdump_tuning_model) > > + aarch64_print_tune_params (aarch64_tune_params, > > opts->x_fdump_tuning_model); > > + > > /* This target defaults to strict volatile bitfields. */ > > if (opts->x_flag_strict_volatile_bitfields < 0 && abi_version_at_least > > (2)) > > opts->x_flag_strict_volatile_bitfields = 1; > > diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt > > index 9ca753e6a88..830da394493 100644 > > --- a/gcc/config/aarch64/aarch64.opt > > +++ b/gcc/config/aarch64/aarch64.opt > > @@ -188,6 +188,10 @@ mabi= > > Target RejectNegative Joined Enum(aarch64_abi) Var(aarch64_abi) > > Init(AARCH64_ABI_DEFAULT) > > Generate code that conforms to the specified ABI. > > > > +fdump-tuning-model= > > +Target RejectNegative Negative(fdump-tuning-model=) ToLower Joined > > Var(fdump_tuning_model) > > +Dump current tuning model to a JSON file. > > + > > moverride= > > Target RejectNegative ToLower Joined Var(aarch64_override_tune_string) Save > > -moverride=<string> Power users only! Override CPU optimization > > parameters. > > diff --git a/gcc/config/aarch64/t-aarch64 b/gcc/config/aarch64/t-aarch64 > > index 38a8c063725..2378767780e 100644 > > --- a/gcc/config/aarch64/t-aarch64 > > +++ b/gcc/config/aarch64/t-aarch64 > > @@ -208,6 +208,15 @@ aarch64-ldp-fusion.o: > > $(srcdir)/config/aarch64/aarch64-ldp-fusion.cc \ > > $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ > > $(srcdir)/config/aarch64/aarch64-ldp-fusion.cc > > > > +aarch64-json-tunings-printer.o: > > $(srcdir)/config/aarch64/aarch64-json-tunings-printer.cc \ > > + $(CONFIG_H) $(SYSTEM_H) $(CORETYPES_H) $(TM_H) $(DIAGNOSTIC_CORE_H) \ > > + $(PRETTY_PRINT_H) json.h \ > > + $(srcdir)/config/aarch64/aarch64-json-tunings-printer.h \ > > + $(srcdir)/config/aarch64/aarch64-protos.h \ > > + $(srcdir)/config/arm/aarch-common-protos.h > > + $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ > > + $(srcdir)/config/aarch64/aarch64-json-tunings-printer.cc > > + > > comma=, > > MULTILIB_OPTIONS = $(subst $(comma),/, $(patsubst %, mabi=%, $(subst > > $(comma),$(comma)mabi=,$(TM_MULTILIB_CONFIG)))) > > MULTILIB_DIRNAMES = $(subst $(comma), ,$(TM_MULTILIB_CONFIG)) > > -- > > 2.44.0 > >