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   | 517 ++++++++++++++++++
 .../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, 563 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 a518e976b82..4d23b578457 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -350,7 +350,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-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-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..6c440838390
--- /dev/null
+++ b/gcc/config/aarch64/aarch64-json-tunings-printer.cc
@@ -0,0 +1,517 @@
+/* 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/>.  */
+
+
+#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"
+
+static std::unique_ptr<json::object>
+serialize_alu_cost_table (const struct alu_cost_table &alu)
+{
+  auto alu_obj = std::make_unique<json::object> ();
+
+  alu_obj->set_integer ("arith", alu.arith);
+  alu_obj->set_integer ("logical", alu.logical);
+  alu_obj->set_integer ("shift", alu.shift);
+  alu_obj->set_integer ("shift_reg", alu.shift_reg);
+  alu_obj->set_integer ("arith_shift", alu.arith_shift);
+  alu_obj->set_integer ("arith_shift_reg", alu.arith_shift_reg);
+  alu_obj->set_integer ("log_shift", alu.log_shift);
+  alu_obj->set_integer ("log_shift_reg", alu.log_shift_reg);
+  alu_obj->set_integer ("extend", alu.extend);
+  alu_obj->set_integer ("extend_arith", alu.extend_arith);
+  alu_obj->set_integer ("bfi", alu.bfi);
+  alu_obj->set_integer ("bfx", alu.bfx);
+  alu_obj->set_integer ("clz", alu.clz);
+  alu_obj->set_integer ("rev", alu.rev);
+  alu_obj->set_integer ("non_exec", alu.non_exec);
+  alu_obj->set_bool ("non_exec_costs_exec", alu.non_exec_costs_exec);
+
+  return alu_obj;
+}
+
+static std::unique_ptr<json::array>
+serialize_mult_cost_table (const struct mult_cost_table *mult)
+{
+  auto mult_arr = std::make_unique<json::array> ();
+
+  for (int i = 0; i < 2; ++i)
+    {
+      auto mult_obj = std::make_unique<json::object> ();
+
+      mult_obj->set_integer ("simple", mult[i].simple);
+      mult_obj->set_integer ("flag_setting", mult[i].flag_setting);
+      mult_obj->set_integer ("extend", mult[i].extend);
+      mult_obj->set_integer ("add", mult[i].add);
+      mult_obj->set_integer ("extend_add", mult[i].extend_add);
+      mult_obj->set_integer ("idiv", mult[i].idiv);
+
+      mult_arr->append (std::move (mult_obj));
+    }
+
+  return mult_arr;
+}
+
+static std::unique_ptr<json::object>
+serialize_mem_cost_table (const struct mem_cost_table &mem)
+{
+  auto mem_obj = std::make_unique<json::object> ();
+
+  mem_obj->set_integer ("load", mem.load);
+  mem_obj->set_integer ("load_sign_extend", mem.load_sign_extend);
+  mem_obj->set_integer ("ldrd", mem.ldrd);
+  mem_obj->set_integer ("ldm_1st", mem.ldm_1st);
+  mem_obj->set_integer ("ldm_regs_per_insn_1st", mem.ldm_regs_per_insn_1st);
+  mem_obj->set_integer ("ldm_regs_per_insn_subsequent",
+                       mem.ldm_regs_per_insn_subsequent);
+  mem_obj->set_integer ("loadf", mem.loadf);
+  mem_obj->set_integer ("loadd", mem.loadd);
+  mem_obj->set_integer ("load_unaligned", mem.load_unaligned);
+  mem_obj->set_integer ("store", mem.store);
+  mem_obj->set_integer ("strd", mem.strd);
+  mem_obj->set_integer ("stm_1st", mem.stm_1st);
+  mem_obj->set_integer ("stm_regs_per_insn_1st", mem.stm_regs_per_insn_1st);
+  mem_obj->set_integer ("stm_regs_per_insn_subsequent",
+                       mem.stm_regs_per_insn_subsequent);
+  mem_obj->set_integer ("storef", mem.storef);
+  mem_obj->set_integer ("stored", mem.stored);
+  mem_obj->set_integer ("store_unaligned", mem.store_unaligned);
+  mem_obj->set_integer ("loadv", mem.loadv);
+  mem_obj->set_integer ("storev", mem.storev);
+
+  return mem_obj;
+}
+
+static std::unique_ptr<json::array>
+serialize_fp_cost_table (const struct fp_cost_table *fp)
+{
+  auto fp_arr = std::make_unique<json::array> ();
+
+  for (int i = 0; i < 2; ++i)
+    {
+      auto fp_obj = std::make_unique<json::object> ();
+
+      fp_obj->set_integer ("div", fp[i].div);
+      fp_obj->set_integer ("mult", fp[i].mult);
+      fp_obj->set_integer ("mult_addsub", fp[i].mult_addsub);
+      fp_obj->set_integer ("fma", fp[i].fma);
+      fp_obj->set_integer ("addsub", fp[i].addsub);
+      fp_obj->set_integer ("fpconst", fp[i].fpconst);
+      fp_obj->set_integer ("neg", fp[i].neg);
+      fp_obj->set_integer ("compare", fp[i].compare);
+      fp_obj->set_integer ("widen", fp[i].widen);
+      fp_obj->set_integer ("narrow", fp[i].narrow);
+      fp_obj->set_integer ("toint", fp[i].toint);
+      fp_obj->set_integer ("fromint", fp[i].fromint);
+      fp_obj->set_integer ("roundint", fp[i].roundint);
+
+      fp_arr->append (std::move (fp_obj));
+    }
+
+  return fp_arr;
+}
+
+static std::unique_ptr<json::object>
+serialize_vector_cost_table (const struct vector_cost_table &vect)
+{
+  auto vec_costs_obj = std::make_unique<json::object> ();
+
+  vec_costs_obj->set_integer ("alu", vect.alu);
+  vec_costs_obj->set_integer ("mult", vect.mult);
+  vec_costs_obj->set_integer ("movi", vect.movi);
+  vec_costs_obj->set_integer ("dup", vect.dup);
+  vec_costs_obj->set_integer ("extract", vect.extract);
+
+  return vec_costs_obj;
+}
+
+static std::unique_ptr<json::object>
+serialize_cpu_cost_table (const struct cpu_cost_table &insn_extra_cost)
+{
+  auto insn_extra_cost_obj = std::make_unique<json::object> ();
+
+  insn_extra_cost_obj->set ("alu",
+                           serialize_alu_cost_table (insn_extra_cost.alu));
+  insn_extra_cost_obj->set ("mult",
+                           serialize_mult_cost_table (insn_extra_cost.mult));
+  insn_extra_cost_obj->set ("ldst",
+                           serialize_mem_cost_table (insn_extra_cost.ldst));
+  insn_extra_cost_obj->set ("fp", serialize_fp_cost_table 
(insn_extra_cost.fp));
+  insn_extra_cost_obj->set ("vect",
+                           serialize_vector_cost_table (insn_extra_cost.vect));
+
+  return insn_extra_cost_obj;
+}
+
+static std::unique_ptr<json::object>
+serialize_addr_scale_costs_objr_mode_cost (
+  const scale_addr_mode_cost &addr_scale_costs)
+{
+  auto addr_scale_costs_objr_obj = std::make_unique<json::object> ();
+
+  addr_scale_costs_objr_obj->set_integer ("hi", addr_scale_costs.hi);
+  addr_scale_costs_objr_obj->set_integer ("si", addr_scale_costs.si);
+  addr_scale_costs_objr_obj->set_integer ("di", addr_scale_costs.di);
+  addr_scale_costs_objr_obj->set_integer ("ti", addr_scale_costs.ti);
+  return addr_scale_costs_objr_obj;
+}
+
+static std::unique_ptr<json::object>
+serialize_cpu_addrcost_table (const cpu_addrcost_table &addr_cost)
+{
+  auto addr_cost_obj = std::make_unique<json::object> ();
+
+  addr_cost_obj->set ("addr_scale_costs",
+                     serialize_addr_scale_costs_objr_mode_cost (
+                       addr_cost.addr_scale_costs));
+  addr_cost_obj->set_integer ("pre_modify", addr_cost.pre_modify);
+  addr_cost_obj->set_integer ("post_modify", addr_cost.post_modify);
+  addr_cost_obj->set_integer ("post_modify_ld3_st3",
+                             addr_cost.post_modify_ld3_st3);
+  addr_cost_obj->set_integer ("post_modify_ld4_st4",
+                             addr_cost.post_modify_ld4_st4);
+  addr_cost_obj->set_integer ("register_offset", addr_cost.register_offset);
+  addr_cost_obj->set_integer ("register_sextend", addr_cost.register_sextend);
+  addr_cost_obj->set_integer ("register_zextend", addr_cost.register_zextend);
+  addr_cost_obj->set_integer ("imm_offset", addr_cost.imm_offset);
+  return addr_cost_obj;
+}
+
+static std::unique_ptr<json::object>
+serialize_cpu_regmove_cost (const cpu_regmove_cost &regmove_cost)
+{
+  auto regmove_cost_obj = std::make_unique<json::object> ();
+
+  regmove_cost_obj->set_integer ("GP2GP", regmove_cost.GP2GP);
+  regmove_cost_obj->set_integer ("GP2FP", regmove_cost.GP2FP);
+  regmove_cost_obj->set_integer ("FP2GP", regmove_cost.FP2GP);
+  regmove_cost_obj->set_integer ("FP2FP", regmove_cost.FP2FP);
+  return regmove_cost_obj;
+}
+
+static std::unique_ptr<json::object>
+serialize_advsimd_vec_cost (const advsimd_vec_cost &advsimd)
+{
+  auto advsimd_obj = std::make_unique<json::object> ();
+
+  advsimd_obj->set_integer ("int_stmt_cost", advsimd.int_stmt_cost);
+  advsimd_obj->set_integer ("fp_stmt_cost", advsimd.fp_stmt_cost);
+  advsimd_obj->set_integer ("ld2_st2_permute_cost",
+                           advsimd.ld2_st2_permute_cost);
+  advsimd_obj->set_integer ("ld3_st3_permute_cost",
+                           advsimd.ld3_st3_permute_cost);
+  advsimd_obj->set_integer ("ld4_st4_permute_cost",
+                           advsimd.ld4_st4_permute_cost);
+  advsimd_obj->set_integer ("permute_cost", advsimd.permute_cost);
+  advsimd_obj->set_integer ("reduc_i8_cost", advsimd.reduc_i8_cost);
+  advsimd_obj->set_integer ("reduc_i16_cost", advsimd.reduc_i16_cost);
+  advsimd_obj->set_integer ("reduc_i32_cost", advsimd.reduc_i32_cost);
+  advsimd_obj->set_integer ("reduc_i64_cost", advsimd.reduc_i64_cost);
+  advsimd_obj->set_integer ("reduc_f16_cost", advsimd.reduc_f16_cost);
+  advsimd_obj->set_integer ("reduc_f32_cost", advsimd.reduc_f32_cost);
+  advsimd_obj->set_integer ("reduc_f64_cost", advsimd.reduc_f64_cost);
+  advsimd_obj->set_integer ("store_elt_extra_cost",
+                           advsimd.store_elt_extra_cost);
+  advsimd_obj->set_integer ("vec_to_scalar_cost", advsimd.vec_to_scalar_cost);
+  advsimd_obj->set_integer ("scalar_to_vec_cost", advsimd.scalar_to_vec_cost);
+  advsimd_obj->set_integer ("align_load_cost", advsimd.align_load_cost);
+  advsimd_obj->set_integer ("unalign_load_cost", advsimd.unalign_load_cost);
+  advsimd_obj->set_integer ("unalign_store_cost", advsimd.unalign_store_cost);
+  advsimd_obj->set_integer ("store_cost", advsimd.store_cost);
+
+  return advsimd_obj;
+}
+static std::unique_ptr<json::object>
+serialize_sve_vec_cost (const sve_vec_cost &sve)
+{
+  auto sve_obj = std::make_unique<json::object> ();
+
+  sve_obj->set_integer ("clast_cost", sve.clast_cost);
+  sve_obj->set_integer ("fadda_f16_cost", sve.fadda_f16_cost);
+  sve_obj->set_integer ("fadda_f32_cost", sve.fadda_f32_cost);
+  sve_obj->set_integer ("fadda_f64_cost", sve.fadda_f64_cost);
+  sve_obj->set_integer ("gather_load_x32_cost", sve.gather_load_x32_cost);
+  sve_obj->set_integer ("gather_load_x64_cost", sve.gather_load_x64_cost);
+  sve_obj->set_integer ("gather_load_x32_init_cost",
+                       sve.gather_load_x32_init_cost);
+  sve_obj->set_integer ("gather_load_x64_init_cost",
+                       sve.gather_load_x64_init_cost);
+  sve_obj->set_integer ("scatter_store_elt_cost", sve.scatter_store_elt_cost);
+
+  return sve_obj;
+}
+
+static std::unique_ptr<json::object>
+serialize_aarch64_base_vec_issue_info (const aarch64_base_vec_issue_info &base)
+{
+  auto base_obj = std::make_unique<json::object> ();
+
+  base_obj->set_integer ("loads_stores_per_cycle", 
base.loads_stores_per_cycle);
+  base_obj->set_integer ("stores_per_cycle", base.stores_per_cycle);
+  base_obj->set_integer ("general_ops_per_cycle", base.general_ops_per_cycle);
+  base_obj->set_integer ("fp_simd_load_general_ops",
+                        base.fp_simd_load_general_ops);
+  base_obj->set_integer ("fp_simd_store_general_ops",
+                        base.fp_simd_store_general_ops);
+
+  return base_obj;
+}
+
+static std::unique_ptr<json::object>
+serialize_aarch64_simd_vec_issue_info (const aarch64_simd_vec_issue_info &simd)
+{
+  std::unique_ptr<json::object> simd_obj
+    = serialize_aarch64_base_vec_issue_info (simd);
+
+  simd_obj->set_integer ("ld2_st2_general_ops", simd.ld2_st2_general_ops);
+  simd_obj->set_integer ("ld3_st3_general_ops", simd.ld3_st3_general_ops);
+  simd_obj->set_integer ("ld4_st4_general_ops", simd.ld4_st4_general_ops);
+
+  return simd_obj;
+}
+
+static std::unique_ptr<json::object>
+serialize_aarch64_sve_vec_issue_info (const aarch64_sve_vec_issue_info &sve)
+{
+  std::unique_ptr<json::object> sve_obj
+    = serialize_aarch64_simd_vec_issue_info (sve);
+
+  sve_obj->set_integer ("pred_ops_per_cycle", sve.pred_ops_per_cycle);
+  sve_obj->set_integer ("while_pred_ops", sve.while_pred_ops);
+  sve_obj->set_integer ("int_cmp_pred_ops", sve.int_cmp_pred_ops);
+  sve_obj->set_integer ("fp_cmp_pred_ops", sve.fp_cmp_pred_ops);
+  sve_obj->set_integer ("gather_scatter_pair_general_ops",
+                       sve.gather_scatter_pair_general_ops);
+  sve_obj->set_integer ("gather_scatter_pair_pred_ops",
+                       sve.gather_scatter_pair_pred_ops);
+
+  return sve_obj;
+}
+
+static std::unique_ptr<json::object>
+serialize_aarch64_vec_issue_info (const aarch64_vec_issue_info &issue_info)
+{
+  auto issue_obj = std::make_unique<json::object> ();
+
+  if (issue_info.scalar)
+    issue_obj->set ("scalar",
+                   serialize_aarch64_base_vec_issue_info (*issue_info.scalar));
+  if (issue_info.advsimd)
+    issue_obj->set ("advsimd", serialize_aarch64_simd_vec_issue_info (
+                                *issue_info.advsimd));
+  if (issue_info.sve)
+    issue_obj->set ("sve",
+                   serialize_aarch64_sve_vec_issue_info (*issue_info.sve));
+
+  return issue_obj;
+}
+
+static std::unique_ptr<json::object>
+serialize_cpu_vector_cost (const cpu_vector_cost &vec_costs)
+{
+  auto vec_costs_obj = std::make_unique<json::object> ();
+
+  vec_costs_obj->set_integer ("scalar_int_stmt_cost",
+                             vec_costs.scalar_int_stmt_cost);
+  vec_costs_obj->set_integer ("scalar_fp_stmt_cost",
+                             vec_costs.scalar_fp_stmt_cost);
+  vec_costs_obj->set_integer ("scalar_load_cost", vec_costs.scalar_load_cost);
+  vec_costs_obj->set_integer ("scalar_store_cost", 
vec_costs.scalar_store_cost);
+  vec_costs_obj->set_integer ("cond_taken_branch_cost",
+                             vec_costs.cond_taken_branch_cost);
+  vec_costs_obj->set_integer ("cond_not_taken_branch_cost",
+                             vec_costs.cond_not_taken_branch_cost);
+  if (vec_costs.advsimd)
+    vec_costs_obj->set ("advsimd",
+                       serialize_advsimd_vec_cost (*vec_costs.advsimd));
+  if (vec_costs.sve)
+    vec_costs_obj->set ("sve", serialize_sve_vec_cost (*vec_costs.sve));
+  if (vec_costs.issue_info)
+    vec_costs_obj->set ("issue_info", serialize_aarch64_vec_issue_info (
+                                       *vec_costs.issue_info));
+
+  return vec_costs_obj;
+}
+
+static std::unique_ptr<json::object>
+serialize_cpu_branch_cost (const cpu_branch_cost &branch_costs)
+{
+  auto branch_costs_obj = std::make_unique<json::object> ();
+  branch_costs_obj->set_integer ("predictable", branch_costs.predictable);
+  branch_costs_obj->set_integer ("unpredictable", branch_costs.unpredictable);
+  return branch_costs_obj;
+}
+
+static std::unique_ptr<json::object>
+serialize_cpu_approx_modes (const cpu_approx_modes &approx_modes)
+{
+  auto approx_modes_obj = std::make_unique<json::object> ();
+  approx_modes_obj->set_integer ("division", approx_modes.division);
+  approx_modes_obj->set_integer ("sqrt", approx_modes.sqrt);
+  approx_modes_obj->set_integer ("recip_sqrt", approx_modes.recip_sqrt);
+  return approx_modes_obj;
+}
+
+static std::unique_ptr<json::object>
+serialize_cpu_memmov_cost (const cpu_memmov_cost &memmov_cost)
+{
+  auto memmov_cost_obj = std::make_unique<json::object> ();
+  memmov_cost_obj->set_integer ("load_int", memmov_cost.load_int);
+  memmov_cost_obj->set_integer ("store_int", memmov_cost.store_int);
+  memmov_cost_obj->set_integer ("load_fp", memmov_cost.load_fp);
+  memmov_cost_obj->set_integer ("store_fp", memmov_cost.store_fp);
+  memmov_cost_obj->set_integer ("load_pred", memmov_cost.load_pred);
+  memmov_cost_obj->set_integer ("store_pred", memmov_cost.store_pred);
+
+  return memmov_cost_obj;
+}
+
+static std::unique_ptr<json::object>
+serialize_cpu_prefetch_tune (const cpu_prefetch_tune &prefetch)
+{
+  auto prefetch_obj = std::make_unique<json::object> ();
+  prefetch_obj->set_integer ("num_slots", prefetch.num_slots);
+  prefetch_obj->set_integer ("l1_cache_size", prefetch.l1_cache_size);
+  prefetch_obj->set_integer ("l1_cache_line_size", 
prefetch.l1_cache_line_size);
+  prefetch_obj->set_integer ("l2_cache_size", prefetch.l2_cache_size);
+  prefetch_obj->set_bool ("prefetch_dynamic_strides",
+                         prefetch.prefetch_dynamic_strides);
+  prefetch_obj->set_integer ("minimum_stride", prefetch.minimum_stride);
+  prefetch_obj->set_integer ("default_opt_level", prefetch.default_opt_level);
+
+  return prefetch_obj;
+}
+
+static const char *
+serialize_autoprefetcher_model (
+  const enum tune_params::aarch64_autoprefetch_model model)
+{
+  switch (model)
+    {
+    case tune_params::AUTOPREFETCHER_OFF:
+      return "AUTOPREFETCHER_OFF";
+    case tune_params::AUTOPREFETCHER_WEAK:
+      return "AUTOPREFETCHER_WEAK";
+    case tune_params::AUTOPREFETCHER_STRONG:
+      return "AUTOPREFETCHER_STRONG";
+    }
+  return "AUTOPREFETCHER_OFF";
+}
+
+static const char *
+serialize_ldp_stp_policy (const enum aarch64_ldp_stp_policy policy)
+{
+  switch (policy)
+    {
+    case AARCH64_LDP_STP_POLICY_DEFAULT:
+      return "AARCH64_LDP_STP_POLICY_DEFAULT";
+    case AARCH64_LDP_STP_POLICY_ALIGNED:
+      return "AARCH64_LDP_STP_POLICY_ALIGNED";
+    case AARCH64_LDP_STP_POLICY_ALWAYS:
+      return "AARCH64_LDP_STP_POLICY_ALWAYS";
+    case AARCH64_LDP_STP_POLICY_NEVER:
+      return "AARCH64_LDP_STP_POLICY_NEVER";
+    }
+  return "AARCH64_LDP_STP_POLICY_DEFAULT";
+}
+
+static std::unique_ptr<json::object>
+serialize_tune_params (const tune_params &params)
+{
+  auto params_obj = std::make_unique<json::object> ();
+  if (params.insn_extra_cost)
+    params_obj->set ("insn_extra_cost",
+                    serialize_cpu_cost_table (*params.insn_extra_cost));
+  if (params.addr_cost)
+    params_obj->set ("addr_cost",
+                    serialize_cpu_addrcost_table (*params.addr_cost));
+  if (params.regmove_cost)
+    params_obj->set ("regmove_cost",
+                    serialize_cpu_regmove_cost (*params.regmove_cost));
+  if (params.vec_costs)
+    params_obj->set ("vec_costs",
+                    serialize_cpu_vector_cost (*params.vec_costs));
+  if (params.branch_costs)
+    params_obj->set ("branch_costs",
+                    serialize_cpu_branch_cost (*params.branch_costs));
+  if (params.approx_modes)
+    params_obj->set ("approx_modes",
+                    serialize_cpu_approx_modes (*params.approx_modes));
+  params_obj->set_integer ("sve_width", params.sve_width);
+
+  params_obj->set ("memmov_cost",
+                  serialize_cpu_memmov_cost (params.memmov_cost));
+
+  params_obj->set_integer ("issue_rate", params.issue_rate);
+  params_obj->set_integer ("fusible_ops", params.fusible_ops);
+  params_obj->set_string ("function_align", params.function_align);
+  params_obj->set_string ("jump_align", params.jump_align);
+  params_obj->set_string ("loop_align", params.loop_align);
+  params_obj->set_integer ("int_reassoc_width", params.int_reassoc_width);
+  params_obj->set_integer ("fp_reassoc_width", params.fp_reassoc_width);
+  params_obj->set_integer ("fma_reassoc_width", params.fma_reassoc_width);
+  params_obj->set_integer ("vec_reassoc_width", params.vec_reassoc_width);
+  params_obj->set_integer ("min_div_recip_mul_sf", 
params.min_div_recip_mul_sf);
+  params_obj->set_integer ("min_div_recip_mul_df", 
params.min_div_recip_mul_df);
+  params_obj->set_integer ("max_case_values", params.max_case_values);
+  params_obj->set_string ("autoprefetcher_model",
+                         serialize_autoprefetcher_model (
+                           params.autoprefetcher_model));
+
+  params_obj->set_integer ("extra_tuning_flags", params.extra_tuning_flags);
+  if (params.prefetch)
+    params_obj->set ("prefetch",
+                    serialize_cpu_prefetch_tune (*params.prefetch));
+
+  params_obj->set_string ("ldp_policy_model",
+                         serialize_ldp_stp_policy (params.ldp_policy_model));
+  params_obj->set_string ("stp_policy_model",
+                         serialize_ldp_stp_policy (params.stp_policy_model));
+
+  return params_obj;
+}
+
+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_tune_params 
(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..d5cc1229c82
--- /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 f9d56eea7ee..2bbed9d2e54 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -97,6 +97,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"
@@ -18592,6 +18593,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 f32d56d4ffa..4c8ea2eb323 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 5aa77809948..c5002eab595 100644
--- a/gcc/config/aarch64/t-aarch64
+++ b/gcc/config/aarch64/t-aarch64
@@ -197,6 +197,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