From: Soumya AR <soum...@nvidia.com> This patch adds support for loading custom CPU tuning parameters from a JSON file for AArch64 targets. The '-muser-provided-CPU=' flag accepts a user provided JSON file and overrides the internal tuning parameters at GCC runtime.
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-parser.o. * config/aarch64/aarch64.cc (aarch64_override_options_internal): Invoke aarch64_load_tuning_params_from_json if -muser-provided-CPU= is specified. * config/aarch64/aarch64.opt: New option. * config/aarch64/t-aarch64 (aarch64-json-tunings-parser.o): New define. * selftest-run-tests.cc (selftest::run_tests): Add json_tunings_tests(). * selftest.h (json_tunings_tests): Declare. * config/aarch64/aarch64-json-schema.h: New file. * config/aarch64/aarch64-json-tunings-parser.cc: New file. * config/aarch64/aarch64-json-tunings-parser.h: New file. --- gcc/config.gcc | 2 +- gcc/config/aarch64/aarch64-json-schema.h | 261 ++++++ .../aarch64/aarch64-json-tunings-parser.cc | 837 ++++++++++++++++++ .../aarch64/aarch64-json-tunings-parser.h | 29 + gcc/config/aarch64/aarch64.cc | 5 + gcc/config/aarch64/aarch64.opt | 4 + gcc/config/aarch64/t-aarch64 | 10 + gcc/selftest-run-tests.cc | 1 + gcc/selftest.h | 1 + 9 files changed, 1149 insertions(+), 1 deletion(-) create mode 100644 gcc/config/aarch64/aarch64-json-schema.h create mode 100644 gcc/config/aarch64/aarch64-json-tunings-parser.cc create mode 100644 gcc/config/aarch64/aarch64-json-tunings-parser.h diff --git a/gcc/config.gcc b/gcc/config.gcc index 4d23b578457..6b13574590a 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 aarch64-json-tunings-printer.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 aarch64-json-tunings-parser.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-schema.h b/gcc/config/aarch64/aarch64-json-schema.h new file mode 100644 index 00000000000..f839f9077fe --- /dev/null +++ b/gcc/config/aarch64/aarch64-json-schema.h @@ -0,0 +1,261 @@ +/* Raw JSON schema for the AArch64 tuning parameters. + 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_SCHEMA_H +#define AARCH64_JSON_SCHEMA_H + +static const char *schema_json = R"json( +{ + "tune_params": { + "insn_extra_cost": { + "alu": { + "arith": "int", + "logical": "int", + "shift": "int", + "shift_reg": "int", + "arith_shift": "int", + "arith_shift_reg": "int", + "log_shift": "int", + "log_shift_reg": "int", + "extend": "int", + "extend_arith": "int", + "bfi": "int", + "bfx": "int", + "clz": "int", + "rev": "int", + "non_exec": "int", + "non_exec_costs_exec": "boolean" + }, + "mult": [ + { + "simple": "int", + "flag_setting": "int", + "extend": "int", + "add": "int", + "extend_add": "int", + "idiv": "int" + }, + { + "simple": "int", + "flag_setting": "int", + "extend": "int", + "add": "int", + "extend_add": "int", + "idiv": "int" + } + ], + "ldst": { + "load": "int", + "load_sign_extend": "int", + "ldrd": "int", + "ldm_1st": "int", + "ldm_regs_per_insn_1st": "int", + "ldm_regs_per_insn_subsequent": "int", + "loadf": "int", + "loadd": "int", + "load_unaligned": "int", + "store": "int", + "strd": "int", + "stm_1st": "int", + "stm_regs_per_insn_1st": "int", + "stm_regs_per_insn_subsequent": "int", + "storef": "int", + "stored": "int", + "store_unaligned": "int", + "loadv": "int", + "storev": "int" + }, + "fp": [ + { + "div": "int", + "mult": "int", + "mult_addsub": "int", + "fma": "int", + "addsub": "int", + "fpconst": "int", + "neg": "int", + "compare": "int", + "widen": "int", + "narrow": "int", + "toint": "int", + "fromint": "int", + "roundint": "int" + }, + { + "div": "int", + "mult": "int", + "mult_addsub": "int", + "fma": "int", + "addsub": "int", + "fpconst": "int", + "neg": "int", + "compare": "int", + "widen": "int", + "narrow": "int", + "toint": "int", + "fromint": "int", + "roundint": "int" + } + ], + "vect": { + "alu": "int", + "mult": "int", + "movi": "int", + "dup": "int", + "extract": "int" + } + }, + "addr_cost": { + "addr_scale_costs": { + "hi": "int", + "si": "int", + "di": "int", + "ti": "int" + }, + "pre_modify": "int", + "post_modify": "int", + "post_modify_ld3_st3": "int", + "post_modify_ld4_st4": "int", + "register_offset": "int", + "register_sextend": "int", + "register_zextend": "int", + "imm_offset": "int" + }, + "regmove_cost": { + "GP2GP": "int", + "GP2FP": "int", + "FP2GP": "int", + "FP2FP": "int" + }, + "vec_costs": { + "scalar_int_stmt_cost": "int", + "scalar_fp_stmt_cost": "int", + "scalar_load_cost": "int", + "scalar_store_cost": "int", + "cond_taken_branch_cost": "int", + "cond_not_taken_branch_cost": "int", + "advsimd": { + "int_stmt_cost": "int", + "fp_stmt_cost": "int", + "ld2_st2_permute_cost": "int", + "ld3_st3_permute_cost": "int", + "ld4_st4_permute_cost": "int", + "permute_cost": "int", + "reduc_i8_cost": "int", + "reduc_i16_cost": "int", + "reduc_i32_cost": "int", + "reduc_i64_cost": "int", + "reduc_f16_cost": "int", + "reduc_f32_cost": "int", + "reduc_f64_cost": "int", + "store_elt_extra_cost": "int", + "vec_to_scalar_cost": "int", + "scalar_to_vec_cost": "int", + "align_load_cost": "int", + "unalign_load_cost": "int", + "unalign_store_cost": "int", + "store_cost": "int" + }, + "sve": { + "clast_cost": "uint", + "fadda_f16_cost": "uint", + "fadda_f32_cost": "uint", + "fadda_f64_cost": "uint", + "gather_load_x32_cost": "uint", + "gather_load_x64_cost": "uint", + "gather_load_x32_init_cost": "uint", + "gather_load_x64_init_cost": "uint", + "scatter_store_elt_cost": "uint" + }, + "issue_info": { + "scalar": { + "loads_stores_per_cycle": "uint", + "stores_per_cycle": "uint", + "general_ops_per_cycle": "uint", + "fp_simd_load_general_ops": "uint", + "fp_simd_store_general_ops": "uint" + }, + "advsimd": { + "loads_stores_per_cycle": "uint", + "stores_per_cycle": "uint", + "general_ops_per_cycle": "uint", + "fp_simd_load_general_ops": "uint", + "fp_simd_store_general_ops": "uint", + "ld2_st2_general_ops": "uint", + "ld3_st3_general_ops": "uint", + "ld4_st4_general_ops": "uint" + }, + "sve": { + "loads_stores_per_cycle": "uint", + "stores_per_cycle": "uint", + "general_ops_per_cycle": "uint", + "fp_simd_load_general_ops": "uint", + "fp_simd_store_general_ops": "uint", + "ld2_st2_general_ops": "uint", + "ld3_st3_general_ops": "uint", + "ld4_st4_general_ops": "uint", + "pred_ops_per_cycle": "uint", + "while_pred_ops": "uint", + "int_cmp_pred_ops": "uint", + "fp_cmp_pred_ops": "uint", + "gather_scatter_pair_general_ops": "uint", + "gather_scatter_pair_pred_ops": "uint" + } + } + }, + "branch_costs": { "predictable": "int", "unpredictable": "int" }, + "approx_modes": { "division": "int", "sqrt": "int", "recip_sqrt": "int" }, + "sve_width": "uint", + "memmov_cost": { + "load_int": "int", + "store_int": "int", + "load_fp": "int", + "store_fp": "int", + "load_pred": "int", + "store_pred": "int" + }, + "issue_rate": "int", + "fusible_ops": "uint", + "function_align": "string", + "jump_align": "string", + "loop_align": "string", + "int_reassoc_width": "int", + "fp_reassoc_width": "int", + "fma_reassoc_width": "int", + "vec_reassoc_width": "int", + "min_div_recip_mul_sf": "int", + "min_div_recip_mul_df": "int", + "max_case_values": "uint", + "autoprefetcher_model": "string", + "extra_tuning_flags": "uint", + "prefetch": { + "num_slots": "int", + "l1_cache_size":"int", + "l1_cache_line_size": "int", + "l2_cache_size":"int", + "prefetch_dynamic_strides": "boolean", + "minimum_stride": "int", + "default_opt_level": "int" + }, + "ldp_policy_model": "string", + "stp_policy_model": "string" + } +})json"; + +#endif \ No newline at end of file diff --git a/gcc/config/aarch64/aarch64-json-tunings-parser.cc b/gcc/config/aarch64/aarch64-json-tunings-parser.cc new file mode 100644 index 00000000000..0d945179652 --- /dev/null +++ b/gcc/config/aarch64/aarch64-json-tunings-parser.cc @@ -0,0 +1,837 @@ +/* Routines to parse the AArch64 tuning parameters from 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_STRING +#define INCLUDE_VECTOR +#include <iostream> +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "diagnostic-core.h" +#include "json-parsing.h" +#include "aarch64-json-schema.h" +#include "aarch64-json-tunings-parser.h" +#include "aarch64-protos.h" +#include "config/arm/aarch-common-protos.h" +#include "selftest.h" + +#define PARSE_INTEGER_FIELD(obj, key, member) \ + if ((obj)->get ((key))) \ + (member) = extract_integer ((obj)->get ((key))) + +#define PARSE_BOOLEAN_FIELD(obj, key, member) \ + if ((obj)->get ((key))) \ + (member) = extract_boolean ((obj)->get ((key))) + +#define PARSE_STRING_FIELD(obj, key, member) \ + if ((obj)->get ((key))) \ + (member) = extract_string ((obj)->get ((key))) + +char * +extract_string (const json::value *val) +{ + if (val && val->get_kind () == json::JSON_STRING) + { + const json::string *string_val = static_cast<const json::string *> (val); + char *result = new char[string_val->get_length () + 1]; + strcpy (result, string_val->get_string ()); + return result; + } + else + { + warning (0, "expected a string but got something else or NULL"); + return nullptr; + } +} + +int +extract_integer (const json::value *val) +{ + if (val && val->get_kind () == json::JSON_INTEGER) + { + const json::integer_number *int_val + = static_cast<const json::integer_number *> (val); + long value = int_val->get (); + if (value > INT_MAX) + { + error ("value exceeds %<INT_MAX%>"); + return 0; + } + return value; + } + else + { + warning (0, "expected an integer value but got something else or NULL"); + return 0; + } +} + +bool +extract_boolean (const json::value *val) +{ + if (val + && (val->get_kind () == json::JSON_TRUE + || val->get_kind () == json::JSON_FALSE)) + { + const json::literal *literal_val + = static_cast<const json::literal *> (val); + return (literal_val->get_kind () == json::JSON_TRUE); + } + else + { + warning (0, "expected a boolean value but got something else or NULL"); + return false; + } +} + +static void +parse_autoprefetcher_model (const json::object *jo, std::string key, + tune_params::aarch64_autoprefetch_model &model) +{ + json::value *field_value = jo->get (key.c_str ()); + if (field_value) + { + const char *field_string + = static_cast<json::string *> (field_value)->get_string (); + + if (strcmp (field_string, "AUTOPREFETCHER_OFF") == 0) + model = tune_params::AUTOPREFETCHER_OFF; + else if (strcmp (field_string, "AUTOPREFETCHER_WEAK") == 0) + model = tune_params::AUTOPREFETCHER_WEAK; + else if (strcmp (field_string, "AUTOPREFETCHER_STRONG") == 0) + model = tune_params::AUTOPREFETCHER_STRONG; + else + { + warning (0, "autoprefetch model not recognized, defaulting to " + "%<AUTOPREFETCHER_OFF%>"); + model = tune_params::AUTOPREFETCHER_OFF; + } + } +} + +static void +parse_aarch64_ldp_stp_policy (const json::object *jo, std::string key, + aarch64_ldp_stp_policy &policy) +{ + json::value *field_value = jo->get (key.c_str ()); + if (field_value) + { + const char *field_string + = static_cast<json::string *> (field_value)->get_string (); + + if (strcmp (field_string, "AARCH64_LDP_STP_POLICY_DEFAULT") == 0) + policy = AARCH64_LDP_STP_POLICY_DEFAULT; + else if (strcmp (field_string, "AARCH64_LDP_STP_POLICY_ALIGNED") == 0) + policy = AARCH64_LDP_STP_POLICY_ALIGNED; + else if (strcmp (field_string, "AARCH64_LDP_STP_POLICY_ALWAYS") == 0) + policy = AARCH64_LDP_STP_POLICY_ALWAYS; + else if (strcmp (field_string, "AARCH64_LDP_STP_POLICY_NEVER") == 0) + policy = AARCH64_LDP_STP_POLICY_NEVER; + else + { + warning (0, "ldp stp policy not recognized, defaulting to " + "%<AARCH64_LDP_STP_POLICY_DEFAULT%>"); + policy = AARCH64_LDP_STP_POLICY_DEFAULT; + } + } +} + +template <typename ParserFunc, typename StructType> +static void +parse_nested_object (const json::object *parent_obj, const char *key, + ParserFunc parser, StructType &target) +{ + const json::value *nested_value = parent_obj->get (key); + if (nested_value && nested_value->get_kind () == json::JSON_OBJECT) + { + const json::object *nested_obj + = static_cast<const json::object *> (nested_value); + parser (nested_obj, target); + } +} + +static void +parse_addr_scale_costs (const json::object *jo, + scale_addr_mode_cost &addr_scale_costs) +{ + PARSE_INTEGER_FIELD (jo, "hi", addr_scale_costs.hi); + PARSE_INTEGER_FIELD (jo, "si", addr_scale_costs.si); + PARSE_INTEGER_FIELD (jo, "di", addr_scale_costs.di); + PARSE_INTEGER_FIELD (jo, "ti", addr_scale_costs.ti); +} + +static void +parse_alu_cost_table (const json::object *jo, alu_cost_table &alu) +{ + PARSE_INTEGER_FIELD (jo, "arith", alu.arith); + PARSE_INTEGER_FIELD (jo, "logical", alu.logical); + PARSE_INTEGER_FIELD (jo, "shift", alu.shift); + PARSE_INTEGER_FIELD (jo, "shift_reg", alu.shift_reg); + PARSE_INTEGER_FIELD (jo, "arith_shift", alu.arith_shift); + PARSE_INTEGER_FIELD (jo, "arith_shift_reg", alu.arith_shift_reg); + PARSE_INTEGER_FIELD (jo, "log_shift", alu.log_shift); + PARSE_INTEGER_FIELD (jo, "log_shift_reg", alu.log_shift_reg); + PARSE_INTEGER_FIELD (jo, "extend", alu.extend); + PARSE_INTEGER_FIELD (jo, "extend_arith", alu.extend_arith); + PARSE_INTEGER_FIELD (jo, "bfi", alu.bfi); + PARSE_INTEGER_FIELD (jo, "bfx", alu.bfx); + PARSE_INTEGER_FIELD (jo, "clz", alu.clz); + PARSE_INTEGER_FIELD (jo, "rev", alu.rev); + PARSE_INTEGER_FIELD (jo, "non_exec", alu.non_exec); + PARSE_BOOLEAN_FIELD (jo, "non_exec_costs_exec", alu.non_exec_costs_exec); +} + +static void +parse_mult_cost (const json::object *jo, mult_cost_table &mult) +{ + PARSE_INTEGER_FIELD (jo, "simple", mult.simple); + PARSE_INTEGER_FIELD (jo, "flag_setting", mult.flag_setting); + PARSE_INTEGER_FIELD (jo, "extend", mult.extend); + PARSE_INTEGER_FIELD (jo, "add", mult.add); + PARSE_INTEGER_FIELD (jo, "extend_add", mult.extend_add); + PARSE_INTEGER_FIELD (jo, "idiv", mult.idiv); +} + +static void +parse_ldst_cost_table (const json::object *jo, mem_cost_table &ldst) +{ + PARSE_INTEGER_FIELD (jo, "load", ldst.load); + PARSE_INTEGER_FIELD (jo, "load_sign_extend", ldst.load_sign_extend); + PARSE_INTEGER_FIELD (jo, "ldrd", ldst.ldrd); + PARSE_INTEGER_FIELD (jo, "ldm_1st", ldst.ldm_1st); + PARSE_INTEGER_FIELD (jo, "ldm_regs_per_insn_1st", ldst.ldm_regs_per_insn_1st); + PARSE_INTEGER_FIELD (jo, "ldm_regs_per_insn_subsequent", + ldst.ldm_regs_per_insn_subsequent); + PARSE_INTEGER_FIELD (jo, "loadf", ldst.loadf); + PARSE_INTEGER_FIELD (jo, "loadd", ldst.loadd); + PARSE_INTEGER_FIELD (jo, "load_unaligned", ldst.load_unaligned); + PARSE_INTEGER_FIELD (jo, "store", ldst.store); + PARSE_INTEGER_FIELD (jo, "strd", ldst.strd); + PARSE_INTEGER_FIELD (jo, "stm_1st", ldst.stm_1st); + PARSE_INTEGER_FIELD (jo, "stm_regs_per_insn_1st", ldst.stm_regs_per_insn_1st); + PARSE_INTEGER_FIELD (jo, "stm_regs_per_insn_subsequent", + ldst.stm_regs_per_insn_subsequent); + PARSE_INTEGER_FIELD (jo, "storef", ldst.storef); + PARSE_INTEGER_FIELD (jo, "stored", ldst.stored); + PARSE_INTEGER_FIELD (jo, "store_unaligned", ldst.store_unaligned); + PARSE_INTEGER_FIELD (jo, "loadv", ldst.loadv); + PARSE_INTEGER_FIELD (jo, "storev", ldst.storev); +} + +static void +parse_fp_cost_table (const json::object *jo, fp_cost_table &fp) +{ + PARSE_INTEGER_FIELD (jo, "div", fp.div); + PARSE_INTEGER_FIELD (jo, "mult", fp.mult); + PARSE_INTEGER_FIELD (jo, "mult_addsub", fp.mult_addsub); + PARSE_INTEGER_FIELD (jo, "fma", fp.fma); + PARSE_INTEGER_FIELD (jo, "addsub", fp.addsub); + PARSE_INTEGER_FIELD (jo, "fpconst", fp.fpconst); + PARSE_INTEGER_FIELD (jo, "neg", fp.neg); + PARSE_INTEGER_FIELD (jo, "compare", fp.compare); + PARSE_INTEGER_FIELD (jo, "widen", fp.widen); + PARSE_INTEGER_FIELD (jo, "narrow", fp.narrow); + PARSE_INTEGER_FIELD (jo, "toint", fp.toint); + PARSE_INTEGER_FIELD (jo, "fromint", fp.fromint); + PARSE_INTEGER_FIELD (jo, "roundint", fp.roundint); +} + +static void +parse_vect_cost_table (const json::object *jo, vector_cost_table &vect) +{ + PARSE_INTEGER_FIELD (jo, "alu", vect.alu); + PARSE_INTEGER_FIELD (jo, "mult", vect.mult); + PARSE_INTEGER_FIELD (jo, "movi", vect.movi); + PARSE_INTEGER_FIELD (jo, "dup", vect.dup); + PARSE_INTEGER_FIELD (jo, "extract", vect.extract); +} + +static void +parse_insn_extra_cost (const json::object *jo, cpu_cost_table &insn_extra_cost) +{ + parse_nested_object (jo, "alu", parse_alu_cost_table, insn_extra_cost.alu); + + const json::value *mult_array = jo->get ("mult"); + if (mult_array && mult_array->get_kind () == json::JSON_ARRAY) + { + const json::array *mults = static_cast<const json::array *> (mult_array); + for (size_t i = 0; i < mults->size (); ++i) + { + parse_mult_cost (static_cast<const json::object *> (mults->get (i)), + insn_extra_cost.mult[i]); + } + } + + parse_nested_object (jo, "ldst", parse_ldst_cost_table, insn_extra_cost.ldst); + + const json::value *fp_array = jo->get ("fp"); + if (fp_array && fp_array->get_kind () == json::JSON_ARRAY) + { + const json::array *fps = static_cast<const json::array *> (fp_array); + for (size_t i = 0; i < fps->size (); ++i) + { + parse_fp_cost_table (static_cast<const json::object *> (fps->get (i)), + insn_extra_cost.fp[i]); + } + } + + parse_nested_object (jo, "vect", parse_vect_cost_table, insn_extra_cost.vect); +} + +static void +parse_addr_cost (const json::object *jo, cpu_addrcost_table &addr_cost) +{ + parse_nested_object (jo, "addr_scale_costs", parse_addr_scale_costs, + addr_cost.addr_scale_costs); + + PARSE_INTEGER_FIELD (jo, "pre_modify", addr_cost.pre_modify); + PARSE_INTEGER_FIELD (jo, "post_modify", addr_cost.post_modify); + PARSE_INTEGER_FIELD (jo, "post_modify_ld3_st3", + addr_cost.post_modify_ld3_st3); + PARSE_INTEGER_FIELD (jo, "post_modify_ld4_st4", + addr_cost.post_modify_ld4_st4); + PARSE_INTEGER_FIELD (jo, "register_offset", addr_cost.register_offset); + PARSE_INTEGER_FIELD (jo, "register_sextend", addr_cost.register_sextend); + PARSE_INTEGER_FIELD (jo, "register_zextend", addr_cost.register_zextend); + PARSE_INTEGER_FIELD (jo, "imm_offset", addr_cost.imm_offset); +} + +static void +parse_advsimd_costs (const json::object *jo, advsimd_vec_cost &advsimd) +{ + PARSE_INTEGER_FIELD (jo, "int_stmt_cost", advsimd.int_stmt_cost); + PARSE_INTEGER_FIELD (jo, "fp_stmt_cost", advsimd.fp_stmt_cost); + PARSE_INTEGER_FIELD (jo, "ld2_st2_permute_cost", + advsimd.ld2_st2_permute_cost); + PARSE_INTEGER_FIELD (jo, "ld3_st3_permute_cost", + advsimd.ld3_st3_permute_cost); + PARSE_INTEGER_FIELD (jo, "ld4_st4_permute_cost", + advsimd.ld4_st4_permute_cost); + PARSE_INTEGER_FIELD (jo, "permute_cost", advsimd.permute_cost); + PARSE_INTEGER_FIELD (jo, "reduc_i8_cost", advsimd.reduc_i8_cost); + PARSE_INTEGER_FIELD (jo, "reduc_i16_cost", advsimd.reduc_i16_cost); + PARSE_INTEGER_FIELD (jo, "reduc_i32_cost", advsimd.reduc_i32_cost); + PARSE_INTEGER_FIELD (jo, "reduc_i64_cost", advsimd.reduc_i64_cost); + PARSE_INTEGER_FIELD (jo, "reduc_f16_cost", advsimd.reduc_f16_cost); + PARSE_INTEGER_FIELD (jo, "reduc_f32_cost", advsimd.reduc_f32_cost); + PARSE_INTEGER_FIELD (jo, "reduc_f64_cost", advsimd.reduc_f64_cost); + PARSE_INTEGER_FIELD (jo, "store_elt_extra_cost", + advsimd.store_elt_extra_cost); + PARSE_INTEGER_FIELD (jo, "vec_to_scalar_cost", advsimd.vec_to_scalar_cost); + PARSE_INTEGER_FIELD (jo, "scalar_to_vec_cost", advsimd.scalar_to_vec_cost); + PARSE_INTEGER_FIELD (jo, "align_load_cost", advsimd.align_load_cost); + PARSE_INTEGER_FIELD (jo, "unalign_load_cost", advsimd.unalign_load_cost); + PARSE_INTEGER_FIELD (jo, "unalign_store_cost", advsimd.unalign_store_cost); + PARSE_INTEGER_FIELD (jo, "store_cost", advsimd.store_cost); +} + +static void +parse_sve_costs (const json::object *jo, sve_vec_cost &sve) +{ + PARSE_INTEGER_FIELD (jo, "clast_cost", sve.clast_cost); + PARSE_INTEGER_FIELD (jo, "fadda_f16_cost", sve.fadda_f16_cost); + PARSE_INTEGER_FIELD (jo, "fadda_f32_cost", sve.fadda_f32_cost); + PARSE_INTEGER_FIELD (jo, "fadda_f64_cost", sve.fadda_f64_cost); + PARSE_INTEGER_FIELD (jo, "gather_load_x32_cost", sve.gather_load_x32_cost); + PARSE_INTEGER_FIELD (jo, "gather_load_x64_cost", sve.gather_load_x64_cost); + PARSE_INTEGER_FIELD (jo, "gather_load_x32_init_cost", + sve.gather_load_x32_init_cost); + PARSE_INTEGER_FIELD (jo, "gather_load_x64_init_cost", + sve.gather_load_x64_init_cost); + PARSE_INTEGER_FIELD (jo, "scatter_store_elt_cost", + sve.scatter_store_elt_cost); +} + +static void +parse_issue_scalar (const json::object *jo, aarch64_base_vec_issue_info &scalar) +{ + PARSE_INTEGER_FIELD (jo, "loads_stores_per_cycle", + scalar.loads_stores_per_cycle); + PARSE_INTEGER_FIELD (jo, "stores_per_cycle", scalar.stores_per_cycle); + PARSE_INTEGER_FIELD (jo, "general_ops_per_cycle", + scalar.general_ops_per_cycle); + PARSE_INTEGER_FIELD (jo, "fp_simd_load_general_ops", + scalar.fp_simd_load_general_ops); + PARSE_INTEGER_FIELD (jo, "fp_simd_store_general_ops", + scalar.fp_simd_store_general_ops); +} + +static void +parse_issue_advsimd (const json::object *jo, + aarch64_simd_vec_issue_info &advsimd) +{ + PARSE_INTEGER_FIELD (jo, "loads_stores_per_cycle", + advsimd.loads_stores_per_cycle); + PARSE_INTEGER_FIELD (jo, "stores_per_cycle", advsimd.stores_per_cycle); + PARSE_INTEGER_FIELD (jo, "general_ops_per_cycle", + advsimd.general_ops_per_cycle); + PARSE_INTEGER_FIELD (jo, "fp_simd_load_general_ops", + advsimd.fp_simd_load_general_ops); + PARSE_INTEGER_FIELD (jo, "fp_simd_store_general_ops", + advsimd.fp_simd_store_general_ops); + PARSE_INTEGER_FIELD (jo, "ld2_st2_general_ops", advsimd.ld2_st2_general_ops); + PARSE_INTEGER_FIELD (jo, "ld3_st3_general_ops", advsimd.ld3_st3_general_ops); + PARSE_INTEGER_FIELD (jo, "ld4_st4_general_ops", advsimd.ld4_st4_general_ops); +} + +static void +parse_issue_sve (const json::object *jo, aarch64_sve_vec_issue_info &sve) +{ + PARSE_INTEGER_FIELD (jo, "loads_stores_per_cycle", + sve.loads_stores_per_cycle); + PARSE_INTEGER_FIELD (jo, "stores_per_cycle", sve.stores_per_cycle); + PARSE_INTEGER_FIELD (jo, "general_ops_per_cycle", sve.general_ops_per_cycle); + PARSE_INTEGER_FIELD (jo, "fp_simd_load_general_ops", + sve.fp_simd_load_general_ops); + PARSE_INTEGER_FIELD (jo, "fp_simd_store_general_ops", + sve.fp_simd_store_general_ops); + PARSE_INTEGER_FIELD (jo, "ld2_st2_general_ops", sve.ld2_st2_general_ops); + PARSE_INTEGER_FIELD (jo, "ld3_st3_general_ops", sve.ld3_st3_general_ops); + PARSE_INTEGER_FIELD (jo, "ld4_st4_general_ops", sve.ld4_st4_general_ops); + PARSE_INTEGER_FIELD (jo, "pred_ops_per_cycle", sve.pred_ops_per_cycle); + PARSE_INTEGER_FIELD (jo, "while_pred_ops", sve.while_pred_ops); + PARSE_INTEGER_FIELD (jo, "int_cmp_pred_ops", sve.int_cmp_pred_ops); + PARSE_INTEGER_FIELD (jo, "fp_cmp_pred_ops", sve.fp_cmp_pred_ops); + PARSE_INTEGER_FIELD (jo, "gather_scatter_pair_general_ops", + sve.gather_scatter_pair_general_ops); + PARSE_INTEGER_FIELD (jo, "gather_scatter_pair_pred_ops", + sve.gather_scatter_pair_pred_ops); +} + +static void +parse_issue_info (const json::object *jo, aarch64_vec_issue_info &info) +{ + if (info.scalar) + parse_nested_object (jo, "scalar", parse_issue_scalar, *info.scalar); + if (info.advsimd) + parse_nested_object (jo, "advsimd", parse_issue_advsimd, *info.advsimd); + if (info.sve) + parse_nested_object (jo, "sve", parse_issue_sve, *info.sve); +} + +static void +parse_vec_costs (const json::object *jo, cpu_vector_cost &vec_costs) +{ + PARSE_INTEGER_FIELD (jo, "scalar_int_stmt_cost", + vec_costs.scalar_int_stmt_cost); + PARSE_INTEGER_FIELD (jo, "scalar_fp_stmt_cost", + vec_costs.scalar_fp_stmt_cost); + PARSE_INTEGER_FIELD (jo, "scalar_load_cost", vec_costs.scalar_load_cost); + PARSE_INTEGER_FIELD (jo, "scalar_store_cost", vec_costs.scalar_store_cost); + PARSE_INTEGER_FIELD (jo, "cond_taken_branch_cost", + vec_costs.cond_taken_branch_cost); + PARSE_INTEGER_FIELD (jo, "cond_not_taken_branch_cost", + vec_costs.cond_not_taken_branch_cost); + if (vec_costs.advsimd) + parse_nested_object (jo, "advsimd", parse_advsimd_costs, + *vec_costs.advsimd); + if (vec_costs.sve) + parse_nested_object (jo, "sve", parse_sve_costs, *vec_costs.sve); + if (vec_costs.issue_info) + parse_nested_object (jo, "issue_info", parse_issue_info, + *vec_costs.issue_info); +} + +static void +parse_branch_costs (const json::object *jo, cpu_branch_cost &branch_costs) +{ + PARSE_INTEGER_FIELD (jo, "predictable", branch_costs.predictable); + PARSE_INTEGER_FIELD (jo, "unpredictable", branch_costs.unpredictable); +} + +static void +parse_regmove_cost (const json::object *jo, cpu_regmove_cost ®move_cost) +{ + PARSE_INTEGER_FIELD (jo, "GP2GP", regmove_cost.GP2GP); + PARSE_INTEGER_FIELD (jo, "GP2FP", regmove_cost.GP2FP); + PARSE_INTEGER_FIELD (jo, "FP2GP", regmove_cost.FP2GP); + PARSE_INTEGER_FIELD (jo, "FP2FP", regmove_cost.FP2FP); +} + +static void +parse_approx_modes (const json::object *jo, cpu_approx_modes &approx_modes) +{ + PARSE_INTEGER_FIELD (jo, "division", approx_modes.division); + PARSE_INTEGER_FIELD (jo, "sqrt", approx_modes.sqrt); + PARSE_INTEGER_FIELD (jo, "recip_sqrt", approx_modes.recip_sqrt); +} + +static void +parse_memmov_cost (const json::object *jo, cpu_memmov_cost &memmov_cost) +{ + PARSE_INTEGER_FIELD (jo, "load_int", memmov_cost.load_int); + PARSE_INTEGER_FIELD (jo, "store_int", memmov_cost.store_int); + PARSE_INTEGER_FIELD (jo, "load_fp", memmov_cost.load_fp); + PARSE_INTEGER_FIELD (jo, "store_fp", memmov_cost.store_fp); + PARSE_INTEGER_FIELD (jo, "load_pred", memmov_cost.load_pred); + PARSE_INTEGER_FIELD (jo, "store_pred", memmov_cost.store_pred); +} + +static void +parse_prefetch (const json::object *jo, cpu_prefetch_tune &prefetch) +{ + PARSE_INTEGER_FIELD (jo, "num_slots", prefetch.num_slots); + PARSE_INTEGER_FIELD (jo, "l1_cache_size", prefetch.l1_cache_size); + PARSE_INTEGER_FIELD (jo, "l1_cache_line_size", prefetch.l1_cache_line_size); + PARSE_INTEGER_FIELD (jo, "l2_cache_size", prefetch.l2_cache_size); + PARSE_BOOLEAN_FIELD (jo, "prefetch_dynamic_strides", + prefetch.prefetch_dynamic_strides); + PARSE_INTEGER_FIELD (jo, "minimum_stride", prefetch.minimum_stride); + PARSE_INTEGER_FIELD (jo, "default_opt_level", prefetch.default_opt_level); +} + +static void +parse_tunings (const json::object *jo, tune_params &tune) +{ + if (tune.insn_extra_cost) + parse_nested_object (jo, "insn_extra_cost", parse_insn_extra_cost, + *tune.insn_extra_cost); + if (tune.regmove_cost) + parse_nested_object (jo, "regmove_cost", parse_regmove_cost, + *tune.regmove_cost); + if (tune.addr_cost) + parse_nested_object (jo, "addr_cost", parse_addr_cost, *tune.addr_cost); + if (tune.vec_costs) + parse_nested_object (jo, "vec_costs", parse_vec_costs, *tune.vec_costs); + if (tune.branch_costs) + parse_nested_object (jo, "branch_costs", parse_branch_costs, + *tune.branch_costs); + if (tune.approx_modes) + parse_nested_object (jo, "approx_modes", parse_approx_modes, + *tune.approx_modes); + PARSE_INTEGER_FIELD (jo, "sve_width", tune.sve_width); + parse_nested_object (jo, "memmov_cost", parse_memmov_cost, tune.memmov_cost); + PARSE_INTEGER_FIELD (jo, "issue_rate", tune.issue_rate); + PARSE_INTEGER_FIELD (jo, "fusible_ops", tune.fusible_ops); + PARSE_STRING_FIELD (jo, "function_align", tune.function_align); + PARSE_STRING_FIELD (jo, "jump_align", tune.jump_align); + PARSE_STRING_FIELD (jo, "loop_align", tune.loop_align); + PARSE_INTEGER_FIELD (jo, "int_reassoc_width", tune.int_reassoc_width); + PARSE_INTEGER_FIELD (jo, "fp_reassoc_width", tune.fp_reassoc_width); + PARSE_INTEGER_FIELD (jo, "fma_reassoc_width", tune.fma_reassoc_width); + PARSE_INTEGER_FIELD (jo, "vec_reassoc_width", tune.vec_reassoc_width); + PARSE_INTEGER_FIELD (jo, "min_div_recip_mul_sf", tune.min_div_recip_mul_sf); + PARSE_INTEGER_FIELD (jo, "min_div_recip_mul_df", tune.min_div_recip_mul_df); + PARSE_INTEGER_FIELD (jo, "max_case_values", tune.max_case_values); + parse_autoprefetcher_model (jo, "autoprefetcher_model", + tune.autoprefetcher_model); + PARSE_INTEGER_FIELD (jo, "extra_tuning_flags", tune.extra_tuning_flags); + if (tune.prefetch) + parse_nested_object (jo, "prefetch", parse_prefetch, *tune.prefetch); + parse_aarch64_ldp_stp_policy (jo, "ldp_policy_model", tune.ldp_policy_model); + parse_aarch64_ldp_stp_policy (jo, "stp_policy_model", tune.stp_policy_model); +} + +static bool +validate_and_traverse (const json::object *json_obj, + const json::object *schema_obj, + const std::string &parent_key = "") +{ + for (const auto &json_entry : json_obj->get_map ()) + { + const std::string &key = json_entry.first; + const json::value *json_value = json_entry.second; + + std::string full_key = parent_key.empty () ? key : parent_key + "." + key; + + const json::value *schema_value = schema_obj->get (key.c_str ()); + if (!schema_value) + { + warning (0, "key %qs is not a tuning parameter, skipping", + full_key.c_str ()); + continue; + } + + if (schema_value->get_kind () == json::JSON_OBJECT) + { + if (json_value->get_kind () != json::JSON_OBJECT) + { + error ("key %qs expected to be an object", full_key.c_str ()); + return false; + } + + const auto *sub_schema_obj + = static_cast<const json::object *> (schema_value); + const auto *sub_json_obj + = static_cast<const json::object *> (json_value); + if (!validate_and_traverse (sub_json_obj, sub_schema_obj, full_key)) + return false; + } + else if (schema_value->get_kind () == json::JSON_ARRAY) + { + if (json_value->get_kind () != json::JSON_ARRAY) + { + error ("key %qs expected to be an array", full_key.c_str ()); + + return false; + } + } + else if (schema_value->get_kind () == json::JSON_STRING) + { + const auto *schema_type_str + = static_cast<const json::string *> (schema_value)->get_string (); + + if (strcmp (schema_type_str, "int") == 0) + { + if (json_value->get_kind () != json::JSON_INTEGER) + { + error ("key %qs expected to be an integer", + full_key.c_str ()); + return false; + } + } + else if (strcmp (schema_type_str, "uint") == 0) + { + if (json_value->get_kind () != json::JSON_INTEGER + || extract_integer (json_value) < 0) + { + error ("key %qs expected to be an unsigned integer", + full_key.c_str ()); + return false; + } + } + else if (strcmp (schema_type_str, "string") == 0) + { + if (json_value->get_kind () != json::JSON_STRING) + { + error ("key %qs expected to be a string", full_key.c_str ()); + return false; + } + } + else if (strcmp (schema_type_str, "boolean") == 0) + { + if (json_value->get_kind () != json::JSON_TRUE + && json_value->get_kind () != json::JSON_FALSE) + { + error ("key %qs expected to be a boolean (true/false)", + full_key.c_str ()); + return false; + } + } + else + { + error ("key %qs has unsupported type", full_key.c_str ()); + return false; + } + } + else + { + error ("key %qs has unexpected format in schema", full_key.c_str ()); + return false; + } + } + return true; +} + +static std::unique_ptr<std::vector<char>> +read_file (const char *path) +{ + FILE *f_in = fopen (path, "r"); + if (!f_in) + { + error ("could not open file %s", path); + return nullptr; + } + + auto result = std::make_unique<std::vector<char>> (); + char buf[4096]; + + while (size_t iter_sz_in = fread (buf, 1, sizeof (buf), f_in)) + result->insert (result->end (), buf, buf + iter_sz_in); + + if (!feof (f_in)) + { + error ("error reading file %s", path); + fclose (f_in); + return nullptr; + } + + fclose (f_in); + result->push_back ('\0'); + return result; +} + + void +aarch64_load_tuning_params_from_json_string (const char *json_string, + const char *schema_string, + struct tune_params *tune) +{ + json::parser_result_t data_result + = json::parse_utf8_string (strlen (json_string), json_string, false, + nullptr); + + if (auto json_err = data_result.m_err.get ()) + { + error ("error parsing JSON data: %s", json_err->get_msg ()); + return; + } + + const std::unique_ptr<json::value> &root = data_result.m_val; + if (!root || root->get_kind () != json::JSON_OBJECT) + { + warning (0, "no JSON object found in the provided data"); + return; + } + const json::object *root_obj + = static_cast<const json::object *> (root.get ()); + + json::parser_result_t schema_result ( + json::parse_utf8_string (strlen (schema_string), schema_string, false, + nullptr)); + + if (auto json_err = schema_result.m_err.get ()) + { + error ("error parsing JSON schema: %s", json_err->get_msg ()); + return; + } + + const std::unique_ptr<json::value> &schema_root = schema_result.m_val; + if (!schema_root || schema_root->get_kind () != json::JSON_OBJECT) + { + error ("no JSON object found in the provided schema"); + return; + } + const json::object *schema_obj + = static_cast<const json::object *> (schema_root.get ()); + + json::object *jo + = static_cast<json::object *> (root_obj->get ("tune_params")); + if (!jo) + { + warning (0, "key %<tune_params%> not found in JSON data"); + return; + } + + if (!validate_and_traverse (root_obj, schema_obj)) + { + error ("validation failed for the provided JSON data"); + return; + } + + parse_tunings (jo, *tune); + return; +} + +void +aarch64_load_tuning_params_from_json (const char *data_filename, + struct tune_params *tune) +{ + std::unique_ptr<std::vector<char>> json_data = read_file (data_filename); + if (!json_data || !json_data->data ()) + { + error ("cannot read JSON data in %s", data_filename); + return; + } + aarch64_load_tuning_params_from_json_string ( + (const char *) json_data->data (), schema_json, tune); +} + +namespace selftest { + +void +test_json_integers () +{ + const char *test_json = R"json({ + "tune_params": { + "sve_width": 256, + "issue_rate": 4 + } + })json"; + + tune_params params; + + aarch64_load_tuning_params_from_json_string (test_json, schema_json, ¶ms); + + ASSERT_EQ (params.sve_width, 256); + ASSERT_EQ (params.issue_rate, 4); +} + +void +test_json_boolean () +{ + const char *test_json = R"json({ + "tune_params": { + "insn_extra_cost": { + "alu": { + "non_exec_costs_exec": false + } + } + } + })json"; + + tune_params params; + params.insn_extra_cost = new cpu_cost_table; + + aarch64_load_tuning_params_from_json_string (test_json, schema_json, ¶ms); + + ASSERT_EQ (params.insn_extra_cost->alu.non_exec_costs_exec, false); + + delete params.insn_extra_cost; +} + +void +test_json_strings () +{ + const char *test_json = R"json({ + "tune_params": { + "function_align": "16", + "jump_align": "2", + "loop_align": "8" + } + })json"; + + tune_params params; + + aarch64_load_tuning_params_from_json_string (test_json, schema_json, ¶ms); + + ASSERT_STREQ (params.function_align, "16"); + ASSERT_STREQ (params.jump_align, "2"); + ASSERT_STREQ (params.loop_align, "8"); +} + +void +test_json_enums () +{ + const char *test_json = R"json({ + "tune_params": { + "autoprefetcher_model": "AUTOPREFETCHER_OFF", + "ldp_policy_model": "AARCH64_LDP_STP_POLICY_NEVER", + "stp_policy_model": "AARCH64_LDP_STP_POLICY_DEFAULT" + } + })json"; + + tune_params params; + + aarch64_load_tuning_params_from_json_string (test_json, schema_json, ¶ms); + + ASSERT_EQ (params.autoprefetcher_model, tune_params::AUTOPREFETCHER_OFF); + ASSERT_EQ (params.ldp_policy_model, AARCH64_LDP_STP_POLICY_NEVER); + ASSERT_EQ (params.stp_policy_model, AARCH64_LDP_STP_POLICY_DEFAULT); +} + +void +json_tunings_tests () +{ + test_json_boolean (); + test_json_strings (); + test_json_enums (); +} + +} // namespace selftest diff --git a/gcc/config/aarch64/aarch64-json-tunings-parser.h b/gcc/config/aarch64/aarch64-json-tunings-parser.h new file mode 100644 index 00000000000..3c608ea497b --- /dev/null +++ b/gcc/config/aarch64/aarch64-json-tunings-parser.h @@ -0,0 +1,29 @@ +/* Routines to parse the AArch64 tuning parameters from 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_PARSER_H +#define AARCH64_JSON_TUNINGS_PARSER_H + +#include "aarch64-protos.h" + +void +aarch64_load_tuning_params_from_json (const char *data_filename, + struct tune_params *tune); + +#endif \ No newline at end of file diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 2bbed9d2e54..70dc27f2487 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -98,6 +98,7 @@ #include "ipa-fnsummary.h" #include "hash-map.h" #include "aarch64-json-tunings-printer.h" +#include "aarch64-json-tunings-parser.h" /* This file should be included last. */ #include "target-def.h" @@ -18580,6 +18581,10 @@ aarch64_override_options_internal (struct gcc_options *opts) /* Make a copy of the tuning parameters attached to the core, which we may later overwrite. */ aarch64_tune_params = *(tune->tune); + if (opts->x_muser_provided_CPU) + aarch64_load_tuning_params_from_json (opts->x_muser_provided_CPU, + &aarch64_tune_params); + if (tune->tune == &generic_tunings) aarch64_adjust_generic_arch_tuning (aarch64_tune_params); diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt index 4c8ea2eb323..50245cfcf19 100644 --- a/gcc/config/aarch64/aarch64.opt +++ b/gcc/config/aarch64/aarch64.opt @@ -192,6 +192,10 @@ fdump-tuning-model= Target RejectNegative Negative(fdump-tuning-model=) ToLower Joined Var(fdump_tuning_model) Dump current tuning model to a JSON file. +muser-provided-CPU= +Target RejectNegative Negative(muser-provided-CPU=) ToLower Joined Var(muser_provided_CPU) +User specific CPU tunings. + 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 c5002eab595..96685d19274 100644 --- a/gcc/config/aarch64/t-aarch64 +++ b/gcc/config/aarch64/t-aarch64 @@ -206,6 +206,16 @@ aarch64-json-tunings-printer.o: $(srcdir)/config/aarch64/aarch64-json-tunings-pr $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ $(srcdir)/config/aarch64/aarch64-json-tunings-printer.cc +aarch64-json-tunings-parser.o: $(srcdir)/config/aarch64/aarch64-json-tunings-parser.cc \ + $(CONFIG_H) $(SYSTEM_H) $(CORETYPES_H) $(TM_H) $(DIAGNOSTIC_CORE_H) \ + json-parsing.h \ + $(srcdir)/config/aarch64/aarch64-json-schema.h \ + $(srcdir)/config/aarch64/aarch64-json-tunings-parser.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-parser.cc + comma=, MULTILIB_OPTIONS = $(subst $(comma),/, $(patsubst %, mabi=%, $(subst $(comma),$(comma)mabi=,$(TM_MULTILIB_CONFIG)))) MULTILIB_DIRNAMES = $(subst $(comma), ,$(TM_MULTILIB_CONFIG)) diff --git a/gcc/selftest-run-tests.cc b/gcc/selftest-run-tests.cc index c4da84a275e..4d575595539 100644 --- a/gcc/selftest-run-tests.cc +++ b/gcc/selftest-run-tests.cc @@ -76,6 +76,7 @@ selftest::run_tests () opts_cc_tests (); json_cc_tests (); json_parser_cc_tests (); + json_tunings_tests (); cgraph_cc_tests (); optinfo_emit_json_cc_tests (); ordered_hash_map_tests_cc_tests (); diff --git a/gcc/selftest.h b/gcc/selftest.h index 5adfa908fd3..7baccadf19d 100644 --- a/gcc/selftest.h +++ b/gcc/selftest.h @@ -241,6 +241,7 @@ extern void hash_set_tests_cc_tests (); extern void input_cc_tests (); extern void json_cc_tests (); extern void lazy_diagnostic_path_cc_tests (); +extern void json_tunings_tests(); extern void json_parser_cc_tests (); extern void optinfo_emit_json_cc_tests (); extern void opts_cc_tests (); -- 2.44.0