Hi Tamar,

Ping.

Thanks,
Soumya

> On 28 Oct 2025, at 2:55 PM, Soumya AR <[email protected]> wrote:
> 
> 
> 
>> On 14 Oct 2025, at 9:07 PM, Tamar Christina <[email protected]> wrote:
>> 
>> External email: Use caution opening links or attachments
>> 
>> 
>>> -----Original Message-----
>>> From: Soumya AR <[email protected]>
>>> Sent: 13 October 2025 09:44
>>> To: Tamar Christina <[email protected]>
>>> Cc: [email protected]; Kyrylo Tkachov <[email protected]>;
>>> [email protected]; [email protected]
>>> Subject: Re: [v3 PATCH 4/6] aarch64: Enable parsing of user-provided
>>> AArch64 CPU tuning parameters
>>> Importance: High
>>> 
>>> 
>>> 
>>>> On 29 Sep 2025, at 5:29 PM, Tamar Christina <[email protected]>
>>> wrote:
>>>> 
>>>> External email: Use caution opening links or attachments
>>>> 
>>>> 
>>>> Hi Soumya,
>>>> 
>>>>> -----Original Message-----
>>>>> From: [email protected] <[email protected]>
>>>>> Sent: 25 August 2025 12:00
>>>>> To: [email protected]
>>>>> Cc: [email protected]; [email protected];
>>> [email protected]
>>>>> Subject: [v3 PATCH 4/6] aarch64: Enable parsing of user-provided AArch64
>>>>> CPU tuning parameters
>>>>> 
>>>>> From: Soumya AR <[email protected]>
>>>>> 
>>>>> 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 <[email protected]>
>>>>> 
>>>>> 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    | 902 ++++++++++++++++++
>>>>> .../aarch64/aarch64-json-tunings-parser.h     |  29 +
>>>>> gcc/config/aarch64/aarch64.cc                 |  16 +
>>>>> 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, 1225 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 698a7bb4b73..39790adb16a 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-
>>>>> early-ra.o aarch64-ldp-fusion.o aarch64-json-tunings-printer.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-
>>>>> 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..873756b01a5
>>>>> --- /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.
>>>> 
>>>> Same as the others the copyright year is missing.
>>>> 
>>> 
>>> I was confused about this too, currently all instances of
>>> "Copyright The GNU Toolchain Authors” in GCC don't mention the year.
>>> 
>>> Should we implement this in all files moving forward?
>>> 
>> 
>> I reached out to ask about this. It turns out that files contributed under 
>> DCO
>> don't need the dates. So this is fine.
>> 
>>> 
>>>> I'm still going through the code, but notice we don't write a
>>>> gcc version out in the json.  But the parser is rather unforgiving
>>>> to mismatch in expected formats.  (i.e. we ICE).
>>>> 
>>>> I think we should write out the version, and reject reading in any
>>>> jsons where the versions don't match with a friendly error message.
>>>> 
>>> 
>>> Thanks, this is a nice suggestion. I have a local working copy that now adds
>>> a metadata object to the schema.
>>> 
>>> Currently, it looks something like this:
>>> 
>>> {
>>> "metadata": {
>>>   "gcc_version": "string"
>>> },
>>> "tune_params": { ... }
>>> }
>>> 
>>> If need be, I can just remove the "metadata" object and directly have a
>>> gcc_version string in the root object. The former felt cleaner, let me know
>>> which you prefer.
>> 
>> I'm fine with this. I wonder if the gcc_version should be only major version?
>> Because we don't tend to change the structures on released versions, but
>> there if it breaks during trunk builds we can maybe just issue a warning?
>> 
>> What do you think?
>> 
> 
> Hi Tamar,
> 
> Yes, I prefer this as well. I'm attaching updated patches with the changes
> you suggested. I've also updated aarch64_run_selftests to call the parser
> self tests as suggested by Kyrill. 
> Attaching an interim updated patch series here. Will update with more changes
> once you are done reviewing. Thank you!
> 
> Best,
> Soumya
> 
>> I'll get through the last of this review this week.
>> 
>> Thanks,
>> Tamar
>>> 
>>> Thanks,
>>> Soumya
>>> 
>>>> Thanks,
>>>> Tamar
>>>> 
>>>>> +
>>>>> +   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": "int",
>>>>> +     "fadda_f16_cost": "int",
>>>>> +     "fadda_f32_cost": "int",
>>>>> +     "fadda_f64_cost": "int",
>>>>> +     "gather_load_x32_cost": "uint",
>>>>> +     "gather_load_x64_cost": "uint",
>>>>> +     "gather_load_x32_init_cost": "int",
>>>>> +     "gather_load_x64_init_cost": "int",
>>>>> +     "scatter_store_elt_cost": "int"
>>>>> +      },
>>>>> +      "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": "enum",
>>>>> +    "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": "enum",
>>>>> +    "stp_policy_model": "enum"
>>>>> +  }
>>>>> +})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..23e742d437f
>>>>> --- /dev/null
>>>>> +++ b/gcc/config/aarch64/aarch64-json-tunings-parser.cc
>>>>> @@ -0,0 +1,902 @@
>>>>> +/* 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
>>>>> +#define INCLUDE_TYPE_TRAITS
>>>>> +#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)                            
>>>>>       \
>>>>> +  {                                                                      
>>>>>       \
>>>>> +    const json::value *val = obj->get (key);                             
>>>>>       \
>>>>> +    if (val)                                                             
>>>>>       \
>>>>> +      member = extract_integer (val);                                    
>>>>>       \
>>>>> +  }
>>>>> +
>>>>> +#define PARSE_BOOLEAN_FIELD(obj, key, member)                            
>>>>>       \
>>>>> +  {                                                                      
>>>>>       \
>>>>> +    const json::value *val = obj->get (key);                             
>>>>>       \
>>>>> +    if (val)                                                             
>>>>>       \
>>>>> +      member = extract_boolean (val);                                    
>>>>>       \
>>>>> +  }
>>>>> +
>>>>> +#define PARSE_STRING_FIELD(obj, key, member)                             
>>>>>       \
>>>>> +  {                                                                      
>>>>>       \
>>>>> +    const json::value *val = obj->get (key);                             
>>>>>       \
>>>>> +    if (val)                                                             
>>>>>       \
>>>>> +      member = extract_string (val);                                     
>>>>>       \
>>>>> +  }
>>>>> +
>>>>> +#define PARSE_OBJECT(obj, key, member, parse_func)                       
>>>>>       \
>>>>> +  {                                                                      
>>>>>       \
>>>>> +    const json::value *field_value = obj->get (key);                     
>>>>>       \
>>>>> +    if (field_value)                                                     
>>>>>       \
>>>>> +      if (auto *field_obj = dyn_cast<const json::object *> 
>>>>> (field_value))      \
>>>>> +     parse_object_helper (field_obj, (member), (parse_func));            
>>>>>    \
>>>>> +  }
>>>>> +
>>>>> +#define PARSE_ARRAY_FIELD(obj, key, member, parse_func)                  
>>>>>       \
>>>>> +  {                                                                      
>>>>>       \
>>>>> +    const json::value *field_value = obj->get (key);                     
>>>>>       \
>>>>> +    if (field_value)                                                     
>>>>>       \
>>>>> +      if (auto *field_array = dyn_cast<const json::array *> 
>>>>> (field_value))     \
>>>>> +     for (size_t i = 0; i < field_array->size (); ++i)                   
>>>>>    \
>>>>> +       {                                                                 
>>>>>    \
>>>>> +         const json::value *elem = field_array->get (i);                 
>>>>>    \
>>>>> +         if (elem)                                                       
>>>>>    \
>>>>> +           if (auto *array_obj = dyn_cast<const json::object *> (elem))  
>>>>>    \
>>>>> +             parse_func (array_obj, member[i]);                          
>>>>>    \
>>>>> +       }                                                                 
>>>>>    \
>>>>> +  }
>>>>> +
>>>>> +#define PARSE_ENUM_FIELD(obj, key, member, mappings)                     
>>>>>       \
>>>>> +  parse_enum_field (obj, key, member, mappings,                          
>>>>>       \
>>>>> +                 sizeof (mappings) / sizeof (mappings[0]))
>>>>> +
>>>>> +/* Type alias for parse function pointer.  */
>>>>> +template <typename T>
>>>>> +using parse_func_type
>>>>> +  = void (*) (const json::object *,
>>>>> +           std::remove_const_t<std::remove_pointer_t<T>> &);
>>>>> +
>>>>> +/* Parse JSON object into non-pointer member type.  */
>>>>> +template <typename T>
>>>>> +static std::enable_if_t<!std::is_pointer<T>::value>
>>>>> +parse_object_helper (const json::object *field_obj, T &member,
>>>>> +                  parse_func_type<T> parse_func)
>>>>> +{
>>>>> +  parse_func (field_obj, member);
>>>>> +}
>>>>> +
>>>>> +/* Parse JSON object into a const pointer member by creating a temp
>>> copy.
>>>>> */
>>>>> +template <typename T>
>>>>> +static std::enable_if_t<std::is_pointer<T>::value
>>>>> +                     && std::is_const<std::remove_pointer_t<T>>::value>
>>>>> +parse_object_helper (const json::object *field_obj, T &member,
>>>>> +                  parse_func_type<T> parse_func)
>>>>> +{
>>>>> +  if (!member)
>>>>> +    return;
>>>>> +
>>>>> +  /* Use static storage for the non-const copy.
>>>>> +     This works because tune_params does not have nested structures of
>>> the
>>>>> +     same type, but has room for errors if we end up having pointers to 
>>>>> the
>>>>> +     same structure at some point.  */
>>>>> +  static bool already_initialized = false;
>>>>> +  if (already_initialized)
>>>>> +    {
>>>>> +      error ("static storage conflict - multiple pointer members of the "
>>>>> +          "same type cannot be parsed");
>>>>> +      return;
>>>>> +    }
>>>>> +  already_initialized = true;
>>>>> +  using NonConstType = std::remove_const_t<std::remove_pointer_t<T>>;
>>>>> +  static NonConstType new_obj = *member;
>>>>> +  parse_func (field_obj, new_obj);
>>>>> +  member = &new_obj;
>>>>> +}
>>>>> +
>>>>> +/* Extract string value from JSON, returning allocated C string.  */
>>>>> +char *
>>>>> +extract_string (const json::value *val)
>>>>> +{
>>>>> +  if (auto *string_val = dyn_cast<const json::string *> (val))
>>>>> +    return xstrdup (string_val->get_string ());
>>>>> +  warning (0, "expected a string but got something else or NULL");
>>>>> +  return nullptr;
>>>>> +}
>>>>> +
>>>>> +/* Extract integer value from JSON.  */
>>>>> +int
>>>>> +extract_integer (const json::value *val)
>>>>> +{
>>>>> +  if (auto *int_val = dyn_cast<const json::integer_number *> (val))
>>>>> +    {
>>>>> +      long value = int_val->get ();
>>>>> +      if (value > INT_MAX)
>>>>> +     {
>>>>> +       error ("value exceeds %<INT_MAX%>");
>>>>> +       return 0;
>>>>> +     }
>>>>> +      return value;
>>>>> +    }
>>>>> +  warning (0, "expected an integer value but got something else or 
>>>>> NULL");
>>>>> +  return 0;
>>>>> +}
>>>>> +
>>>>> +/* Extract boolean value from JSON literal.  */
>>>>> +bool
>>>>> +extract_boolean (const json::value *val)
>>>>> +{
>>>>> +  if (auto *literal_val = dyn_cast<const json::literal *> (val))
>>>>> +    {
>>>>> +      json::kind kind = literal_val->get_kind ();
>>>>> +      if (kind == json::JSON_TRUE || kind == json::JSON_FALSE)
>>>>> +     return (kind == json::JSON_TRUE);
>>>>> +    }
>>>>> +  warning (0, "expected a boolean value but got something else or NULL");
>>>>> +  return false;
>>>>> +}
>>>>> +
>>>>> +template <typename EnumType> struct enum_mapping
>>>>> +{
>>>>> +  const char *name;
>>>>> +  EnumType value;
>>>>> +};
>>>>> +
>>>>> +/* Parse JSON string field into enum value using string-to-enum mappings.
>>>>> */
>>>>> +template <typename EnumType>
>>>>> +static void
>>>>> +parse_enum_field (const json::object *jo, const std::string &key,
>>>>> +               EnumType &enum_var, const enum_mapping<EnumType>
>>>>> *mappings,
>>>>> +               size_t num_mappings)
>>>>> +{
>>>>> +  const json::value *field_value = jo->get (key.c_str ());
>>>>> +  if (!field_value)
>>>>> +    return;
>>>>> +
>>>>> +  auto *string_val = dyn_cast<const json::string *> (field_value);
>>>>> +  if (!string_val)
>>>>> +    {
>>>>> +      warning (0, "expected string for enum field %s", key.c_str ());
>>>>> +      enum_var = mappings[0].value;
>>>>> +      return;
>>>>> +    }
>>>>> +
>>>>> +  const char *field_string = string_val->get_string ();
>>>>> +  for (size_t i = 0; i < num_mappings; ++i)
>>>>> +    {
>>>>> +      if (strcmp (field_string, mappings[i].name) == 0)
>>>>> +     {
>>>>> +       enum_var = mappings[i].value;
>>>>> +       return;
>>>>> +     }
>>>>> +    }
>>>>> +
>>>>> +  warning (0, "%s not recognized, defaulting to %qs", key.c_str (),
>>>>> +        mappings[0].name);
>>>>> +  enum_var = mappings[0].value;
>>>>> +}
>>>>> +
>>>>> +/* Enum mappings for known tuning parameter enums.  */
>>>>> +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}};
>>>>> +
>>>>> +template <typename T>
>>>>> +static void
>>>>> +parse_insn_extra_cost_alu (const json::object *jo, T &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);
>>>>> +}
>>>>> +
>>>>> +template <typename T>
>>>>> +static void
>>>>> +parse_insn_extra_cost_mult_element (const json::object *jo, T
>>>>> &mult_element)
>>>>> +{
>>>>> +  PARSE_INTEGER_FIELD (jo, "simple", mult_element.simple);
>>>>> +  PARSE_INTEGER_FIELD (jo, "flag_setting", mult_element.flag_setting);
>>>>> +  PARSE_INTEGER_FIELD (jo, "extend", mult_element.extend);
>>>>> +  PARSE_INTEGER_FIELD (jo, "add", mult_element.add);
>>>>> +  PARSE_INTEGER_FIELD (jo, "extend_add", mult_element.extend_add);
>>>>> +  PARSE_INTEGER_FIELD (jo, "idiv", mult_element.idiv);
>>>>> +}
>>>>> +
>>>>> +template <typename T>
>>>>> +static void
>>>>> +parse_insn_extra_cost_ldst (const json::object *jo, T &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);
>>>>> +}
>>>>> +
>>>>> +template <typename T>
>>>>> +static void
>>>>> +parse_insn_extra_cost_fp_element (const json::object *jo, T
>>> &fp_element)
>>>>> +{
>>>>> +  PARSE_INTEGER_FIELD (jo, "div", fp_element.div);
>>>>> +  PARSE_INTEGER_FIELD (jo, "mult", fp_element.mult);
>>>>> +  PARSE_INTEGER_FIELD (jo, "mult_addsub", fp_element.mult_addsub);
>>>>> +  PARSE_INTEGER_FIELD (jo, "fma", fp_element.fma);
>>>>> +  PARSE_INTEGER_FIELD (jo, "addsub", fp_element.addsub);
>>>>> +  PARSE_INTEGER_FIELD (jo, "fpconst", fp_element.fpconst);
>>>>> +  PARSE_INTEGER_FIELD (jo, "neg", fp_element.neg);
>>>>> +  PARSE_INTEGER_FIELD (jo, "compare", fp_element.compare);
>>>>> +  PARSE_INTEGER_FIELD (jo, "widen", fp_element.widen);
>>>>> +  PARSE_INTEGER_FIELD (jo, "narrow", fp_element.narrow);
>>>>> +  PARSE_INTEGER_FIELD (jo, "toint", fp_element.toint);
>>>>> +  PARSE_INTEGER_FIELD (jo, "fromint", fp_element.fromint);
>>>>> +  PARSE_INTEGER_FIELD (jo, "roundint", fp_element.roundint);
>>>>> +}
>>>>> +
>>>>> +template <typename T>
>>>>> +static void
>>>>> +parse_insn_extra_cost_vect (const json::object *jo, T &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);
>>>>> +}
>>>>> +
>>>>> +template <typename T>
>>>>> +static void
>>>>> +parse_addr_cost_addr_scale_costs (const json::object *jo, T
>>>>> &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);
>>>>> +}
>>>>> +
>>>>> +template <typename T>
>>>>> +static void
>>>>> +parse_regmove_cost (const json::object *jo, T &regmove_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);
>>>>> +}
>>>>> +
>>>>> +template <typename T>
>>>>> +static void
>>>>> +parse_vec_costs_advsimd (const json::object *jo, T &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);
>>>>> +}
>>>>> +
>>>>> +template <typename T>
>>>>> +static void
>>>>> +parse_vec_costs_sve (const json::object *jo, T &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);
>>>>> +}
>>>>> +
>>>>> +template <typename T>
>>>>> +static void
>>>>> +parse_vec_costs_issue_info_scalar (const json::object *jo, T &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);
>>>>> +}
>>>>> +
>>>>> +template <typename T>
>>>>> +static void
>>>>> +parse_vec_costs_issue_info_advsimd (const json::object *jo, T &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);
>>>>> +}
>>>>> +
>>>>> +template <typename T>
>>>>> +static void
>>>>> +parse_vec_costs_issue_info_sve (const json::object *jo, T &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);
>>>>> +}
>>>>> +
>>>>> +template <typename T>
>>>>> +static void
>>>>> +parse_branch_costs (const json::object *jo, T &branch_costs)
>>>>> +{
>>>>> +  PARSE_INTEGER_FIELD (jo, "predictable", branch_costs.predictable);
>>>>> +  PARSE_INTEGER_FIELD (jo, "unpredictable",
>>> branch_costs.unpredictable);
>>>>> +}
>>>>> +
>>>>> +template <typename T>
>>>>> +static void
>>>>> +parse_approx_modes (const json::object *jo, T &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);
>>>>> +}
>>>>> +
>>>>> +template <typename T>
>>>>> +static void
>>>>> +parse_memmov_cost (const json::object *jo, T &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);
>>>>> +}
>>>>> +
>>>>> +template <typename T>
>>>>> +static void
>>>>> +parse_prefetch (const json::object *jo, T &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);
>>>>> +}
>>>>> +
>>>>> +template <typename T>
>>>>> +static void
>>>>> +parse_insn_extra_cost (const json::object *jo, T &insn_extra_cost)
>>>>> +{
>>>>> +  PARSE_OBJECT (jo, "alu", insn_extra_cost.alu,
>>> parse_insn_extra_cost_alu);
>>>>> +  PARSE_ARRAY_FIELD (jo, "mult", insn_extra_cost.mult,
>>>>> +                  parse_insn_extra_cost_mult_element);
>>>>> +  PARSE_OBJECT (jo, "ldst", insn_extra_cost.ldst,
>>>>> parse_insn_extra_cost_ldst);
>>>>> +  PARSE_ARRAY_FIELD (jo, "fp", insn_extra_cost.fp,
>>>>> +                  parse_insn_extra_cost_fp_element);
>>>>> +  PARSE_OBJECT (jo, "vect", insn_extra_cost.vect,
>>>>> parse_insn_extra_cost_vect);
>>>>> +}
>>>>> +
>>>>> +template <typename T>
>>>>> +static void
>>>>> +parse_addr_cost (const json::object *jo, T &addr_cost)
>>>>> +{
>>>>> +  PARSE_OBJECT (jo, "addr_scale_costs", addr_cost.addr_scale_costs,
>>>>> +             parse_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);
>>>>> +}
>>>>> +
>>>>> +template <typename T>
>>>>> +static void
>>>>> +parse_vec_costs_issue_info (const json::object *jo, T &issue_info)
>>>>> +{
>>>>> +  PARSE_OBJECT (jo, "scalar", issue_info.scalar,
>>>>> +             parse_vec_costs_issue_info_scalar);
>>>>> +  PARSE_OBJECT (jo, "advsimd", issue_info.advsimd,
>>>>> +             parse_vec_costs_issue_info_advsimd);
>>>>> +  PARSE_OBJECT (jo, "sve", issue_info.sve,
>>> parse_vec_costs_issue_info_sve);
>>>>> +}
>>>>> +
>>>>> +template <typename T>
>>>>> +static void
>>>>> +parse_vec_costs (const json::object *jo, T &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);
>>>>> +  PARSE_OBJECT (jo, "advsimd", vec_costs.advsimd,
>>>>> parse_vec_costs_advsimd);
>>>>> +  PARSE_OBJECT (jo, "sve", vec_costs.sve, parse_vec_costs_sve);
>>>>> +  PARSE_OBJECT (jo, "issue_info", vec_costs.issue_info,
>>>>> +             parse_vec_costs_issue_info);
>>>>> +}
>>>>> +
>>>>> +template <typename T>
>>>>> +static void
>>>>> +parse_tunings (const json::object *jo, T &tunings)
>>>>> +{
>>>>> +  PARSE_OBJECT (jo, "insn_extra_cost", tunings.insn_extra_cost,
>>>>> +             parse_insn_extra_cost);
>>>>> +  PARSE_OBJECT (jo, "addr_cost", tunings.addr_cost, parse_addr_cost);
>>>>> +  PARSE_OBJECT (jo, "regmove_cost", tunings.regmove_cost,
>>>>> parse_regmove_cost);
>>>>> +  PARSE_OBJECT (jo, "vec_costs", tunings.vec_costs, parse_vec_costs);
>>>>> +  PARSE_OBJECT (jo, "branch_costs", tunings.branch_costs,
>>>>> parse_branch_costs);
>>>>> +  PARSE_OBJECT (jo, "approx_modes", tunings.approx_modes,
>>>>> parse_approx_modes);
>>>>> +  PARSE_INTEGER_FIELD (jo, "sve_width", tunings.sve_width);
>>>>> +  PARSE_OBJECT (jo, "memmov_cost", tunings.memmov_cost,
>>>>> parse_memmov_cost);
>>>>> +  PARSE_INTEGER_FIELD (jo, "issue_rate", tunings.issue_rate);
>>>>> +  PARSE_INTEGER_FIELD (jo, "fusible_ops", tunings.fusible_ops);
>>>>> +  PARSE_STRING_FIELD (jo, "function_align", tunings.function_align);
>>>>> +  PARSE_STRING_FIELD (jo, "jump_align", tunings.jump_align);
>>>>> +  PARSE_STRING_FIELD (jo, "loop_align", tunings.loop_align);
>>>>> +  PARSE_INTEGER_FIELD (jo, "int_reassoc_width",
>>>>> tunings.int_reassoc_width);
>>>>> +  PARSE_INTEGER_FIELD (jo, "fp_reassoc_width",
>>> tunings.fp_reassoc_width);
>>>>> +  PARSE_INTEGER_FIELD (jo, "fma_reassoc_width",
>>>>> tunings.fma_reassoc_width);
>>>>> +  PARSE_INTEGER_FIELD (jo, "vec_reassoc_width",
>>>>> tunings.vec_reassoc_width);
>>>>> +  PARSE_INTEGER_FIELD (jo, "min_div_recip_mul_sf",
>>>>> +                    tunings.min_div_recip_mul_sf);
>>>>> +  PARSE_INTEGER_FIELD (jo, "min_div_recip_mul_df",
>>>>> +                    tunings.min_div_recip_mul_df);
>>>>> +  PARSE_INTEGER_FIELD (jo, "max_case_values",
>>> tunings.max_case_values);
>>>>> +  PARSE_ENUM_FIELD (jo, "autoprefetcher_model",
>>>>> tunings.autoprefetcher_model,
>>>>> +                 autoprefetcher_model_mappings);
>>>>> +  PARSE_INTEGER_FIELD (jo, "extra_tuning_flags",
>>>>> tunings.extra_tuning_flags);
>>>>> +  PARSE_OBJECT (jo, "prefetch", tunings.prefetch, parse_prefetch);
>>>>> +  PARSE_ENUM_FIELD (jo, "ldp_policy_model", tunings.ldp_policy_model,
>>>>> +                 ldp_policy_model_mappings);
>>>>> +  PARSE_ENUM_FIELD (jo, "stp_policy_model", tunings.stp_policy_model,
>>>>> +                 stp_policy_model_mappings);
>>>>> +}
>>>>> +
>>>>> +/* Validate the user provided JSON data against the present schema.
>>>>> +   Checks for correct types, fields, and expected format.  */
>>>>> +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 (auto *sub_schema_obj = dyn_cast<const json::object *>
>>>>> (schema_value))
>>>>> +     {
>>>>> +       if (auto *sub_json_obj = dyn_cast<const json::object *>
>>>>> (json_value))
>>>>> +         {
>>>>> +           if (!validate_and_traverse (sub_json_obj, sub_schema_obj,
>>>>> +                                       full_key))
>>>>> +             return false;
>>>>> +         }
>>>>> +       else
>>>>> +         {
>>>>> +           error ("key %qs expected to be an object", full_key.c_str ());
>>>>> +           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 (auto *schema_string
>>>>> +            = dyn_cast<const json::string *> (schema_value))
>>>>> +     {
>>>>> +       const char *schema_type_str = schema_string->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 if (strcmp (schema_type_str, "enum") == 0)
>>>>> +         {
>>>>> +           if (json_value->get_kind () != json::JSON_STRING)
>>>>> +             {
>>>>> +               error ("key %qs expected to be an enum (string)",
>>>>> +                      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;
>>>>> +}
>>>>> +
>>>>> +/* Helper routine for reading the provided JSON file.  */
>>>>> +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;
>>>>> +}
>>>>> +
>>>>> +/* Main routine for setting up the parsing of JSON data.  */
>>>>> +void
>>>>> +aarch64_load_tuning_params_from_json_string (const char *json_string,
>>>>> +                                          const char *schema_string,
>>>>> +                                          struct tune_params *tune)
>>>>> +{
>>>>> +  /* Try parsing the JSON string.  */
>>>>> +  json::parser_result_t data_result
>>>>> +    = json::parse_utf8_string (strlen (json_string), json_string, true,
>>>>> +                            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)
>>>>> +    {
>>>>> +      error ("JSON parsing returned null data");
>>>>> +      return;
>>>>> +    }
>>>>> +  auto *root_obj = dyn_cast<const json::object *> (root.get ());
>>>>> +  if (!root_obj)
>>>>> +    {
>>>>> +      warning (0, "no JSON object found in the provided data");
>>>>> +      return;
>>>>> +    }
>>>>> +
>>>>> +  json::parser_result_t schema_result
>>>>> +    = json::parse_utf8_string (strlen (schema_string), schema_string, 
>>>>> true,
>>>>> +                            nullptr);
>>>>> +
>>>>> +  gcc_assert (!schema_result.m_err.get ());
>>>>> +  gcc_assert (schema_result.m_val);
>>>>> +
>>>>> +  auto *schema_obj
>>>>> +    = dyn_cast<const json::object *> (schema_result.m_val.get ());
>>>>> +  gcc_assert (schema_obj);
>>>>> +
>>>>> +  const json::value *tune_params_value = root_obj->get ("tune_params");
>>>>> +  if (!tune_params_value)
>>>>> +    {
>>>>> +      warning (0, "key %<tune_params%> not found in JSON data");
>>>>> +      return;
>>>>> +    }
>>>>> +
>>>>> +  auto *jo = dyn_cast<const json::object *> (tune_params_value);
>>>>> +  if (!jo)
>>>>> +    {
>>>>> +      error ("key %<tune_params%> is not a JSON object");
>>>>> +      return;
>>>>> +    }
>>>>> +
>>>>> +  if (!validate_and_traverse (root_obj, schema_obj))
>>>>> +    {
>>>>> +      error ("validation failed for the provided JSON data");
>>>>> +      return;
>>>>> +    }
>>>>> +
>>>>> +  parse_tunings (jo, *tune);
>>>>> +  return;
>>>>> +}
>>>>> +
>>>>> +/* Wrapper for calling aarch64_load_tuning_params_from_json_string.  */
>>>>> +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);
>>>>> +}
>>>>> +
>>>>> +/* Self-tests to check if the values populated to the tune_params 
>>>>> structure
>>>>> +   are correct.  */
>>>>> +
>>>>> +#if CHECKING_P
>>>>> +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,
>>>>> &params);
>>>>> +
>>>>> +  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";
>>>>> +
>>>>> +  static const cpu_cost_table default_cost_table = {};
>>>>> +
>>>>> +  tune_params params;
>>>>> +  params.insn_extra_cost = &default_cost_table;
>>>>> +
>>>>> +  aarch64_load_tuning_params_from_json_string (test_json,
>>> schema_json,
>>>>> &params);
>>>>> +
>>>>> +  ASSERT_EQ (params.insn_extra_cost->alu.non_exec_costs_exec, false);
>>>>> +}
>>>>> +
>>>>> +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,
>>>>> &params);
>>>>> +
>>>>> +  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,
>>>>> &params);
>>>>> +
>>>>> +  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_integers ();
>>>>> +  test_json_boolean ();
>>>>> +  test_json_strings ();
>>>>> +  test_json_enums ();
>>>>> +}
>>>>> +
>>>>> +} // namespace selftest
>>>>> +
>>>>> +#endif /* CHECKING_P */
>>>>> \ No newline at end of file
>>>>> 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..3c5cd4c3c20
>>>>> --- /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 198820b5e5f..a22369cfcb8 100644
>>>>> --- a/gcc/config/aarch64/aarch64.cc
>>>>> +++ b/gcc/config/aarch64/aarch64.cc
>>>>> @@ -99,6 +99,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"
>>>>> @@ -19006,6 +19007,21 @@ aarch64_override_options_internal (struct
>>>>> gcc_options *opts)
>>>>>   aarch64_parse_override_string (opts->x_aarch64_override_tune_string,
>>>>>                               &aarch64_tune_params);
>>>>> 
>>>>> +  /* We need to parse the JSON file only once per program execution.  */
>>>>> +  if (opts->x_muser_provided_CPU)
>>>>> +    {
>>>>> +      static bool json_parsed = false;
>>>>> +      static struct tune_params aarch64_json_params;
>>>>> +      if (!json_parsed)
>>>>> +     {
>>>>> +       aarch64_json_params = *(tune->tune);
>>>>> +       aarch64_load_tuning_params_from_json (opts-
>>>>>> x_muser_provided_CPU,
>>>>> +                                             &aarch64_json_params);
>>>>> +       json_parsed = true;
>>>>> +     }
>>>>> +      aarch64_tune_params = aarch64_json_params;
>>>>> +    }
>>>>> +
>>>>> if (opts->x_aarch64_ldp_policy_param)
>>>>>   aarch64_tune_params.ldp_policy_model = opts-
>>>>>> x_aarch64_ldp_policy_param;
>>>>> 
>>>>> diff --git a/gcc/config/aarch64/aarch64.opt
>>>>> b/gcc/config/aarch64/aarch64.opt
>>>>> index fd9864cc670..1735d2debe5 100644
>>>>> --- a/gcc/config/aarch64/aarch64.opt
>>>>> +++ b/gcc/config/aarch64/aarch64.opt
>>>>> @@ -192,6 +192,10 @@ fdump-tuning-model=
>>>>> Target Undocumented RejectNegative Negative(fdump-tuning-model=)
>>>>> Joined Var(fdump_tuning_model)
>>>>> -fdump-tuning-model=<filename> Dump current tuning model to a JSON
>>> file.
>>>>> 
>>>>> +muser-provided-CPU=
>>>>> +Target Undocumented RejectNegative Negative(muser-provided-CPU=)
>>>>> Joined Var(muser_provided_CPU)
>>>>> +-muser-provided-CPU=<json-tuning-file> 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 fe95eaee116..ce1e54aba2f 100644
>>>>> --- a/gcc/config/aarch64/t-aarch64
>>>>> +++ b/gcc/config/aarch64/t-aarch64
>>>>> @@ -211,6 +211,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 c68d3e79a31..e060f260a46 100644
>>>>> --- a/gcc/selftest-run-tests.cc
>>>>> +++ b/gcc/selftest-run-tests.cc
>>>>> @@ -77,6 +77,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 4501d34181c..7a2fb3d14f1 100644
>>>>> --- a/gcc/selftest.h
>>>>> +++ b/gcc/selftest.h
>>>>> @@ -239,6 +239,7 @@ extern void input_cc_tests ();
>>>>> extern void ipa_modref_tree_cc_tests ();
>>>>> extern void json_cc_tests ();
>>>>> extern void json_parser_cc_tests ();
>>>>> +extern void json_tunings_tests ();
>>>>> extern void opt_suggestions_cc_tests ();
>>>>> extern void optinfo_emit_json_cc_tests ();
>>>>> extern void opts_cc_tests ();
>>>>> --
>>>>> 2.44.0
> <0001-aarch64-arm-Remove-const-keyword-from-tune_params-me.patch><0002-aarch64-Enable-dumping-of-AArch64-CPU-tuning-paramet.patch><0003-json-Add-get_map-method-to-JSON-object-class.patch><0004-aarch64-Enable-parsing-of-user-provided-AArch64-CPU-.patch><0005-aarch64-Regression-tests-for-parsing-of-user-provide.patch><0006-aarch64-Script-to-auto-generate-JSON-tuning-routines.patch>

Reply via email to