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"
        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 &))
+{
+  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 &))
+{
+  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}};
+
+/* 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);
+
+  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 &regmove_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 &params, 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 &params, 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

Reply via email to