Infrastructure for optimization level sensitive PARAM_ values

Richard Biener rguenther@suse.de
Tue Jun 11 13:29:00 GMT 2019


On Tue, 11 Jun 2019, Jan Hubicka wrote:

> Hi,
> we plan to work on optimizing -O2 better for C++ code. This should
> involve enabling some limited auto-inlining and possibly other opts.  To
> not ruin code size we plan to tune down the newly introduced
> optimizations as well as some of existing ones (shuch as complete loop
> unrolling) to make more reasoable code size/performance tradeoffs.
> 
> Problem is that our passes are currently kind of binary (eiter enabled
> or disabled) and when enabled they are usually tuned to highest value
> needed for SPEC improvement and thus often bit extreme.
> 
> In opts.c we handle few PARAM values specially but this does not work
> well with optimization attribute and LTO where parameters are not
> done in funtion specific way.
> 
> This patch makes params optimization level sensitive.  This is done as
> follows:
> 
>  1) parameters are now of two types - either global or optimization level
>     specific. Some basic "type checking" is present since gloal parameter
>     enum names are now GLOBAL_parname and they are defined by
>     DEFPARAM_GLOBAL and used by PARAM_VALUE_GLOBAL
>  2) opt specific parameter now have 6 values: for O1,O2,O3,Ofast, Os O1
>     and Os O2+.
>     This set is meant to be easily changed and basically I worked it
>     out by looking at what we do currently with default parameters.
>     I did not include Og and one combine flag.
>     Generally I do not want to have too many parameters.
>  3) For IPA passes there is now PARAM_VALUE_FOR_FN that can be used
>     to obtain value depending on the setting of a given function.
>  4) there is currently no way for user to specify differet values for different
>     levels, but we can do that incrementally.
> 
> One ugly thing I needed to track is the fact that params.h is included
> in contexts where tree.h is not present and thus DEF_PARAM can't be implemented
> by means of inline function. (And I want to keep it inline since params might
> be used in loops). This is done by simply passing down all necessary opt
> settings from macro.
> 
> Bootstrapped/regtested x86_64-linux, seem reasonable?

Hmm, so looking at

+DEFPARAM_Ofast (PARAM_ALLOW_STORE_DATA_RACES,
          "allow-store-data-races",
          "Allow new data races on stores to be introduced.",
-         0, 0, 1)
+         0, 1, 0, 1)

once we want to have different defaults for -Os, -O2 and -Ofast
we need a new macro here and consumers need to deal with that.

I think we have a similar situation for regular options as well.
If we'd want different -finline-limit= dependent on optimization
setting there's no way to encode that in common.opt or in
default_options_table (maybe there by listing it multiple times
in the "correct" order).

You're not saving --params per function but instead key on
optimize[_{size,fast}].

I'm not sure why there is a distiction between DEFPARAM_*
and DEFPARAM_GLOBAL.  I'd have kept the existing DEFPARAM
syntax like

DEFPARAM (PARAM_ALLOW_STORE_DATA_RACES,
          "allow-store-data-races",
          "Allow new data races on stores to be introduced.",
          0, 0, 1)

which would set the default and then amend it with multiple

DEFPARAM_TUNING (PARAM_ALLOW_STORE_DATA_RACES, TUNE_Ofast, 1)

how does PARAM_VALUE_SET_FOR_FN work when a user cannot specify
param values per function?  Does it say "yes" in case the
function has 'optimize' attributes?

Does it ever make sense to use PARAM_VALUE_GLOBAL?  I think
we should always use PARAM_VALUE[_FOR_FN].

That said, the situation looks somewhat incomplete when
looking at the same issue in common.opt options?

I suppose the alternative was to embed (some) param values
into the opts structure as streamed.  Where I think we need
to go anyways with user supplied per CU --param specifications?
So the patch below walks in a non-extensible direction?

Thanks,
Richard.

> 2019-06-11  Jan Hubicka  <hubicka@ucw.cz>
> 
> 	* cp/name-lookup.c (namespace_hints::namespace_hints): Use
> 	PARAM_VALUE_GLOBAL.
> 
> 2019-06-11  Jan Hubicka  <hubicka@ucw.cz>
> 
> 	* lto/lto-partition.c (lto_balanced_map): Use PARAM_VALUE_GLOBAL.
> 	* lto/lto.c (do_whole_program_analysis): Likewise.
> 
> 
> ChangeLog:
> 
> 2019-06-11  Jan Hubicka  <hubicka@ucw.cz>
> 
> 	* params.def: Introduce DEFPARAM_GLOBAL, DEFPARAM_O2plus,
> 	DEFPARAM_Ofast, DEFPARAM_Os.
> 	* common.opt: param_values type is now struct param_vals.
> 	* opts.c (init_options_struct): Update allocation of param_values.
> 	(default_options_optimization): Move opt specific initialization of
> 	PARAM_LOOP_INVARIANT_MAX_BBS_IN_LOOP, PARAM_MAX_DSE_ACTIVE_LOCAL_STORES,
> 	PARAM_ALLOW_STORE_DATA_RACES, PARAM_MIN_CROSSJUMP_INSNS to 
> 	params.def; use GLOBAL_PARAM_MAX_FIELDS_FOR_FIELD_SENSITIVE instead
> 	of PARAM_MAX_FIELDS_FOR_FIELD_SENSITIVE.
> 	(print_filtered_help): Update.
> 	(common_handle_option): Update handling of sanitize options.
> 	* params-enum.h (DEFPARAM): Update.
> 	(DEFPARAM_OPT, DEFPARAM_GLOBAL): New.
> 	* params-list.h: (DEFPARAM): Update.
> 	(DEFPARAM_OPT, DEFPARAM_GLOBAL): New.
> 	* params-options.h: (DEFPARAM): Update.
> 	(DEFPARAM_OPT, DEFPARAM_GLOBAL): New.
> 	* params.c (INIT_VALUES): New macro.
> 	(DEFPARAM): Update.
> 	(DEFPARAM_OPT, DEFPARAM_GLOBAL): New.
> 	(set_param_value_internal): Update.
> 	(set_param_value_internal_index): New.
> 	(validate_param): Update.
> 	(set_param_value): Update.
> 	(maybe_set_param_value): Update.
> 	(set_default_param_value): Update.
> 	(default_param_value): Update.
> 	* params.h (NUM_PARAM_SETTINGS): Set to 6.
> 	(struct param_vals): New structure.
> 	(struct param_info): Change type of default_value to param_vals.
> 	(param_value_index): Update prototype.
> 	(extern void init_param_values): Update prototype.
> 	(PARAM_VALUE_FOR_FN, PARAM_VALUE_SET_FOR_FN,
> 	PARAM_VALUE_SET, PARAM_VALUE_GLOBAL, PARAM_VALUE_GLOBAL_SET): New
> 	macros.
> 	(PARAM_VALUE): Implement using PARAM_VALUE_SET_FOR_FN.
> 	(param_value_index): New inline function.
> 	(MAX_INLINE_INSNS_SINGLE, MAX_INLINE_INSNS, MAX_INLINE_SLOPE,
> 	MIN_INLINE_INSNS, MAX_INLINE_INSNS_AUTO, MIN_VIRTUAL_MAPPINGS,
> 	VIRTUAL_MAPPINGS_TO_SYMS_RATIO): Remove; update uses
> 	by explicit PARAM_VALUE_FOR_FN.
> 	(INTEGER_SHARE_LIMIT, MAX_FIELDS_FOR_FIELD_SENSITIVE,
> 	USE_CANONICAL_TYPES, MIN_NONDEBUG_INSN_UID, ASAN_STACK,
> 	ASAN_PROTECT_ALLOCAS, ASAN_GLOBALS, ASAN_INSTRUMENT_READS,
> 	ASAN_INSTRUMENT_WRITES, ASAN_MEMINTRIN, ASAN_USE_AFTER_RETURN,
> 	ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD): Use
> 	PARAM_VALUE_GLOBAL.
> 	* predict.c (get_hot_bb_threshold): Use PARAM_VALUE_GLOBAL.
> 	(maybe_hot_count_p): Use PARAM_VALUE_GLOBAL.
> 	(probably_never_executed): Use PARAM_VALUE_GLOBAL.
> 	(predictable_edge_p): Use PARAM_VALUE_GLOBAL.
> 	(handle_missing_profiles): Use PARAM_VALUE_GLOBAL.
> 	* resource.c: Include tree.h.
> 	* sched-ebb.c: Include tree.h.
> 	* sched-rgn.c: Include tree.h.
> 	* targhooks.c (default_max_noce_ifcvt_seq_cost): Use
> 	PARAM_VALUE_SET.
> 	* toplev.c (print_version): Use PARAM_VALUE_GLOBAL.
> 	(process_options): Use PARAM_VALUE_GLOBAL.
> 	* tree-sra.c (analyze_all_variable_accesses): USE PARAM_VALUE_SET.
> 	(ipa_sra_preliminary_function_checks): Likewise.
> 	* tree-ssa-ifcombine.c (ifcombine_ifandif): Likewise.
> 	* cgraph.c (cgraph_edge::maybe_hot_p): Likewise.
> 	* coverage.c (get_coverage_counts): Likewise.
> 	(coverage_compute_profile_id): Likewise.
> 	(coverage_begin_function): Likewise.
> 	(coverage_end_function): Likewise.
> 	* cprop.c: Include tree.h
> 	* fold-const.c (fold_range_test): Use PARAM_VALUE_GLOBAL.
> 	(fold_truth_andor): likewise.
> 	* ggc-page.c (ggc_collect): Use PARAM_VALUE_GLOBAL.
> 	* haifa-sched.c: Include tree.h.
> 	* hash-table.h: Use PARAM_VALUE_GLOBAL.
> 	* ipa-cp.c (ipcp_lattice::add_value): Use PARAM_VALUE_FOR_FN.
> 	(merge_agg_lats_step): Use PARAM_VALUE_GLOBAL.
> 	(devirtualization_time_bonus): Use PARAM_VALUE_FOR_FN.
> 	(hint_time_bonus): Use PARAM_VALUE_GLOBAL.
> 	(incorporate_penalties): Use PARAM_VALUE_GLOBAL.
> 	(good_cloning_opportunity_p): Use PARAM_VALUE_FOR_FN.
> 	(ipcp_propagate_stage): Use PARAM_VALUE_FOR_FN.
> 	* ipa-fnsummary.c (analyze_function_body): Use PARAM_VALUE_FOR_FN.
> 	(compute_fn_summary): Use PARAM_VALUE_FOR_FN.
> 	* ipa-inline-analysis.c (estimate_growth): Use PARAM_VALUE_FOR_FN.
> 	* ipa-inline.c (caller_growth_limits): Use PARAM_VALUE_FOR_FN.
> 	(can_inline_edge_by_limits_p): Use PARAM_VALUE_FOR_FN.
> 	(want_early_inline_function_p): Use PARAM_VALUE_FOR_FN.
> 	(big_speedup_p): Use PARAM_VALUE_FOR_FN.
> 	(want_inline_small_function_p): Use PARAM_VALUE_FOR_FN.
> 	(want_inline_self_recursive_call_p): Use PARAM_VALUE_FOR_FN.
> 	(edge_badness): Use PARAM_VALUE_FOR_FN.
> 	(recursive_inlining): Use PARAM_VALUE_FOR_FN.
> 	(compute_max_insns): Use PARAM_VALUE_GLOBAL.
> 	* ipa-profile.c (ipa_profile): Likewise.
> 	* ipa-prop.c: (determine_locally_known_aggregate_parts): Use
> 	PARAM_VALUE_GLOBAL
> 	* ipa-split.c (consider_split): Use PARAM_VALUE.
> 	* ira-build.c: Include tree.h
> 	* ira-conflicts.c: Include tree.h
> 
> config/ChangeLog:
> 
> 2019-06-11  Jan Hubicka  <hubicka@ucw.cz>
> 
> 	* i386/i386.c (ix86_max_noce_ifcvt_seq_cost): Use PARAM_VALUE_SET.
> 
> Index: params.def
> ===================================================================
> --- params.def	(revision 272142)
> +++ params.def	(working copy)
> @@ -19,7 +19,8 @@ along with GCC; see the file COPYING3.
>  <http://www.gnu.org/licenses/>.  */
>  
>  /* This file contains definitions for language-independent
> -   parameters.  The DEFPARAM macro takes 6 arguments:
> +   parameters.  Parameters that are independent of optimization level
> +   are set by the DEFPARAM_GLOBAL macro takes 6 arguments:
>  
>       - The enumeral corresponding to this parameter.
>  
> @@ -35,12 +36,34 @@ along with GCC; see the file COPYING3.
>       - The maximum acceptable value for the parameter (if greater than
>       the minimum).
>  
> +   The DEFPARAM is same except that it declares parameter that may have
> +   different values depends on optimization level.  Those are set by
> +   DEFPARAM_O2plus, DEFPARAM_Ofast and DEFPARAM_Os which additionally
> +   take extra argument specifying values for -O2+, -Ofast and -Os
> +   respectively.
> +
>     The DEFPARAMENUM<N> macro is similar, but instead of the minumum and maximum
>     arguments, it contains a list of <N> allowed strings, corresponding to
>     integer values 0..<N>-1.  Note that the default argument needs to be
>     specified as one of the allowed strings, rather than an integer value.
>  
> -   Be sure to add an entry to invoke.texi summarizing the parameter.  */
> +   Be sure to add an entry to invoke.texi summarizing the parameter.
> +
> +   Values declared by DEFPARAM_GLOBAL are used via PARAM_VALUE_GLOBAL macro
> +   whole other values are read by PARAM_VALUE.  */
> +
> +#define DEFPARAM(ENUM, OPTION, HELP, DEF, MIN, MAX) \
> +	DEFPARAM_OPT (ENUM, OPTION, HELP, DEF, DEF, DEF, DEF, DEF, DEF, \
> +		      MIN, MAX)
> +#define DEFPARAM_O2plus(ENUM, OPTION, HELP, DEF, DEFO2, MIN, MAX) \
> +	DEFPARAM_OPT (ENUM, OPTION, HELP, \
> +		      DEF, DEFO2, DEFO2, DEFO2, DEF, DEFO2, MIN, MAX)
> +#define DEFPARAM_Ofast(ENUM, OPTION, HELP, DEF, DEFOfast, MIN, MAX) \
> +	DEFPARAM_OPT (ENUM, OPTION, HELP, \
> +		      DEF, DEF, DEF, DEFOfast, DEF, DEF, MIN, MAX)
> +#define DEFPARAM_Os(ENUM, OPTION, HELP, DEF, DEFOs, MIN, MAX) \
> +	DEFPARAM_OPT (ENUM, OPTION, HELP, \
> +		      DEF, DEF, DEF, DEF, DEFOs, DEFOs, MIN, MAX)
>  
>  /* When branch is predicted to be taken with probability lower than this
>     threshold (in percent), then it is considered well predictable. */
> @@ -219,15 +242,15 @@ DEFPARAM(PARAM_LARGE_FUNCTION_GROWTH,
>  	 "large-function-growth",
>  	 "Maximal growth due to inlining of large function (in percent).",
>  	 100, 0, 0)
> -DEFPARAM(PARAM_LARGE_UNIT_INSNS,
> +DEFPARAM_GLOBAL(PARAM_LARGE_UNIT_INSNS,
>  	 "large-unit-insns",
>  	 "The size of translation unit to be considered large.",
>  	 10000, 0, 0)
> -DEFPARAM(PARAM_INLINE_UNIT_GROWTH,
> +DEFPARAM_GLOBAL(PARAM_INLINE_UNIT_GROWTH,
>  	 "inline-unit-growth",
>  	 "How much can given compilation unit grow because of the inlining (in percent).",
>  	 40, 0, 0)
> -DEFPARAM(PARAM_IPCP_UNIT_GROWTH,
> +DEFPARAM_GLOBAL(PARAM_IPCP_UNIT_GROWTH,
>  	 "ipcp-unit-growth",
>  	 "How much can given compilation unit grow because of the interprocedural constant propagation (in percent).",
>  	 10, 0, 0)
> @@ -425,12 +448,12 @@ DEFPARAM(PARAM_SMS_LOOP_AVERAGE_COUNT_TH
>  	 "A threshold on the average loop count considered by the swing modulo scheduler.",
>  	 0, 0, 0)
>  
> -DEFPARAM(HOT_BB_COUNT_FRACTION,
> +DEFPARAM_GLOBAL(HOT_BB_COUNT_FRACTION,
>  	 "hot-bb-count-fraction",
>  	 "Select fraction of the maximal count of repetitions of basic block in program given basic "
>  	 "block needs to have to be considered hot (used in non-LTO mode).",
>  	 10000, 0, 0)
> -DEFPARAM(HOT_BB_COUNT_WS_PERMILLE,
> +DEFPARAM_GLOBAL(HOT_BB_COUNT_WS_PERMILLE,
>  	 "hot-bb-count-ws-permille",
>           "A basic block profile count is considered hot if it contributes to "
>           "the given permillage of the entire profiled execution (used in LTO mode).",
> @@ -440,7 +463,7 @@ DEFPARAM(HOT_BB_FREQUENCY_FRACTION,
>  	 "Select fraction of the maximal frequency of executions of basic block in function given basic block needs to have to be considered hot.",
>  	 1000, 0, 0)
>  
> -DEFPARAM(UNLIKELY_BB_COUNT_FRACTION,
> +DEFPARAM_GLOBAL(UNLIKELY_BB_COUNT_FRACTION,
>  	 "unlikely-bb-count-fraction",
>           "The minimum fraction of profile runs a given basic block execution count must be not to be considered unlikely.",
>  	 20, 1, 10000)
> @@ -518,11 +541,12 @@ DEFPARAM(PARAM_MAX_CROSSJUMP_EDGES,
>  	 "The maximum number of incoming edges to consider for crossjumping.",
>  	 100, 0, 0)
>  
> -/* The minimum number of matching instructions to consider for crossjumping.  */
> -DEFPARAM(PARAM_MIN_CROSSJUMP_INSNS,
> +/* The minimum number of matching instructions to consider for crossjumping.
> +   At -Os we want to crossjump as much as possible*/
> +DEFPARAM_Os(PARAM_MIN_CROSSJUMP_INSNS,
>       "min-crossjump-insns",
>       "The minimum number of matching instructions to consider for crossjumping.",
> -     5, 1, 0)
> +     5, 1, 1, 0)
>  
>  /* The maximum number expansion factor when copying basic blocks.  */
>  DEFPARAM(PARAM_MAX_GROW_COPY_BB_INSNS,
> @@ -637,12 +661,12 @@ DEFPARAM(PARAM_MAX_CSELIB_MEMORY_LOCATIO
>  # define GGC_MIN_HEAPSIZE_DEFAULT 4096
>  #endif
>  
> -DEFPARAM(GGC_MIN_EXPAND,
> +DEFPARAM_GLOBAL(GGC_MIN_EXPAND,
>  	 "ggc-min-expand",
>  	 "Minimum heap expansion to trigger garbage collection, as a percentage of the total size of the heap.",
>  	 GGC_MIN_EXPAND_DEFAULT, 0, 0)
>  
> -DEFPARAM(GGC_MIN_HEAPSIZE,
> +DEFPARAM_GLOBAL(GGC_MIN_HEAPSIZE,
>  	 "ggc-min-heapsize",
>  	 "Minimum heap size before we start collecting garbage, in kilobytes.",
>  	 GGC_MIN_HEAPSIZE_DEFAULT, 0, 0)
> @@ -744,7 +768,7 @@ DEFPARAM(PARAM_MAX_COMBINE_INSNS,
>     {signed,unsigned} integral types.  This determines N.
>     Experimentation shows 251 to be a good value that generates the
>     least amount of garbage for allocating the TREE_VEC storage.  */
> -DEFPARAM (PARAM_INTEGER_SHARE_LIMIT,
> +DEFPARAM_GLOBAL (PARAM_INTEGER_SHARE_LIMIT,
>  	  "integer-share-limit",
>  	  "The upper bound for sharing integer constants.",
>  	  251, 2, 2)
> @@ -782,7 +806,7 @@ DEFPARAM (PARAM_MAX_JUMP_THREAD_DUPLICAT
>     will stop trying to treat it in a field-sensitive manner.
>     There are programs out there with thousands of fields per structure, and handling them
>     field-sensitively is not worth the cost.  */
> -DEFPARAM (PARAM_MAX_FIELDS_FOR_FIELD_SENSITIVE,
> +DEFPARAM_GLOBAL (PARAM_MAX_FIELDS_FOR_FIELD_SENSITIVE,
>            "max-fields-for-field-sensitive",
>  	  "Maximum number of fields in a structure before pointer analysis treats the structure as a single variable.",
>  	  0, 0, 0)
> @@ -793,10 +817,10 @@ DEFPARAM(PARAM_MAX_SCHED_READY_INSNS,
>  	 100, 1, 0)
>  
>  /* This is the maximum number of active local stores RTL DSE will consider.  */
> -DEFPARAM (PARAM_MAX_DSE_ACTIVE_LOCAL_STORES,
> +DEFPARAM_O2plus (PARAM_MAX_DSE_ACTIVE_LOCAL_STORES,
>  	  "max-dse-active-local-stores",
>  	  "Maximum number of active local stores in RTL dead store elimination.",
> -	  5000, 0, 0)
> +	  500, 5000, 0, 0)
>  
>  /* Prefetching and cache-optimizations related parameters.  Default values are
>     usually set by machine description.  */
> @@ -874,7 +898,7 @@ DEFPARAM (PARAM_LOOP_INTERCHANGE_STRIDE_
>     this value should only be set to zero to work around bugs in the
>     canonical type system by disabling it.  */
>  
> -DEFPARAM (PARAM_USE_CANONICAL_TYPES,
> +DEFPARAM_GLOBAL (PARAM_USE_CANONICAL_TYPES,
>  	  "use-canonical-types",
>  	  "Whether to use canonical types.",
>  	  1, 0, 1)
> @@ -979,15 +1003,15 @@ DEFPARAM (PARAM_LOOP_MAX_DATAREFS_FOR_DA
>  
>  /* Avoid doing loop invariant motion on very large loops.  */
>  
> -DEFPARAM (PARAM_LOOP_INVARIANT_MAX_BBS_IN_LOOP,
> +DEFPARAM_O2plus (PARAM_LOOP_INVARIANT_MAX_BBS_IN_LOOP,
>  	  "loop-invariant-max-bbs-in-loop",
>  	  "Max basic blocks number in loop for loop invariant motion.",
> -	  10000, 0, 0)
> +	  1000, 10000, 0, 0)
>  
>  /* When the parameter is 1, use the internal function id
>     to look up for profile data. Otherwise, use a more stable
>     external id based on assembler name and source location. */
> -DEFPARAM (PARAM_PROFILE_FUNC_INTERNAL_ID,
> +DEFPARAM_GLOBAL (PARAM_PROFILE_FUNC_INTERNAL_ID,
>  	  "profile-func-internal-id",
>  	  "Use internal function id in profile lookup.",
>  	  0, 0, 1)
> @@ -1043,7 +1067,7 @@ DEFPARAM (PARAM_MAX_DEBUG_MARKER_COUNT,
>  
>  /* Set minimum insn uid for non-debug insns.  */
>  
> -DEFPARAM (PARAM_MIN_NONDEBUG_INSN_UID,
> +DEFPARAM_GLOBAL (PARAM_MIN_NONDEBUG_INSN_UID,
>  	  "min-nondebug-insn-uid",
>  	  "The minimum UID to be used for a nondebug insn.",
>  	  0, 0, 0)
> @@ -1085,31 +1109,31 @@ DEFPARAM (PARAM_IPA_CP_EVAL_THRESHOLD,
>  	  "beneficial to clone.",
>  	  500, 0, 0)
>  
> -DEFPARAM (PARAM_IPA_CP_RECURSION_PENALTY,
> +DEFPARAM_GLOBAL (PARAM_IPA_CP_RECURSION_PENALTY,
>  	  "ipa-cp-recursion-penalty",
>  	  "Percentage penalty the recursive functions will receive when they "
>  	  "are evaluated for cloning.",
>  	  40, 0, 100)
>  
> -DEFPARAM (PARAM_IPA_CP_SINGLE_CALL_PENALTY,
> +DEFPARAM_GLOBAL (PARAM_IPA_CP_SINGLE_CALL_PENALTY,
>  	  "ipa-cp-single-call-penalty",
>  	  "Percentage penalty functions containing a single call to another "
>  	  "function will receive when they are evaluated for cloning.",
>  	  15, 0, 100)
>  
> -DEFPARAM (PARAM_IPA_MAX_AGG_ITEMS,
> +DEFPARAM_GLOBAL (PARAM_IPA_MAX_AGG_ITEMS,
>  	  "ipa-max-agg-items",
>  	  "Maximum number of aggregate content items for a parameter in "
>  	  "jump functions and lattices.",
>  	  16, 0, 0)
>  
> -DEFPARAM (PARAM_IPA_CP_LOOP_HINT_BONUS,
> +DEFPARAM_GLOBAL (PARAM_IPA_CP_LOOP_HINT_BONUS,
>  	  "ipa-cp-loop-hint-bonus",
>  	  "Compile-time bonus IPA-CP assigns to candidates which make loop "
>  	  "bounds or strides known.",
>  	  64, 0, 0)
>  
> -DEFPARAM (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS,
> +DEFPARAM_GLOBAL (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS,
>  	  "ipa-cp-array-index-hint-bonus",
>  	  "Compile-time bonus IPA-CP assigns to candidates which make an array "
>  	  "index known.",
> @@ -1123,29 +1147,29 @@ DEFPARAM (PARAM_IPA_MAX_AA_STEPS,
>  
>  /* WHOPR partitioning configuration.  */
>  
> -DEFPARAM (PARAM_LTO_PARTITIONS,
> +DEFPARAM_GLOBAL (PARAM_LTO_PARTITIONS,
>  	  "lto-partitions",
>  	  "Number of partitions the program should be split to.",
>  	  128, 1, 0)
>  
> -DEFPARAM (MIN_PARTITION_SIZE,
> +DEFPARAM_GLOBAL (MIN_PARTITION_SIZE,
>  	  "lto-min-partition",
>  	  "Minimal size of a partition for LTO (in estimated instructions).",
>  	  10000, 0, 0)
>  
> -DEFPARAM (MAX_PARTITION_SIZE,
> +DEFPARAM_GLOBAL (MAX_PARTITION_SIZE,
>  	  "lto-max-partition",
>  	  "Maximal size of a partition for LTO (in estimated instructions).",
>  	  1000000, 0, INT_MAX)
>  
> -DEFPARAM (PARAM_MAX_LTO_STREAMING_PARALLELISM,
> +DEFPARAM_GLOBAL (PARAM_MAX_LTO_STREAMING_PARALLELISM,
>  	  "lto-max-streaming-parallelism",
>  	  "maximal number of LTO partitions streamed in parallel.",
>  	  32, 1, 0)
>  
>  /* Diagnostic parameters.  */
>  
> -DEFPARAM (CXX_MAX_NAMESPACES_FOR_DIAGNOSTIC_HELP,
> +DEFPARAM_GLOBAL (CXX_MAX_NAMESPACES_FOR_DIAGNOSTIC_HELP,
>  	  "cxx-max-namespaces-for-diagnostic-help",
>  	  "Maximum number of namespaces to search for alternatives when "
>  	  "name lookup fails.",
> @@ -1181,11 +1205,12 @@ DEFPARAM (PARAM_JUMP_TABLE_MAX_GROWTH_RA
>  	  "optimizing for speed.",
>  	  800, 0, 0)
>  
> -/* Data race flags for C++0x memory model compliance.  */
> -DEFPARAM (PARAM_ALLOW_STORE_DATA_RACES,
> +/* Data race flags for C++0x memory model compliance.
> +   Allow them only for Ofast  */
> +DEFPARAM_Ofast (PARAM_ALLOW_STORE_DATA_RACES,
>  	  "allow-store-data-races",
>  	  "Allow new data races on stores to be introduced.",
> -	  0, 0, 1)
> +	  0, 1, 0, 1)
>  
>  /* Reassociation width to be used by tree reassoc optimization.  */
>  DEFPARAM (PARAM_TREE_REASSOC_WIDTH,
> @@ -1244,42 +1269,42 @@ DEFPARAM (PARAM_MAX_SLSR_CANDIDATE_SCAN,
>  
>  /* ASan stands for AddressSanitizer: https://github.com/google/sanitizers.  */
>  
> -DEFPARAM (PARAM_ASAN_STACK,
> +DEFPARAM_GLOBAL (PARAM_ASAN_STACK,
>           "asan-stack",
>           "Enable asan stack protection.",
>           1, 0, 1)
>  
> -DEFPARAM (PARAM_ASAN_PROTECT_ALLOCAS,
> +DEFPARAM_GLOBAL (PARAM_ASAN_PROTECT_ALLOCAS,
>  	"asan-instrument-allocas",
>  	"Enable asan allocas/VLAs protection.",
>  	1, 0, 1)
>  
> -DEFPARAM (PARAM_ASAN_GLOBALS,
> +DEFPARAM_GLOBAL (PARAM_ASAN_GLOBALS,
>           "asan-globals",
>           "Enable asan globals protection.",
>           1, 0, 1)
>  
> -DEFPARAM (PARAM_ASAN_INSTRUMENT_WRITES,
> +DEFPARAM_GLOBAL (PARAM_ASAN_INSTRUMENT_WRITES,
>           "asan-instrument-writes",
>           "Enable asan store operations protection.",
>           1, 0, 1)
>  
> -DEFPARAM (PARAM_ASAN_INSTRUMENT_READS,
> +DEFPARAM_GLOBAL (PARAM_ASAN_INSTRUMENT_READS,
>           "asan-instrument-reads",
>           "Enable asan load operations protection.",
>           1, 0, 1)
>  
> -DEFPARAM (PARAM_ASAN_MEMINTRIN,
> +DEFPARAM_GLOBAL (PARAM_ASAN_MEMINTRIN,
>           "asan-memintrin",
>           "Enable asan builtin functions protection.",
>           1, 0, 1)
>  
> -DEFPARAM (PARAM_ASAN_USE_AFTER_RETURN,
> +DEFPARAM_GLOBAL (PARAM_ASAN_USE_AFTER_RETURN,
>           "asan-use-after-return",
>           "Enable asan detection of use-after-return bugs.",
>           1, 0, 1)
>  
> -DEFPARAM (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD,
> +DEFPARAM_GLOBAL (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD,
>           "asan-instrumentation-with-call-threshold",
>           "Use callbacks instead of inline code if number of accesses "
>           "in function becomes greater or equal to this number.",
> @@ -1407,7 +1432,7 @@ DEFPARAM(PARAM_AVOID_FMA_MAX_BITS,
>  	 "Maximum number of bits for which we avoid creating FMAs.",
>  	 0, 0, 512)
>  
> -DEFPARAM(PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT,
> +DEFPARAM_GLOBAL(PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT,
>  	 "logical-op-non-short-circuit",
>  	 "True if a non-short-circuit operation is optimal.",
>  	 -1, -1, 1)
> @@ -1431,12 +1456,13 @@ DEFPARAM(PARAM_GIMPLE_FE_COMPUTED_HOT_BB
>  	 " The parameter is used only in GIMPLE FE.",
>  	 0, 0, 0)
>  
> -DEFPARAM(PARAM_HASH_TABLE_VERIFICATION_LIMIT,
> +DEFPARAM_GLOBAL(PARAM_HASH_TABLE_VERIFICATION_LIMIT,
>  	 "hash-table-verification-limit",
>  	 "The number of elements for which hash table verification is done for "
>  	 "each searched element.",
>  	 100, 0, 0)
>  
> +#undef DEFPARAM
>  /*
>  
>  Local variables:
> Index: common.opt
> ===================================================================
> --- common.opt	(revision 272142)
> +++ common.opt	(working copy)
> @@ -64,7 +64,7 @@ Variable
>  bool flag_warn_unused_result = false
>  
>  Variable
> -int *param_values
> +struct param_vals *param_values
>  
>  ; Nonzero if we should write GIMPLE bytecode for link-time optimization.
>  Variable
> Index: opts.c
> ===================================================================
> --- opts.c	(revision 272142)
> +++ opts.c	(working copy)
> @@ -292,10 +292,10 @@ init_options_struct (struct gcc_options
>    if (opts_set)
>      memset (opts_set, 0, sizeof (*opts_set));
>  
> -  opts->x_param_values = XNEWVEC (int, num_params);
> +  opts->x_param_values = XNEWVEC (struct param_vals, num_params);
>  
>    if (opts_set)
> -    opts_set->x_param_values = XCNEWVEC (int, num_params);
> +    opts_set->x_param_values = XCNEWVEC (struct param_vals, num_params);
>  
>    init_param_values (opts->x_param_values);
>  
> @@ -664,41 +664,10 @@ default_options_optimization (struct gcc
>  
>    /* Track fields in field-sensitive alias analysis.  */
>    maybe_set_param_value
> -    (PARAM_MAX_FIELDS_FOR_FIELD_SENSITIVE,
> -     opt2 ? 100 : default_param_value (PARAM_MAX_FIELDS_FOR_FIELD_SENSITIVE),
> +    (GLOBAL_PARAM_MAX_FIELDS_FOR_FIELD_SENSITIVE,
> +     opt2 ? 100 : default_param_value (GLOBAL_PARAM_MAX_FIELDS_FOR_FIELD_SENSITIVE),
>       opts->x_param_values, opts_set->x_param_values);
>  
> -  /* For -O1 only do loop invariant motion for very small loops.  */
> -  maybe_set_param_value
> -    (PARAM_LOOP_INVARIANT_MAX_BBS_IN_LOOP,
> -     opt2 ? default_param_value (PARAM_LOOP_INVARIANT_MAX_BBS_IN_LOOP)
> -     : default_param_value (PARAM_LOOP_INVARIANT_MAX_BBS_IN_LOOP) / 10,
> -     opts->x_param_values, opts_set->x_param_values);
> -
> -  /* For -O1 reduce the maximum number of active local stores for RTL DSE
> -     since this can consume huge amounts of memory (PR89115).  */
> -  maybe_set_param_value
> -    (PARAM_MAX_DSE_ACTIVE_LOCAL_STORES,
> -     opt2 ? default_param_value (PARAM_MAX_DSE_ACTIVE_LOCAL_STORES)
> -     : default_param_value (PARAM_MAX_DSE_ACTIVE_LOCAL_STORES) / 10,
> -     opts->x_param_values, opts_set->x_param_values);
> -
> -  /* At -Ofast, allow store motion to introduce potential race conditions.  */
> -  maybe_set_param_value
> -    (PARAM_ALLOW_STORE_DATA_RACES,
> -     opts->x_optimize_fast ? 1
> -     : default_param_value (PARAM_ALLOW_STORE_DATA_RACES),
> -     opts->x_param_values, opts_set->x_param_values);
> -
> -  if (opts->x_optimize_size)
> -    /* We want to crossjump as much as possible.  */
> -    maybe_set_param_value (PARAM_MIN_CROSSJUMP_INSNS, 1,
> -			   opts->x_param_values, opts_set->x_param_values);
> -  else
> -    maybe_set_param_value (PARAM_MIN_CROSSJUMP_INSNS,
> -			   default_param_value (PARAM_MIN_CROSSJUMP_INSNS),
> -			   opts->x_param_values, opts_set->x_param_values);
> -
>    /* Restrict the amount of work combine does at -Og while retaining
>       most of its useful transforms.  */
>    if (opts->x_optimize_debug)
> @@ -1330,7 +1299,7 @@ print_filtered_help (unsigned int includ
>  	    {
>  	      snprintf (new_help, sizeof (new_help),
>  			_("default %d minimum %d maximum %d"),
> -			compiler_params[i].default_value,
> +			compiler_params[i].default_value.val[0],
>  			compiler_params[i].min_value,
>  			compiler_params[i].max_value);
>  	      help = new_help;
> @@ -2273,17 +2242,19 @@ common_handle_option (struct gcc_options
>  	 all features.  */
>        if (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS)
>  	{
> -	  maybe_set_param_value (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD,
> +	  maybe_set_param_value (GLOBAL_PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD,
>  				 0, opts->x_param_values,
>  				 opts_set->x_param_values);
> -	  maybe_set_param_value (PARAM_ASAN_GLOBALS, 0, opts->x_param_values,
> +	  maybe_set_param_value (GLOBAL_PARAM_ASAN_GLOBALS, 0,
> +				 opts->x_param_values,
>  				 opts_set->x_param_values);
> -	  maybe_set_param_value (PARAM_ASAN_STACK, 0, opts->x_param_values,
> +	  maybe_set_param_value (GLOBAL_PARAM_ASAN_STACK, 0,
> +				 opts->x_param_values,
>  				 opts_set->x_param_values);
> -	  maybe_set_param_value (PARAM_ASAN_PROTECT_ALLOCAS, 0,
> +	  maybe_set_param_value (GLOBAL_PARAM_ASAN_PROTECT_ALLOCAS, 0,
>  				 opts->x_param_values,
>  				 opts_set->x_param_values);
> -	  maybe_set_param_value (PARAM_ASAN_USE_AFTER_RETURN, 0,
> +	  maybe_set_param_value (GLOBAL_PARAM_ASAN_USE_AFTER_RETURN, 0,
>  				 opts->x_param_values,
>  				 opts_set->x_param_values);
>  	}
> Index: params-enum.h
> ===================================================================
> --- params-enum.h	(revision 272142)
> +++ params-enum.h	(working copy)
> @@ -17,7 +17,9 @@ You should have received a copy of the G
>  along with GCC; see the file COPYING3.  If not see
>  <http://www.gnu.org/licenses/>.  */
>  
> -#define DEFPARAM(ENUM, OPTION, HELP, DEFAULT, MIN, MAX)
> +#define DEFPARAM_OPT(ENUM, OPTION, HELP, DEFO1, DEFO2, DEFO3, DEFOfast,\
> +		     DEFOsO1, DEFOsO2, MIN, MAX)
> +#define DEFPARAM_GLOBAL(ENUM, OPTION, HELP, DEFAULT, MIN, MAX)
>  #define DEFPARAMENUMNAME(ENUM) ENUM ## _KIND
>  #define DEFPARAMENUMVAL(ENUM, V) ENUM ## _KIND_ ## V
>  #define DEFPARAMENUMTERM(ENUM) ENUM ## _KIND_ ## LAST
> @@ -36,4 +38,5 @@ along with GCC; see the file COPYING3.
>  #undef DEFPARAMENUMTERM
>  #undef DEFPARAMENUMVAL
>  #undef DEFPARAMENUMNAME
> -#undef DEFPARAM
> +#undef DEFPARAM_OPT
> +#undef DEFPARAM_GLOBAL
> Index: params-list.h
> ===================================================================
> --- params-list.h	(revision 272142)
> +++ params-list.h	(working copy)
> @@ -17,10 +17,14 @@ You should have received a copy of the G
>  along with GCC; see the file COPYING3.  If not see
>  <http://www.gnu.org/licenses/>.  */
>  
> -#define DEFPARAM(enumerator, option, nocmsgid, default, min, max) \
> +#define DEFPARAM_OPT(enumerator, option, nocmsgid, DEFO1, DEFO2, DEFO3, \
> +		     DEFOfast, DEFOsO1, DEFOsO2, min, max) \
>    enumerator,
> +#define DEFPARAM_GLOBAL(enumerator, option, nocmsgid, default, min, max) \
> +  GLOBAL_##enumerator,
>  #define DEFPARAMENUM5(enumerator, option, nocmsgid, default, \
>  		      v0, v1, v2, v3, v4) enumerator,
>  #include "params.def"
> -#undef DEFPARAM
> +#undef DEFPARAM_OPT
> +#undef DEFPARAM_GLOBAL
>  #undef DEFPARAMENUM5
> Index: params-options.h
> ===================================================================
> --- params-options.h	(revision 272142)
> +++ params-options.h	(working copy)
> @@ -17,11 +17,13 @@ You should have received a copy of the G
>  along with GCC; see the file COPYING3.  If not see
>  <http://www.gnu.org/licenses/>.  */
>  
> -#define DEFPARAM(enumerator, option, nocmsgid, default, min, max) \
> +#define DEFPARAM(enumerator, option, nocmsgid, defO1, defO2, defO3, defOfast, \
> +		 defOs, defOsO1, min, max) \
>    option=default,min,max
>  #define DEFPARAMENUM5(enumerator, option, nocmsgid, default, \
>  		      v0, v1, v2, v3, v4) \
>    option=v0,v1,v2,v3,v4
>  #include "params.def"
> -#undef DEFPARAM
> +#undef DEFPARAM_OPT
> +#undef DEFPARAM_GLOBAL
>  #undef DEFPARAMENUM5
> Index: params.c
> ===================================================================
> --- params.c	(revision 272142)
> +++ params.c	(working copy)
> @@ -28,6 +28,8 @@ along with GCC; see the file COPYING3.
>  #include "diagnostic.h"
>  #include "spellcheck.h"
>  
> +#define INIT_VALUES(VAL) {{(VAL), (VAL), (VAL), (VAL), (VAL), (VAL)}}
> +
>  /* An array containing the compiler parameters and their current
>     values.  */
>  
> @@ -40,27 +42,36 @@ static size_t num_compiler_params;
>     default values determined.  */
>  static bool params_finished;
>  
> -#define DEFPARAM(ENUM, OPTION, HELP, DEFAULT, MIN, MAX)
> +#define DEFPARAM_OPT(ENUM, OPTION, HELP, DEFO1, DEFO2, DEFO3, DEFOfast, \
> +		     DEFOsO1, DEFOsO2, MIN, MAX)
> +#define DEFPARAM_GLOBAL(ENUM, OPTION, HELP, DEFAULT, MIN, MAX)
>  #define DEFPARAMENUM5(ENUM, OPTION, HELP, DEFAULT, V0, V1, V2, V3, V4)	\
>    static const char *values_ ## ENUM [] = { #V0, #V1, #V2, #V3, #V4, NULL };
>  #include "params.def"
>  #undef DEFPARAMENUM5
> -#undef DEFPARAM
> +#undef DEFPARAM_OPT
> +#undef DEFPARAM_GLOBAL
>  
>  static const param_info lang_independent_params[] = {
> -#define DEFPARAM(ENUM, OPTION, HELP, DEFAULT, MIN, MAX) \
> -  { OPTION, DEFAULT, MIN, MAX, HELP, NULL },
> +#define DEFPARAM_GLOBAL(ENUM, OPTION, HELP, DEFAULT, MIN, MAX) \
> +  { OPTION, {DEFAULT, DEFAULT, DEFAULT, DEFAULT}, MIN, MAX, HELP, NULL },
> +#define DEFPARAM_OPT(ENUM, OPTION, HELP, DEFO1, DEFO2, DEFO3, DEFOfast, \
> +		     DEFOsO1, DEFOsO2, MIN, MAX) \
> +  { OPTION, \
> +   {DEFO1, DEFO2, DEFO3, DEFOfast, DEFOsO1, DEFOsO2}, MIN, MAX, HELP, NULL },
>  #define DEFPARAMENUM5(ENUM, OPTION, HELP, DEFAULT,	     \
>  		      V0, V1, V2, V3, V4)		     \
> -  { OPTION, (int)ENUM ## _KIND_ ## DEFAULT, 0, 4, HELP, values_ ## ENUM },
> +  { OPTION, INIT_VALUES((int)ENUM ## _KIND_ ## DEFAULT),     \
> +    0, 4, HELP, values_ ## ENUM },
>  #include "params.def"
> -#undef DEFPARAM
> +#undef DEFPARAM_OPT
>  #undef DEFPARAMENUM5
> -  { NULL, 0, 0, 0, NULL, NULL }
> +  { NULL, INIT_VALUES (0), 0, 0, NULL, NULL }
>  };
>  
>  static bool
> -validate_param (const int value, const param_info param, const int index);
> +validate_param (const struct param_vals values,
> +		const param_info param, const int index);
>  
>  
>  /* Add the N PARAMS to the current list of compiler parameters.  */
> @@ -131,40 +142,66 @@ params_c_finalize (void)
>     otherwise it is being set implicitly by the compiler.  */
>  
>  static void
> -set_param_value_internal (compiler_param num, int value,
> -			  int *params, int *params_set,
> +set_param_value_internal (compiler_param num, struct param_vals value,
> +			  struct param_vals *params, 
> +			  struct param_vals *params_set,
>  			  bool explicit_p)
>  {
> +  param_vals true_vals = INIT_VALUES (true);
> +
>    size_t i = (size_t) num;
>  
>    gcc_assert (params_finished);
>  
>    params[i] = value;
>    if (explicit_p)
> -    params_set[i] = true;
> +    params_set[i] = true_vals;
> +}
> +
> +/* Same as set_param_value_inter but set only value for given INDEX.  */
> +
> +static void
> +set_param_value_internal_index (compiler_param num, int index,
> +				int value,
> +			        struct param_vals *params, 
> +			        struct param_vals *params_set,
> +				bool explicit_p)
> +{
> +  size_t i = (size_t) num;
> +
> +  gcc_assert (params_finished);
> +
> +  params[i].val[index] = value;
> +  if (explicit_p)
> +    params_set[i].val[index] = true;
>  }
>  
>  /* Validate PARAM and write an error if invalid.  */
>  
>  static bool
> -validate_param (const int value, const param_info param, const int index)
> +validate_param (const struct param_vals values,
> +	        const param_info param, const int index)
>  {
> -  /* These paremeters interpret bounds of 0 to be unbounded, as such don't
> -     perform any range validation on 0 parameters.  */
> -  if (value < param.min_value && param.min_value != 0)
> +  for (int i = 0; i < NUM_PARAM_SETTINGS; i++)
>      {
> -      error ("minimum value of parameter %qs is %u",
> -	     param.option, param.min_value);
> -      return false;
> -    }
> -  else if (param.max_value > param.min_value && value > param.max_value)
> -    {
> -      error ("maximum value of parameter %qs is %u",
> -	     param.option, param.max_value);
> -      return false;
> -    }
> -  else if (targetm_common.option_validate_param (value, index))
> -    return true;
> +      int value = values.val[i];
> +      /* These paremeters interpret bounds of 0 to be unbounded, as such don't
> +	 perform any range validation on 0 parameters.  */
> +      if (value < param.min_value && param.min_value != 0)
> +	{
> +	  error ("minimum value of parameter %qs is %u",
> +		 param.option, param.min_value);
> +	  return false;
> +	}
> +      else if (param.max_value > param.min_value && value > param.max_value)
> +	{
> +	  error ("maximum value of parameter %qs is %u",
> +		 param.option, param.max_value);
> +	  return false;
> +	}
> +      else if (targetm_common.option_validate_param (value, index))
> +	return true;
> +   }
>  
>    return false;
>  }
> @@ -226,9 +263,11 @@ param_string_value_p (enum compiler_para
>  
>  void
>  set_param_value (const char *name, int value,
> -		 int *params, int *params_set)
> +		 struct param_vals *params, 
> +		 struct param_vals *params_set)
>  {
>    size_t i;
> +  struct param_vals values = INIT_VALUES (value);
>  
>    /* Make sure nobody tries to set a parameter to an invalid value.  */
>    gcc_assert (value != INVALID_PARAM_VAL);
> @@ -242,8 +281,8 @@ set_param_value (const char *name, int v
>      }
>    i = (size_t)index;
>  
> -  if (validate_param (value, compiler_params[i], i))
> -    set_param_value_internal ((compiler_param) i, value,
> +  if (validate_param (values, compiler_params[i], i))
> +    set_param_value_internal ((compiler_param) i, values,
>  			      params, params_set, true);
>  }
>  
> @@ -253,10 +292,13 @@ set_param_value (const char *name, int v
>  
>  void
>  maybe_set_param_value (compiler_param num, int value,
> -		       int *params, int *params_set)
> +		       struct param_vals *params, 
> +		       struct param_vals *params_set)
>  {
> -  if (!params_set[(int) num])
> -    set_param_value_internal (num, value, params, params_set, false);
> +  for (int index = 0; index < NUM_PARAM_SETTINGS; index++)
> +    if (!params_set[(int) num].val[index])
> +      set_param_value_internal_index (num, index, value, params,
> +				      params_set, false);
>  }
>  
>  /* Set the default value of a parameter given by NUM to VALUE, before
> @@ -265,9 +307,10 @@ maybe_set_param_value (compiler_param nu
>  void
>  set_default_param_value (compiler_param num, int value)
>  {
> +  struct param_vals vals = INIT_VALUES (value);
>    gcc_assert (!params_finished);
>  
> -  compiler_params[(int) num].default_value = value;
> +  compiler_params[(int) num].default_value = vals;
>  }
>  
>  /* Return the default value of parameter NUM.  */
> @@ -275,14 +318,14 @@ set_default_param_value (compiler_param
>  int
>  default_param_value (compiler_param num)
>  {
> -  return compiler_params[(int) num].default_value;
> +  return compiler_params[(int) num].default_value.val[0];
>  }
>  
>  /* Initialize an array PARAMS with default values of the
>     parameters.  */
>  
>  void
> -init_param_values (int *params)
> +init_param_values (struct param_vals *params)
>  {
>    size_t i;
>  
> Index: params.h
> ===================================================================
> --- params.h	(revision 272142)
> +++ params.h	(working copy)
> @@ -32,10 +32,19 @@ along with GCC; see the file COPYING3.
>  #ifndef GCC_PARAMS_H
>  #define GCC_PARAMS_H
>  
> +#define NUM_PARAM_SETTINGS 6
> +
>  /* No parameter shall have this value.  */
>  
>  #define INVALID_PARAM_VAL (-1)
>  
> +/* Default values for given param.  */
> +
> +struct param_vals
> +{
> +  int val[NUM_PARAM_SETTINGS];
> +};
> +
>  /* The information associated with each parameter.  */
>  
>  struct param_info
> @@ -45,7 +54,7 @@ struct param_info
>    const char *option;
>  
>    /* The default value.  */
> -  int default_value;
> +  struct param_vals default_value;
>  
>    /* Minimum acceptable value.  */
>    int min_value;
> @@ -77,7 +86,8 @@ extern void add_params (const param_info
>     explicitly set.  */
>  
>  extern void set_param_value (const char *name, int value,
> -			     int *params, int *params_set);
> +			     struct param_vals *params,
> +			     struct param_vals *params_set);
>  
>  

>  /* The parameters in use by language-independent code.  */
> @@ -92,16 +102,56 @@ extern bool find_param (const char *, en
>  extern const char *find_param_fuzzy (const char *name);
>  extern bool param_string_value_p (enum compiler_param, const char *, int *);
>  
> -/* The value of the parameter given by ENUM.  Not an lvalue.  */
> -#define PARAM_VALUE(ENUM) \
> -  ((int) global_options.x_param_values[(int) ENUM])
> +/* Return index into param values for optimization setting of the function FUN:
> +   0 for -O0, -O1 and when optimization level is unknown.
> +   1 for -O2
> +   2 for -O3
> +   3 for -Ofast
> +   4 for -Os -O1. 
> +   5 for -Os -O2+.  */
> +inline int
> +param_value_index (bool opt_size, int opt_level, bool opt_fast)
> +{
> +  if (opt_size)
> +    return opt_level <= 1 ? 4 : 5;
> +  if (opt_fast)
> +    return 3;
> +  return MAX (MIN (opt_level-1, 2), 0);
> +}
> +
> +/* The value of the optimization level specific
> +   parameter given by ENUM.  Not an lvalue.  */
> +#define PARAM_VALUE_FOR_FN(FUN, ENUM)					     \
> +  ((int) global_options.x_param_values 					     \
> + 	 [(int) ENUM].val[param_value_index (opt_for_fn (FUN, optimize_size),\
> +					     opt_for_fn (FUN, optimize),     \
> +					     opt_for_fn (FUN, optimize_fast))])
> +/* True if optimization level specific parameter given by ENUM is set.  */
> +#define PARAM_VALUE_SET_FOR_FN(FUN, ENUM)				     \
> +  ((int) global_options_set.x_param_values 				     \
> + 	 [(int) ENUM].val[param_value_index (opt_for_fn (FUN, optimize_size),\
> +					     opt_for_fn (FUN, optimize),     \
> +					     opt_for_fn (FUN, optimize_fast))])
> +
> +/* The value of the optimization level specific
> +   parameter given by ENUM.  Not an lvalue.  */
> +#define PARAM_VALUE(ENUM) 						     \
> +  PARAM_VALUE_FOR_FN(current_function_decl, ENUM)
> +/* True if optimization level specific parameter given by ENUM is set.  */
> +#define PARAM_VALUE_SET(ENUM) 						     \
> +  PARAM_VALUE_SET_FOR_FN(current_function_decl, ENUM)
> +#define PARAM_VALUE_GLOBAL(ENUM) 					     \
> +  ((int) global_options.x_param_values [(int) GLOBAL_##ENUM].val[0])
> +#define PARAM_VALUE_GLOBAL_SET(ENUM) 						     \
> +  ((int) global_options_set.x_param_values [(int) GLOBAL_##ENUM].val[0])
>  
>  /* Set the value of the parameter given by NUM to VALUE, implicitly,
>     if it has not been set explicitly by the user, in the table PARAMS
>     using PARAMS_SET to indicate which have been explicitly set.  */
>  
>  extern void maybe_set_param_value (compiler_param num, int value,
> -				   int *params, int *params_set);
> +				   struct param_vals *params,
> +				   struct param_vals *params_set);
>  
>  /* Set the default value of a parameter given by NUM to VALUE, before
>     option processing.  */
> @@ -127,19 +177,9 @@ extern int default_param_value (compiler
>  
>  /* Initialize an array PARAMS with default values of the
>     parameters.  */
> -extern void init_param_values (int *params);
> +extern void init_param_values (struct param_vals *params);
>  
>  /* Macros for the various parameters.  */
> -#define MAX_INLINE_INSNS_SINGLE \
> -  PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SINGLE)
> -#define MAX_INLINE_INSNS \
> -  PARAM_VALUE (PARAM_MAX_INLINE_INSNS)
> -#define MAX_INLINE_SLOPE \
> -  PARAM_VALUE (PARAM_MAX_INLINE_SLOPE)
> -#define MIN_INLINE_INSNS \
> -  PARAM_VALUE (PARAM_MIN_INLINE_INSNS)
> -#define MAX_INLINE_INSNS_AUTO \
> -  PARAM_VALUE (PARAM_MAX_INLINE_INSNS_AUTO)
>  #define MAX_VARIABLE_EXPANSIONS \
>    PARAM_VALUE (PARAM_MAX_VARIABLE_EXPANSIONS)
>  #define MIN_VECT_LOOP_BOUND \
> @@ -175,15 +215,11 @@ extern void init_param_values (int *para
>  #define SMS_LOOP_AVERAGE_COUNT_THRESHOLD \
>    PARAM_VALUE (PARAM_SMS_LOOP_AVERAGE_COUNT_THRESHOLD)
>  #define INTEGER_SHARE_LIMIT \
> -  PARAM_VALUE (PARAM_INTEGER_SHARE_LIMIT)
> +  PARAM_VALUE_GLOBAL (PARAM_INTEGER_SHARE_LIMIT)
>  #define MAX_LAST_VALUE_RTL \
>    PARAM_VALUE (PARAM_MAX_LAST_VALUE_RTL)
> -#define MIN_VIRTUAL_MAPPINGS \
> -  PARAM_VALUE (PARAM_MIN_VIRTUAL_MAPPINGS)
> -#define VIRTUAL_MAPPINGS_TO_SYMS_RATIO \
> -  PARAM_VALUE (PARAM_VIRTUAL_MAPPINGS_TO_SYMS_RATIO)
>  #define MAX_FIELDS_FOR_FIELD_SENSITIVE \
> -  ((size_t) PARAM_VALUE (PARAM_MAX_FIELDS_FOR_FIELD_SENSITIVE))
> +  ((size_t) PARAM_VALUE_GLOBAL (PARAM_MAX_FIELDS_FOR_FIELD_SENSITIVE))
>  #define MAX_SCHED_READY_INSNS \
>    PARAM_VALUE (PARAM_MAX_SCHED_READY_INSNS)
>  #define PREFETCH_LATENCY \
> @@ -201,7 +237,7 @@ extern void init_param_values (int *para
>  #define PREFETCH_MINIMUM_STRIDE \
>    PARAM_VALUE (PARAM_PREFETCH_MINIMUM_STRIDE)
>  #define USE_CANONICAL_TYPES \
> -  PARAM_VALUE (PARAM_USE_CANONICAL_TYPES)
> +  PARAM_VALUE_GLOBAL (PARAM_USE_CANONICAL_TYPES)
>  #define IRA_MAX_LOOPS_NUM \
>    PARAM_VALUE (PARAM_IRA_MAX_LOOPS_NUM)
>  #define IRA_MAX_CONFLICT_TABLE_SIZE \
> @@ -223,7 +259,7 @@ extern void init_param_values (int *para
>  #define PREFETCH_MIN_INSN_TO_MEM_RATIO \
>    PARAM_VALUE (PARAM_PREFETCH_MIN_INSN_TO_MEM_RATIO)
>  #define MIN_NONDEBUG_INSN_UID \
> -  PARAM_VALUE (PARAM_MIN_NONDEBUG_INSN_UID)
> +  PARAM_VALUE_GLOBAL (PARAM_MIN_NONDEBUG_INSN_UID)
>  #define MAX_STORES_TO_SINK \
>    PARAM_VALUE (PARAM_MAX_STORES_TO_SINK)
>  #define ALLOW_LOAD_DATA_RACES \
> @@ -235,21 +271,21 @@ extern void init_param_values (int *para
>  #define ALLOW_PACKED_STORE_DATA_RACES \
>    PARAM_VALUE (PARAM_ALLOW_PACKED_STORE_DATA_RACES)
>  #define ASAN_STACK \
> -  PARAM_VALUE (PARAM_ASAN_STACK)
> +  PARAM_VALUE_GLOBAL (PARAM_ASAN_STACK)
>  #define ASAN_PROTECT_ALLOCAS \
> -  PARAM_VALUE (PARAM_ASAN_PROTECT_ALLOCAS)
> +  PARAM_VALUE_GLOBAL (PARAM_ASAN_PROTECT_ALLOCAS)
>  #define ASAN_GLOBALS \
> -  PARAM_VALUE (PARAM_ASAN_GLOBALS)
> +  PARAM_VALUE_GLOBAL (PARAM_ASAN_GLOBALS)
>  #define ASAN_INSTRUMENT_READS \
> -  PARAM_VALUE (PARAM_ASAN_INSTRUMENT_READS)
> +  PARAM_VALUE_GLOBAL (PARAM_ASAN_INSTRUMENT_READS)
>  #define ASAN_INSTRUMENT_WRITES \
> -  PARAM_VALUE (PARAM_ASAN_INSTRUMENT_WRITES)
> +  PARAM_VALUE_GLOBAL (PARAM_ASAN_INSTRUMENT_WRITES)
>  #define ASAN_MEMINTRIN \
> -  PARAM_VALUE (PARAM_ASAN_MEMINTRIN)
> +  PARAM_VALUE_GLOBAL (PARAM_ASAN_MEMINTRIN)
>  #define ASAN_USE_AFTER_RETURN \
> -  PARAM_VALUE (PARAM_ASAN_USE_AFTER_RETURN)
> +  PARAM_VALUE_GLOBAL (PARAM_ASAN_USE_AFTER_RETURN)
>  #define ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD \
> -  PARAM_VALUE (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD)
> +  PARAM_VALUE_GLOBAL (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD)
>  #define ASAN_PARAM_USE_AFTER_SCOPE_DIRECT_EMISSION_THRESHOLD \
>    ((unsigned) PARAM_VALUE (PARAM_USE_AFTER_SCOPE_DIRECT_EMISSION_THRESHOLD))
>  
> Index: predict.c
> ===================================================================
> --- predict.c	(revision 272142)
> +++ predict.c	(working copy)
> @@ -132,7 +132,8 @@ get_hot_bb_threshold ()
>  {
>    if (min_count == -1)
>      {
> -      gcov_type t = profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION);
> +      gcov_type t = profile_info->sum_max / PARAM_VALUE_GLOBAL
> +						 (HOT_BB_COUNT_FRACTION);
>        set_hot_bb_threshold (t);
>        if (dump_file)
>  	fprintf (dump_file, "Setting hotness threshold to %" PRId64 ".\n",
> @@ -173,9 +174,10 @@ maybe_hot_count_p (struct function *fun,
>        if (node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
>  	  && count < (ENTRY_BLOCK_PTR_FOR_FN (fun)->count.apply_scale (2, 3)))
>  	return false;
> -      if (PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION) == 0)
> +      if (PARAM_VALUE_FOR_FN (node->decl, HOT_BB_FREQUENCY_FRACTION) == 0)
>  	return false;
> -      if (count.apply_scale (PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION), 1)
> +      if (count.apply_scale (PARAM_VALUE_FOR_FN (node->decl,
> +						 HOT_BB_FREQUENCY_FRACTION), 1)
>  	  < ENTRY_BLOCK_PTR_FOR_FN (fun)->count)
>  	return false;
>        return true;
> @@ -222,7 +224,8 @@ probably_never_executed (struct function
>       desirable.  */
>    if (count.precise_p () && profile_status_for_fn (fun) == PROFILE_READ)
>      {
> -      int unlikely_count_fraction = PARAM_VALUE (UNLIKELY_BB_COUNT_FRACTION);
> +      int unlikely_count_fraction = PARAM_VALUE_GLOBAL
> +				      (UNLIKELY_BB_COUNT_FRACTION);
>        if (count.apply_scale (unlikely_count_fraction, 1) >= profile_info->runs)
>  	return false;
>        return true;
> @@ -413,9 +416,11 @@ predictable_edge_p (edge e)
>    if (!e->probability.initialized_p ())
>      return false;
>    if ((e->probability.to_reg_br_prob_base ()
> -       <= PARAM_VALUE (PARAM_PREDICTABLE_BRANCH_OUTCOME) * REG_BR_PROB_BASE / 100)
> +       <= PARAM_VALUE (PARAM_PREDICTABLE_BRANCH_OUTCOME)
> +			 * REG_BR_PROB_BASE / 100)
>        || (REG_BR_PROB_BASE - e->probability.to_reg_br_prob_base ()
> -          <= PARAM_VALUE (PARAM_PREDICTABLE_BRANCH_OUTCOME) * REG_BR_PROB_BASE / 100))
> +          <= PARAM_VALUE (PARAM_PREDICTABLE_BRANCH_OUTCOME)
> +				 * REG_BR_PROB_BASE / 100))
>      return true;
>    return false;
>  }
> @@ -3531,7 +3536,7 @@ void
>  handle_missing_profiles (void)
>  {
>    struct cgraph_node *node;
> -  int unlikely_count_fraction = PARAM_VALUE (UNLIKELY_BB_COUNT_FRACTION);
> +  int unlikely_count_fraction = PARAM_VALUE_GLOBAL (UNLIKELY_BB_COUNT_FRACTION);
>    auto_vec<struct cgraph_node *, 64> worklist;
>  
>    /* See if 0 count function has non-0 count callers.  In this case we
> Index: resource.c
> ===================================================================
> --- resource.c	(revision 272142)
> +++ resource.c	(working copy)
> @@ -30,6 +30,7 @@ along with GCC; see the file COPYING3.
>  #include "resource.h"
>  #include "insn-attr.h"
>  #include "params.h"
> +#include "tree.h"
>  
>  /* This structure is used to record liveness information at the targets or
>     fallthrough insns of branches.  We will most likely need the information
> Index: sched-ebb.c
> ===================================================================
> --- sched-ebb.c	(revision 272142)
> +++ sched-ebb.c	(working copy)
> @@ -33,6 +33,7 @@ along with GCC; see the file COPYING3.
>  #include "cfgrtl.h"
>  #include "cfgbuild.h"
>  #include "sched-int.h"
> +#include "tree.h"
>  
>  

>  #ifdef INSN_SCHEDULING
> Index: sched-rgn.c
> ===================================================================
> --- sched-rgn.c	(revision 272142)
> +++ sched-rgn.c	(working copy)
> @@ -66,6 +66,7 @@ along with GCC; see the file COPYING3.
>  #include "dbgcnt.h"
>  #include "pretty-print.h"
>  #include "print-rtl.h"
> +#include "tree.h"
>  
>  /* Disable warnings about quoting issues in the pp_xxx calls below
>     that (intentionally) don't follow GCC diagnostic conventions.  */
> Index: targhooks.c
> ===================================================================
> --- targhooks.c	(revision 272142)
> +++ targhooks.c	(working copy)
> @@ -2302,7 +2302,7 @@ default_max_noce_ifcvt_seq_cost (edge e)
>  
>    /* If we have a parameter set, use that, otherwise take a guess using
>       BRANCH_COST.  */
> -  if (global_options_set.x_param_values[param])
> +  if (PARAM_VALUE_SET (param))
>      return PARAM_VALUE (param);
>    else
>      return BRANCH_COST (true, predictable_p) * COSTS_N_INSNS (3);
> Index: toplev.c
> ===================================================================
> --- toplev.c	(revision 272142)
> +++ toplev.c	(working copy)
> @@ -697,7 +697,8 @@ print_version (FILE *file, const char *i
>        fprintf (file,
>  	       file == stderr ? _(fmt4) : fmt4,
>  	       indent, *indent != 0 ? " " : "",
> -	       PARAM_VALUE (GGC_MIN_EXPAND), PARAM_VALUE (GGC_MIN_HEAPSIZE));
> +	       PARAM_VALUE_GLOBAL (GGC_MIN_EXPAND),
> +	       PARAM_VALUE_GLOBAL (GGC_MIN_HEAPSIZE));
>  
>        print_plugins_versions (file, indent);
>      }
> @@ -1801,7 +1802,7 @@ process_options (void)
>  
>    if (flag_checking >= 2)
>      hash_table_sanitize_eq_limit
> -      = PARAM_VALUE (PARAM_HASH_TABLE_VERIFICATION_LIMIT);
> +      = PARAM_VALUE_GLOBAL (PARAM_HASH_TABLE_VERIFICATION_LIMIT);
>  
>    /* Please don't change global_options after this point, those changes won't
>       be reflected in optimization_{default,current}_node.  */
> Index: tree-sra.c
> ===================================================================
> --- tree-sra.c	(revision 272142)
> +++ tree-sra.c	(working copy)
> @@ -2977,7 +2977,7 @@ analyze_all_variable_accesses (void)
>    /* If the user didn't set PARAM_SRA_MAX_SCALARIZATION_SIZE_<...>,
>       fall back to a target default.  */
>    unsigned HOST_WIDE_INT max_scalarization_size
> -    = global_options_set.x_param_values[param]
> +    = PARAM_VALUE_SET (param)
>        ? PARAM_VALUE (param)
>        : get_move_ratio (optimize_speed_p) * UNITS_PER_WORD;
>  
> @@ -5604,7 +5604,8 @@ ipa_sra_preliminary_function_checks (str
>  
>    if ((DECL_ONE_ONLY (node->decl) || DECL_EXTERNAL (node->decl))
>        && ipa_fn_summaries->get (node)
> -      && ipa_fn_summaries->get (node)->size >= MAX_INLINE_INSNS_AUTO)
> +      && ipa_fn_summaries->get (node)->size >=
> +	   PARAM_VALUE_FOR_FN (node->decl, PARAM_MAX_INLINE_INSNS_AUTO))
>      {
>        if (dump_file)
>  	fprintf (dump_file, "Function too big to be made truly local.\n");
> Index: tree-ssa-ifcombine.c
> ===================================================================
> --- tree-ssa-ifcombine.c	(revision 272142)
> +++ tree-ssa-ifcombine.c	(working copy)
> @@ -565,9 +565,9 @@ ifcombine_ifandif (basic_block inner_con
>  	  tree t1, t2;
>  	  gimple_stmt_iterator gsi;
>  	  bool logical_op_non_short_circuit = LOGICAL_OP_NON_SHORT_CIRCUIT;
> -	  if (PARAM_VALUE (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT) != -1)
> +	  if (PARAM_VALUE_GLOBAL (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT) != -1)
>  	    logical_op_non_short_circuit
> -	      = PARAM_VALUE (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT);
> +	      = PARAM_VALUE_GLOBAL (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT);
>  	  if (!logical_op_non_short_circuit || flag_sanitize_coverage)
>  	    return false;
>  	  /* Only do this optimization if the inner bb contains only the conditional. */
> Index: cgraph.c
> ===================================================================
> --- cgraph.c	(revision 272142)
> +++ cgraph.c	(working copy)
> @@ -2783,8 +2783,10 @@ cgraph_edge::maybe_hot_p (void)
>    if (caller->frequency == NODE_FREQUENCY_EXECUTED_ONCE
>        && sreal_frequency () * 2 < 3)
>      return false;
> -  if (PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION) == 0
> -      || sreal_frequency () * PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION) <= 1)
> +  if (PARAM_VALUE_FOR_FN (caller->decl, HOT_BB_FREQUENCY_FRACTION) == 0
> +      || sreal_frequency () * PARAM_VALUE_FOR_FN
> +				 (caller->decl,
> +				  HOT_BB_FREQUENCY_FRACTION) <= 1)
>      return false;
>    return true;
>  }
> Index: config/i386/i386.c
> ===================================================================
> --- config/i386/i386.c	(revision 272142)
> +++ config/i386/i386.c	(working copy)
> @@ -21449,7 +21449,7 @@ ix86_max_noce_ifcvt_seq_cost (edge e)
>  
>    /* If we have a parameter set, use that, otherwise take a guess using
>       BRANCH_COST.  */
> -  if (global_options_set.x_param_values[param])
> +  if (PARAM_VALUE_SET (param))
>      return PARAM_VALUE (param);
>    else
>      return BRANCH_COST (true, predictable_p) * COSTS_N_INSNS (2);
> Index: coverage.c
> ===================================================================
> --- coverage.c	(revision 272142)
> +++ coverage.c	(working copy)
> @@ -324,7 +324,7 @@ get_coverage_counts (unsigned counter, u
>  	}
>        return NULL;
>      }
> -  if (PARAM_VALUE (PARAM_PROFILE_FUNC_INTERNAL_ID))
> +  if (PARAM_VALUE_GLOBAL (PARAM_PROFILE_FUNC_INTERNAL_ID))
>      elt.ident = current_function_funcdef_no + 1;
>    else
>      {
> @@ -560,7 +560,8 @@ coverage_compute_profile_id (struct cgra
>      {
>        expanded_location xloc
>  	= expand_location (DECL_SOURCE_LOCATION (n->decl));
> -      bool use_name_only = (PARAM_VALUE (PARAM_PROFILE_FUNC_INTERNAL_ID) == 0);
> +      bool use_name_only
> +		 = (PARAM_VALUE_GLOBAL (PARAM_PROFILE_FUNC_INTERNAL_ID) == 0);
>  
>        chksum = (use_name_only ? 0 : xloc.line);
>        if (xloc.file)
> @@ -628,7 +629,7 @@ coverage_begin_function (unsigned lineno
>  
>    /* Announce function */
>    offset = gcov_write_tag (GCOV_TAG_FUNCTION);
> -  if (PARAM_VALUE (PARAM_PROFILE_FUNC_INTERNAL_ID))
> +  if (PARAM_VALUE_GLOBAL (PARAM_PROFILE_FUNC_INTERNAL_ID))
>      gcov_write_unsigned (current_function_funcdef_no + 1);
>    else
>      {
> @@ -682,7 +683,7 @@ coverage_end_function (unsigned lineno_c
>  
>        item = ggc_alloc<coverage_data> ();
>  
> -      if (PARAM_VALUE (PARAM_PROFILE_FUNC_INTERNAL_ID))
> +      if (PARAM_VALUE_GLOBAL (PARAM_PROFILE_FUNC_INTERNAL_ID))
>  	item->ident = current_function_funcdef_no + 1;
>        else
>  	{
> Index: cp/name-lookup.c
> ===================================================================
> --- cp/name-lookup.c	(revision 272142)
> +++ cp/name-lookup.c	(working copy)
> @@ -5311,7 +5311,7 @@ namespace_hints::namespace_hints (locati
>  
>    m_candidates = vNULL;
>    m_limited = false;
> -  m_limit = PARAM_VALUE (CXX_MAX_NAMESPACES_FOR_DIAGNOSTIC_HELP);
> +  m_limit = PARAM_VALUE_GLOBAL (CXX_MAX_NAMESPACES_FOR_DIAGNOSTIC_HELP);
>  
>    /* Breadth-first search of namespaces.  Up to limit namespaces
>       searched (limit zero == unlimited).  */
> Index: cprop.c
> ===================================================================
> --- cprop.c	(revision 272142)
> +++ cprop.c	(working copy)
> @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3.
>  #include "cfganal.h"
>  #include "lcm.h"
>  #include "cfgcleanup.h"
> +#include "tree.h"
>  #include "params.h"
>  #include "cselib.h"
>  #include "intl.h"
> Index: fold-const.c
> ===================================================================
> --- fold-const.c	(revision 272142)
> +++ fold-const.c	(working copy)
> @@ -5589,9 +5589,9 @@ fold_range_test (location_t loc, enum tr
>       short-circuited branch and the underlying object on both sides
>       is the same, make a non-short-circuit operation.  */
>    bool logical_op_non_short_circuit = LOGICAL_OP_NON_SHORT_CIRCUIT;
> -  if (PARAM_VALUE (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT) != -1)
> +  if (PARAM_VALUE_GLOBAL (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT) != -1)
>      logical_op_non_short_circuit
> -      = PARAM_VALUE (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT);
> +      = PARAM_VALUE_GLOBAL (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT);
>    if (logical_op_non_short_circuit
>        && !flag_sanitize_coverage
>        && lhs != 0 && rhs != 0
> @@ -8255,9 +8255,9 @@ fold_truth_andor (location_t loc, enum t
>      return tem;
>  
>    bool logical_op_non_short_circuit = LOGICAL_OP_NON_SHORT_CIRCUIT;
> -  if (PARAM_VALUE (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT) != -1)
> +  if (PARAM_VALUE_GLOBAL (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT) != -1)
>      logical_op_non_short_circuit
> -      = PARAM_VALUE (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT);
> +      = PARAM_VALUE_GLOBAL (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT);
>    if (logical_op_non_short_circuit
>        && !flag_sanitize_coverage
>        && (code == TRUTH_AND_EXPR
> Index: ggc-page.c
> ===================================================================
> --- ggc-page.c	(revision 272142)
> +++ ggc-page.c	(working copy)
> @@ -2171,9 +2171,11 @@ ggc_collect (void)
>       total allocations haven't expanded much since the last
>       collection.  */
>    float allocated_last_gc =
> -    MAX (G.allocated_last_gc, (size_t)PARAM_VALUE (GGC_MIN_HEAPSIZE) * 1024);
> +    MAX (G.allocated_last_gc,
> +	 (size_t)PARAM_VALUE_GLOBAL (GGC_MIN_HEAPSIZE) * 1024);
>  
> -  float min_expand = allocated_last_gc * PARAM_VALUE (GGC_MIN_EXPAND) / 100;
> +  float min_expand = allocated_last_gc
> +		     * PARAM_VALUE_GLOBAL (GGC_MIN_EXPAND) / 100;
>    if (G.allocated < allocated_last_gc + min_expand && !ggc_force_collect)
>      return;
>  
> Index: haifa-sched.c
> ===================================================================
> --- haifa-sched.c	(revision 272142)
> +++ haifa-sched.c	(working copy)
> @@ -146,6 +146,7 @@ along with GCC; see the file COPYING3.
>  #include "cfgloop.h"
>  #include "dumpfile.h"
>  #include "print-rtl.h"
> +#include "tree.h"
>  
>  #ifdef INSN_SCHEDULING
>  
> Index: hash-table.h
> ===================================================================
> --- hash-table.h	(revision 272142)
> +++ hash-table.h	(working copy)
> @@ -386,10 +386,10 @@ public:
>  
>    /* Create a hash_table in gc memory.  */
>    static hash_table *
> -  create_ggc (size_t n CXX_MEM_STAT_INFO)
> +  create_ggc (size_t n, bool sanitize_eq_and_hash = true CXX_MEM_STAT_INFO)
>    {
>      hash_table *table = ggc_alloc<hash_table> ();
> -    new (table) hash_table (n, true, true, GATHER_STATISTICS,
> +    new (table) hash_table (n, true, sanitize_eq_and_hash, GATHER_STATISTICS,
>  			    HASH_TABLE_ORIGIN PASS_MEM_STAT);
>      return table;
>    }
> Index: ipa-cp.c
> ===================================================================
> --- ipa-cp.c	(revision 272142)
> +++ ipa-cp.c	(working copy)
> @@ -1563,7 +1563,8 @@ ipcp_lattice<valtype>::add_value (valtyp
>  	return false;
>        }
>  
> -  if (values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE))
> +  if (values_count == PARAM_VALUE_FOR_FN (cs->caller->decl,
> +					  PARAM_IPA_CP_VALUE_LIST_SIZE))
>      {
>        /* We can only free sources, not the values themselves, because sources
>  	 of other values in this SCC might point to them.   */
> @@ -2043,7 +2044,7 @@ merge_agg_lats_step (struct ipcp_param_l
>  	  set_agg_lats_to_bottom (dest_plats);
>  	  return false;
>  	}
> -      if (dest_plats->aggs_count == PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS))
> +      if (dest_plats->aggs_count == PARAM_VALUE_GLOBAL (PARAM_IPA_MAX_AGG_ITEMS))
>  	return false;
>        dest_plats->aggs_count++;
>        new_al = ipcp_agg_lattice_pool.allocate ();
> @@ -2589,11 +2590,13 @@ devirtualization_time_bonus (struct cgra
>  
>        /* FIXME: The values below need re-considering and perhaps also
>  	 integrating into the cost metrics, at lest in some very basic way.  */
> -      if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4)
> +      int max_inline_insns_auto = PARAM_VALUE_FOR_FN
> +			 (node->decl, PARAM_MAX_INLINE_INSNS_AUTO);
> +      if (isummary->size <= max_inline_insns_auto / 4)
>  	res += 31 / ((int)speculative + 1);
> -      else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
> +      else if (isummary->size <= max_inline_insns_auto / 2)
>  	res += 15 / ((int)speculative + 1);
> -      else if (isummary->size <= MAX_INLINE_INSNS_AUTO
> +      else if (isummary->size <= max_inline_insns_auto
>  	       || DECL_DECLARED_INLINE_P (callee->decl))
>  	res += 7 / ((int)speculative + 1);
>      }
> @@ -2608,9 +2611,9 @@ hint_time_bonus (ipa_hints hints)
>  {
>    int result = 0;
>    if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
> -    result += PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS);
> +    result += PARAM_VALUE_GLOBAL (PARAM_IPA_CP_LOOP_HINT_BONUS);
>    if (hints & INLINE_HINT_array_index)
> -    result += PARAM_VALUE (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS);
> +    result += PARAM_VALUE_GLOBAL (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS);
>    return result;
>  }
>  
> @@ -2622,11 +2625,13 @@ incorporate_penalties (ipa_node_params *
>  {
>    if (info->node_within_scc)
>      evaluation = (evaluation
> -		  * (100 - PARAM_VALUE (PARAM_IPA_CP_RECURSION_PENALTY))) / 100;
> +		  * (100 - PARAM_VALUE_GLOBAL
> +				 (PARAM_IPA_CP_RECURSION_PENALTY))) / 100;
>  
>    if (info->node_calling_single_call)
>      evaluation = (evaluation
> -		  * (100 - PARAM_VALUE (PARAM_IPA_CP_SINGLE_CALL_PENALTY)))
> +		  * (100 - PARAM_VALUE_GLOBAL
> +				 (PARAM_IPA_CP_SINGLE_CALL_PENALTY)))
>        / 100;
>  
>    return evaluation;
> @@ -2666,10 +2671,12 @@ good_cloning_opportunity_p (struct cgrap
>  		 ", threshold: %i\n",
>  		 info->node_within_scc ? ", scc" : "",
>  		 info->node_calling_single_call ? ", single_call" : "",
> -		 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
> +		 evaluation, PARAM_VALUE_FOR_FN (node->decl,
> +						 PARAM_IPA_CP_EVAL_THRESHOLD));
>  	}
>  
> -      return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
> +      return evaluation >= PARAM_VALUE_FOR_FN (node->decl,
> +					       PARAM_IPA_CP_EVAL_THRESHOLD);
>      }
>    else
>      {
> @@ -2684,9 +2691,11 @@ good_cloning_opportunity_p (struct cgrap
>  		 time_benefit, size_cost, freq_sum,
>  		 info->node_within_scc ? ", scc" : "",
>  		 info->node_calling_single_call ? ", single_call" : "",
> -		 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
> +		 evaluation, PARAM_VALUE_FOR_FN (node->decl,
> +						 PARAM_IPA_CP_EVAL_THRESHOLD));
>  
> -      return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD);
> +      return evaluation >= PARAM_VALUE_FOR_FN (node->decl,
> +					       PARAM_IPA_CP_EVAL_THRESHOLD);
>      }
>  }
>  
> @@ -3301,9 +3310,10 @@ ipcp_propagate_stage (struct ipa_topo_in
>    }
>  
>    max_new_size = overall_size;
> -  if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
> -    max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS);
> -  max_new_size += max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1;
> +  if (max_new_size < PARAM_VALUE_GLOBAL (PARAM_LARGE_UNIT_INSNS))
> +    max_new_size = PARAM_VALUE_GLOBAL (PARAM_LARGE_UNIT_INSNS);
> +  max_new_size += max_new_size
> +		  * PARAM_VALUE_GLOBAL (PARAM_IPCP_UNIT_GROWTH) / 100 + 1;
>  
>    if (dump_file)
>      fprintf (dump_file, "\noverall_size: %li, max_new_size: %li\n",
> Index: ipa-fnsummary.c
> ===================================================================
> --- ipa-fnsummary.c	(revision 272142)
> +++ ipa-fnsummary.c	(working copy)
> @@ -1987,9 +1987,9 @@ fp_expression_p (gimple *stmt)
>  static void
>  analyze_function_body (struct cgraph_node *node, bool early)
>  {
> -  sreal time = PARAM_VALUE (PARAM_UNINLINED_FUNCTION_TIME);
> +  sreal time = PARAM_VALUE_FOR_FN (node->decl, PARAM_UNINLINED_FUNCTION_TIME);
>    /* Estimate static overhead for function prologue/epilogue and alignment. */
> -  int size = PARAM_VALUE (PARAM_UNINLINED_FUNCTION_INSNS);
> +  int size = PARAM_VALUE_FOR_FN (node->decl, PARAM_UNINLINED_FUNCTION_INSNS);
>    /* Benefits are scaled by probability of elimination that is in range
>       <0,2>.  */
>    basic_block bb;
> @@ -2037,7 +2037,8 @@ analyze_function_body (struct cgraph_nod
>  	  fbi.bb_infos = vNULL;
>  	  fbi.bb_infos.safe_grow_cleared (last_basic_block_for_fn (cfun));
>  	  fbi.param_count = count_formal_params (node->decl);
> -	  fbi.aa_walk_budget = PARAM_VALUE (PARAM_IPA_MAX_AA_STEPS);
> +	  fbi.aa_walk_budget = PARAM_VALUE_FOR_FN (node->decl,
> +						   PARAM_IPA_MAX_AA_STEPS);
>  
>  	  nonconstant_names.safe_grow_cleared
>  	    (SSANAMES (my_function)->length ());
> @@ -2054,9 +2055,11 @@ analyze_function_body (struct cgraph_nod
>    info->account_size_time (0, 0, bb_predicate, bb_predicate);
>  
>    bb_predicate = predicate::not_inlined ();
> -  info->account_size_time (PARAM_VALUE (PARAM_UNINLINED_FUNCTION_INSNS)
> +  info->account_size_time (PARAM_VALUE_FOR_FN (node->decl,
> +					       PARAM_UNINLINED_FUNCTION_INSNS)
>  			   * ipa_fn_summary::size_scale,
> -			   PARAM_VALUE (PARAM_UNINLINED_FUNCTION_TIME),
> +			   PARAM_VALUE_FOR_FN (node->decl,
> +					       PARAM_UNINLINED_FUNCTION_TIME),
>  			   bb_predicate,
>  		           bb_predicate);
>  
> @@ -2441,10 +2444,12 @@ compute_fn_summary (struct cgraph_node *
>        es->call_stmt_size = eni_size_weights.call_cost;
>        es->call_stmt_time = eni_time_weights.call_cost;
>        info->account_size_time (ipa_fn_summary::size_scale
> -			       * PARAM_VALUE
> -				 (PARAM_UNINLINED_FUNCTION_THUNK_INSNS),
> -			       PARAM_VALUE
> -				 (PARAM_UNINLINED_FUNCTION_THUNK_TIME), t, t);
> +			       * PARAM_VALUE_FOR_FN
> +				 (node->decl,
> +				  PARAM_UNINLINED_FUNCTION_THUNK_INSNS),
> +			       PARAM_VALUE_FOR_FN
> +				 (node->decl,
> +				  PARAM_UNINLINED_FUNCTION_THUNK_TIME), t, t);
>        t = predicate::not_inlined ();
>        info->account_size_time (2 * ipa_fn_summary::size_scale, 0, t, t);
>        ipa_update_overall_fn_summary (node);
> Index: ipa-inline-analysis.c
> ===================================================================
> --- ipa-inline-analysis.c	(revision 272142)
> +++ ipa-inline-analysis.c	(working copy)
> @@ -343,7 +343,8 @@ estimate_growth (struct cgraph_node *nod
>        else if (DECL_COMDAT (node->decl)
>  	       && node->can_remove_if_no_direct_calls_p ())
>  	d.growth -= (info->size
> -		     * (100 - PARAM_VALUE (PARAM_COMDAT_SHARING_PROBABILITY))
> +		     * (100 - PARAM_VALUE_FOR_FN (node->decl,
> +						  PARAM_COMDAT_SHARING_PROBABILITY))
>  		     + 50) / 100;
>      }
>  
> Index: ipa-inline.c
> ===================================================================
> --- ipa-inline.c	(revision 272142)
> +++ ipa-inline.c	(working copy)
> @@ -179,13 +179,15 @@ caller_growth_limits (struct cgraph_edge
>    if (limit < what_info->self_size)
>      limit = what_info->self_size;
>  
> -  limit += limit * PARAM_VALUE (PARAM_LARGE_FUNCTION_GROWTH) / 100;
> +  limit += limit * PARAM_VALUE_FOR_FN (e->caller->decl,
> +				       PARAM_LARGE_FUNCTION_GROWTH) / 100;
>  
>    /* Check the size after inlining against the function limits.  But allow
>       the function to shrink if it went over the limits by forced inlining.  */
>    newsize = estimate_size_after_inlining (to, e);
>    if (newsize >= info->size
> -      && newsize > PARAM_VALUE (PARAM_LARGE_FUNCTION_INSNS)
> +      && newsize > PARAM_VALUE_FOR_FN (e->caller->decl,
> +				       PARAM_LARGE_FUNCTION_INSNS)
>        && newsize > limit)
>      {
>        e->inline_failed = CIF_LARGE_FUNCTION_GROWTH_LIMIT;
> @@ -201,7 +203,8 @@ caller_growth_limits (struct cgraph_edge
>       on every invocation of the caller (i.e. its call statement dominates
>       exit block).  We do not track this information, yet.  */
>    stack_size_limit += ((gcov_type)stack_size_limit
> -		       * PARAM_VALUE (PARAM_STACK_FRAME_GROWTH) / 100);
> +		       * PARAM_VALUE_FOR_FN (e->caller->decl,
> +					     PARAM_STACK_FRAME_GROWTH) / 100);
>  
>    inlined_stack = (outer_info->stack_frame_offset
>  		   + outer_info->estimated_self_stack_size
> @@ -214,7 +217,8 @@ caller_growth_limits (struct cgraph_edge
>  	 This bit overoptimistically assume that we are good at stack
>  	 packing.  */
>        && inlined_stack > info->estimated_stack_size
> -      && inlined_stack > PARAM_VALUE (PARAM_LARGE_STACK_FRAME))
> +      && inlined_stack > PARAM_VALUE_FOR_FN (e->caller->decl,
> +					     PARAM_LARGE_STACK_FRAME))
>      {
>        e->inline_failed = CIF_LARGE_STACK_FRAME_GROWTH_LIMIT;
>        return false;
> @@ -530,10 +534,15 @@ can_inline_edge_by_limits_p (struct cgra
>  	       > opt_for_fn (caller->decl, optimize_size))
>  	{
>  	  int growth = estimate_edge_growth (e);
> -	  if (growth > PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SIZE)
> +	  if (growth > PARAM_VALUE_FOR_FN (e->caller->decl,
> +					   PARAM_MAX_INLINE_INSNS_SIZE)
>  	      && (!DECL_DECLARED_INLINE_P (callee->decl)
> -		  && growth >= MAX (MAX_INLINE_INSNS_SINGLE,
> -				    MAX_INLINE_INSNS_AUTO)))
> +		  && growth >= MAX (PARAM_VALUE_FOR_FN
> +				      (e->caller->decl,
> +					PARAM_MAX_INLINE_INSNS_SINGLE),
> +				    PARAM_VALUE_FOR_FN
> +				      (e->caller->decl,
> +					PARAM_MAX_INLINE_INSNS_AUTO))))
>  	    {
>  	      e->inline_failed = CIF_OPTIMIZATION_MISMATCH;
>  	      inlinable = false;
> @@ -642,7 +651,8 @@ want_early_inline_function_p (struct cgr
>        int growth = estimate_edge_growth (e);
>        int n;
>  
> -      if (growth <= PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SIZE))
> +      if (growth <= PARAM_VALUE_FOR_FN (e->caller->decl,
> +					PARAM_MAX_INLINE_INSNS_SIZE))
>  	;
>        else if (!e->maybe_hot_p ())
>  	{
> @@ -654,7 +664,8 @@ want_early_inline_function_p (struct cgr
>  			     growth);
>  	  want_inline = false;
>  	}
> -      else if (growth > PARAM_VALUE (PARAM_EARLY_INLINING_INSNS))
> +      else if (growth > PARAM_VALUE_FOR_FN (e->caller->decl,
> +					    PARAM_EARLY_INLINING_INSNS))
>  	{
>  	  if (dump_enabled_p ())
>  	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, e->call_stmt,
> @@ -665,7 +676,9 @@ want_early_inline_function_p (struct cgr
>  	  want_inline = false;
>  	}
>        else if ((n = num_calls (callee)) != 0
> -	       && growth * (n + 1) > PARAM_VALUE (PARAM_EARLY_INLINING_INSNS))
> +	       && growth * (n + 1) > PARAM_VALUE_FOR_FN
> +					 (e->caller->decl,
> +					  PARAM_EARLY_INLINING_INSNS))
>  	{
>  	  if (dump_enabled_p ())
>  	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, e->call_stmt,
> @@ -741,7 +754,8 @@ big_speedup_p (struct cgraph_edge *e)
>    sreal inlined_time = compute_inlined_call_time (e, spec_time);
>  
>    if ((time - inlined_time) * 100
> -      > (sreal) (time * PARAM_VALUE (PARAM_INLINE_MIN_SPEEDUP)))
> +      > (sreal) (time * PARAM_VALUE_FOR_FN
> +			 (e->caller->decl, PARAM_INLINE_MIN_SPEEDUP)))
>      return true;
>    return false;
>  }
> @@ -775,7 +789,10 @@ want_inline_small_function_p (struct cgr
>  	   && (!e->count.ipa ().initialized_p () || !e->maybe_hot_p ()))
>  	   && ipa_fn_summaries->get (callee)->min_size
>  		- ipa_call_summaries->get (e)->call_stmt_size
> -	      > MAX (MAX_INLINE_INSNS_SINGLE, MAX_INLINE_INSNS_AUTO))
> +	      > MAX (PARAM_VALUE_FOR_FN (e->caller->decl,
> +					 PARAM_MAX_INLINE_INSNS_SINGLE),
> +		     PARAM_VALUE_FOR_FN (e->caller->decl,
> +					 PARAM_MAX_INLINE_INSNS_AUTO)))
>      {
>        e->inline_failed = CIF_MAX_INLINE_INSNS_AUTO_LIMIT;
>        want_inline = false;
> @@ -784,7 +801,8 @@ want_inline_small_function_p (struct cgr
>  	    || e->count.ipa ().nonzero_p ())
>  	   && ipa_fn_summaries->get (callee)->min_size
>  		- ipa_call_summaries->get (e)->call_stmt_size
> -	      > 16 * MAX_INLINE_INSNS_SINGLE)
> +	      > 16 * PARAM_VALUE_FOR_FN (e->caller->decl,
> +					 PARAM_MAX_INLINE_INSNS_SINGLE))
>      {
>        e->inline_failed = (DECL_DECLARED_INLINE_P (callee->decl)
>  			  ? CIF_MAX_INLINE_INSNS_SINGLE_LIMIT
> @@ -797,13 +815,16 @@ want_inline_small_function_p (struct cgr
>        ipa_hints hints = estimate_edge_hints (e);
>        int big_speedup = -1; /* compute this lazily */
>  
> -      if (growth <= PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SIZE))
> +      if (growth <= PARAM_VALUE_FOR_FN
> +			 (e->caller->decl, PARAM_MAX_INLINE_INSNS_SIZE))
>  	;
>        /* Apply MAX_INLINE_INSNS_SINGLE limit.  Do not do so when
>  	 hints suggests that inlining given function is very profitable.  */
>        else if (DECL_DECLARED_INLINE_P (callee->decl)
> -	       && growth >= MAX_INLINE_INSNS_SINGLE
> -	       && (growth >= MAX_INLINE_INSNS_SINGLE * 16
> +	       && growth >= PARAM_VALUE_FOR_FN (e->caller->decl,
> +						PARAM_MAX_INLINE_INSNS_SINGLE)
> +	       && (growth >= PARAM_VALUE_FOR_FN (e->caller->decl,
> +						 PARAM_MAX_INLINE_INSNS_SINGLE)
>  		   || (!(hints & (INLINE_HINT_indirect_call
>  				  | INLINE_HINT_known_hot
>  				  | INLINE_HINT_loop_iterations
> @@ -816,10 +837,12 @@ want_inline_small_function_p (struct cgr
>  	}
>        else if (!DECL_DECLARED_INLINE_P (callee->decl)
>  	       && !opt_for_fn (e->caller->decl, flag_inline_functions)
> -	       && growth >= PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SMALL))
> +	       && growth >= PARAM_VALUE_FOR_FN
> +				 (e->caller->decl, PARAM_MAX_INLINE_INSNS_SMALL))
>  	{
>  	  /* growth_likely_positive is expensive, always test it last.  */
> -          if (growth >= MAX_INLINE_INSNS_SINGLE
> +          if (growth >= PARAM_VALUE_FOR_FN (e->caller->decl,
> +					    PARAM_MAX_INLINE_INSNS_SINGLE)
>  	      || growth_likely_positive (callee, growth))
>  	    {
>                e->inline_failed = CIF_NOT_DECLARED_INLINED;
> @@ -835,13 +858,19 @@ want_inline_small_function_p (struct cgr
>  				       | INLINE_HINT_loop_iterations
>  			               | INLINE_HINT_array_index
>  				       | INLINE_HINT_loop_stride))
> -			     ? MAX (MAX_INLINE_INSNS_AUTO,
> -				    MAX_INLINE_INSNS_SINGLE)
> -			     : MAX_INLINE_INSNS_AUTO)
> +			     ? MAX (PARAM_VALUE_FOR_FN
> +					 (e->caller->decl,
> +					  PARAM_MAX_INLINE_INSNS_AUTO),
> +				    PARAM_VALUE_FOR_FN
> +					 (e->caller->decl,
> +					  PARAM_MAX_INLINE_INSNS_SINGLE))
> +			     : PARAM_VALUE_FOR_FN (e->caller->decl,
> +						   PARAM_MAX_INLINE_INSNS_AUTO))
>  	       && !(big_speedup == -1 ? big_speedup_p (e) : big_speedup))
>  	{
>  	  /* growth_likely_positive is expensive, always test it last.  */
> -          if (growth >= MAX_INLINE_INSNS_SINGLE
> +          if (growth >=	PARAM_VALUE_FOR_FN (e->caller->decl,
> +				     	    PARAM_MAX_INLINE_INSNS_SINGLE)
>  	      || growth_likely_positive (callee, growth))
>  	    {
>  	      e->inline_failed = CIF_MAX_INLINE_INSNS_AUTO_LIMIT;
> @@ -850,7 +879,8 @@ want_inline_small_function_p (struct cgr
>  	}
>        /* If call is cold, do not inline when function body would grow. */
>        else if (!e->maybe_hot_p ()
> -	       && (growth >= MAX_INLINE_INSNS_SINGLE
> +	       && (growth >= PARAM_VALUE_FOR_FN (e->caller->decl,
> +						 PARAM_MAX_INLINE_INSNS_SINGLE)
>  		   || growth_likely_positive (callee, growth)))
>  	{
>            e->inline_failed = CIF_UNLIKELY_CALL;
> @@ -882,10 +912,12 @@ want_inline_self_recursive_call_p (struc
>    char const *reason = NULL;
>    bool want_inline = true;
>    sreal caller_freq = 1;
> -  int max_depth = PARAM_VALUE (PARAM_MAX_INLINE_RECURSIVE_DEPTH_AUTO);
> +  int max_depth = PARAM_VALUE_FOR_FN (edge->caller->decl,
> +				      PARAM_MAX_INLINE_RECURSIVE_DEPTH_AUTO);
>  
>    if (DECL_DECLARED_INLINE_P (edge->caller->decl))
> -    max_depth = PARAM_VALUE (PARAM_MAX_INLINE_RECURSIVE_DEPTH);
> +    max_depth = PARAM_VALUE_FOR_FN (edge->caller->decl,
> +				    PARAM_MAX_INLINE_RECURSIVE_DEPTH);
>  
>    if (!edge->maybe_hot_p ())
>      {
> @@ -947,7 +979,8 @@ want_inline_self_recursive_call_p (struc
>      {
>        if (edge->sreal_frequency () * 100
>            <= caller_freq
> -	     * PARAM_VALUE (PARAM_MIN_INLINE_RECURSIVE_PROBABILITY))
> +	     * PARAM_VALUE_FOR_FN (edge->caller->decl,
> +			           PARAM_MIN_INLINE_RECURSIVE_PROBABILITY))
>  	{
>  	  reason = "frequency of recursive call is too small";
>  	  want_inline = false;
> @@ -1144,8 +1177,9 @@ edge_badness (struct cgraph_edge *edge,
>  		 frequency still indicates splitting is a win ... */
>  	      || (callee->split_part && !caller->split_part
>  		  && edge->sreal_frequency () * 100
> -		     < PARAM_VALUE
> -			  (PARAM_PARTIAL_INLINING_ENTRY_PROBABILITY)
> +		     < PARAM_VALUE_FOR_FN
> +			  (caller->decl,
> +			   PARAM_PARTIAL_INLINING_ENTRY_PROBABILITY)
>  		  /* ... and do not overwrite user specified hints.   */
>  		  && (!DECL_DECLARED_INLINE_P (edge->callee->decl)
>  		      || DECL_DECLARED_INLINE_P (caller->decl)))))
> @@ -1158,8 +1192,10 @@ edge_badness (struct cgraph_edge *edge,
>  	  if (!caller_info->single_caller && overall_growth < caller_growth
>  	      && caller_info->inlinable
>  	      && caller_info->size
> -		 < (DECL_DECLARED_INLINE_P (caller->decl)
> -		    ? MAX_INLINE_INSNS_SINGLE : MAX_INLINE_INSNS_AUTO))
> +		 < PARAM_VALUE_FOR_FN (caller->decl,
> +			(DECL_DECLARED_INLINE_P (caller->decl)
> +			 ? PARAM_MAX_INLINE_INSNS_SINGLE
> +			 : PARAM_MAX_INLINE_INSNS_AUTO)))
>  	    {
>  	      if (dump)
>  		fprintf (dump_file,
> @@ -1473,7 +1509,8 @@ static bool
>  recursive_inlining (struct cgraph_edge *edge,
>  		    vec<cgraph_edge *> *new_edges)
>  {
> -  int limit = PARAM_VALUE (PARAM_MAX_INLINE_INSNS_RECURSIVE_AUTO);
> +  int limit = PARAM_VALUE_FOR_FN (edge->caller->decl,
> +				  PARAM_MAX_INLINE_INSNS_RECURSIVE_AUTO);
>    edge_heap_t heap (sreal::min ());
>    struct cgraph_node *node;
>    struct cgraph_edge *e;
> @@ -1486,7 +1523,7 @@ recursive_inlining (struct cgraph_edge *
>      node = node->global.inlined_to;
>  
>    if (DECL_DECLARED_INLINE_P (node->decl))
> -    limit = PARAM_VALUE (PARAM_MAX_INLINE_INSNS_RECURSIVE);
> +    limit = PARAM_VALUE_FOR_FN (node->decl, PARAM_MAX_INLINE_INSNS_RECURSIVE);
>  
>    /* Make sure that function is small enough to be considered for inlining.  */
>    if (estimate_size_after_inlining (node, edge)  >= limit)
> @@ -1611,11 +1648,11 @@ static int
>  compute_max_insns (int insns)
>  {
>    int max_insns = insns;
> -  if (max_insns < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
> -    max_insns = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS);
> +  if (max_insns < PARAM_VALUE_GLOBAL (PARAM_LARGE_UNIT_INSNS))
> +    max_insns = PARAM_VALUE_GLOBAL (PARAM_LARGE_UNIT_INSNS);
>  
>    return ((int64_t) max_insns
> -	  * (100 + PARAM_VALUE (PARAM_INLINE_UNIT_GROWTH)) / 100);
> +	  * (100 + PARAM_VALUE_GLOBAL (PARAM_INLINE_UNIT_GROWTH)) / 100);
>  }
>  
>  
> Index: ipa-profile.c
> ===================================================================
> --- ipa-profile.c	(revision 272142)
> +++ ipa-profile.c	(working copy)
> @@ -506,7 +506,8 @@ ipa_profile (void)
>  
>        gcc_assert (overall_size);
>  
> -      cutoff = (overall_time * PARAM_VALUE (HOT_BB_COUNT_WS_PERMILLE) + 500) / 1000;
> +      cutoff = (overall_time * PARAM_VALUE_GLOBAL
> +			 (HOT_BB_COUNT_WS_PERMILLE) + 500) / 1000;
>        threshold = 0;
>        for (i = 0; cumulated < cutoff; i++)
>  	{
> Index: ipa-prop.c
> ===================================================================
> --- ipa-prop.c	(revision 272142)
> +++ ipa-prop.c	(working copy)
> @@ -1547,7 +1547,7 @@ determine_locally_known_aggregate_parts
>    bool check_ref, by_ref;
>    ao_ref r;
>  
> -  if (PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS) == 0)
> +  if (PARAM_VALUE_GLOBAL (PARAM_IPA_MAX_AGG_ITEMS) == 0)
>      return;
>  
>    /* The function operates in three stages.  First, we prepare check_ref, r,
> @@ -1675,8 +1675,8 @@ determine_locally_known_aggregate_parts
>        *p = n;
>  
>        item_count++;
> -      if (const_count == PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS)
> -	  || item_count == 2 * PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS))
> +      if (const_count == PARAM_VALUE_GLOBAL (PARAM_IPA_MAX_AGG_ITEMS)
> +	  || item_count == 2 * PARAM_VALUE_GLOBAL (PARAM_IPA_MAX_AGG_ITEMS))
>  	break;
>      }
>  
> Index: ipa-split.c
> ===================================================================
> --- ipa-split.c	(revision 272142)
> +++ ipa-split.c	(working copy)
> @@ -561,8 +561,8 @@ consider_split (struct split_point *curr
>       that.  Next stage1 we should try to be more meaningful here.  */
>    if (current->header_size + call_overhead
>        >= (unsigned int)(DECL_DECLARED_INLINE_P (current_function_decl)
> -			? MAX_INLINE_INSNS_SINGLE
> -			: MAX_INLINE_INSNS_AUTO) + 10)
> +			? PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SINGLE)
> +			: PARAM_VALUE (PARAM_MAX_INLINE_INSNS_AUTO)) + 10)
>      {
>        if (dump_file && (dump_flags & TDF_DETAILS))
>  	fprintf (dump_file,
> @@ -575,7 +575,8 @@ consider_split (struct split_point *curr
>       Limit this duplication.  This is consistent with limit in tree-sra.c  
>       FIXME: with LTO we ought to be able to do better!  */
>    if (DECL_ONE_ONLY (current_function_decl)
> -      && current->split_size >= (unsigned int) MAX_INLINE_INSNS_AUTO + 10)
> +      && current->split_size
> +	   >= (unsigned int) PARAM_VALUE (PARAM_MAX_INLINE_INSNS_AUTO) + 10)
>      {
>        if (dump_file && (dump_flags & TDF_DETAILS))
>  	fprintf (dump_file,
> Index: ira-build.c
> ===================================================================
> --- ira-build.c	(revision 272142)
> +++ ira-build.c	(working copy)
> @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3.
>  #include "params.h"
>  #include "sparseset.h"
>  #include "cfgloop.h"
> +#include "tree.h"
>  
>  static ira_copy_t find_allocno_copy (ira_allocno_t, ira_allocno_t, rtx_insn *,
>  				     ira_loop_tree_node_t);
> Index: ira-conflicts.c
> ===================================================================
> --- ira-conflicts.c	(revision 272142)
> +++ ira-conflicts.c	(working copy)
> @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3.
>  #include "params.h"
>  #include "sparseset.h"
>  #include "addresses.h"
> +#include "tree.h"
>  
>  /* This file contains code responsible for allocno conflict creation,
>     allocno copy creation and allocno info accumulation on upper level
> Index: lto/lto-partition.c
> ===================================================================
> --- lto/lto-partition.c	(revision 272142)
> +++ lto/lto-partition.c	(working copy)
> @@ -560,13 +560,13 @@ lto_balanced_map (int n_lto_partitions,
>    varpool_order.qsort (varpool_node_cmp);
>  
>    /* Compute partition size and create the first partition.  */
> -  if (PARAM_VALUE (MIN_PARTITION_SIZE) > max_partition_size)
> +  if (PARAM_VALUE_GLOBAL (MIN_PARTITION_SIZE) > max_partition_size)
>      fatal_error (input_location, "min partition size cannot be greater "
>  		 "than max partition size");
>  
>    partition_size = total_size / n_lto_partitions;
> -  if (partition_size < PARAM_VALUE (MIN_PARTITION_SIZE))
> -    partition_size = PARAM_VALUE (MIN_PARTITION_SIZE);
> +  if (partition_size < PARAM_VALUE_GLOBAL (MIN_PARTITION_SIZE))
> +    partition_size = PARAM_VALUE_GLOBAL (MIN_PARTITION_SIZE);
>    npartitions = 1;
>    partition = new_partition ("");
>    if (dump_file)
> @@ -816,8 +816,8 @@ lto_balanced_map (int n_lto_partitions,
>  	    fprintf (dump_file,
>  		     "Total size: %" PRId64 " partition_size: %" PRId64 "\n",
>  		     total_size, partition_size);
> -	  if (partition_size < PARAM_VALUE (MIN_PARTITION_SIZE))
> -	    partition_size = PARAM_VALUE (MIN_PARTITION_SIZE);
> +	  if (partition_size < PARAM_VALUE_GLOBAL (MIN_PARTITION_SIZE))
> +	    partition_size = PARAM_VALUE_GLOBAL (MIN_PARTITION_SIZE);
>  	  npartitions ++;
>  	}
>      }
> Index: lto/lto.c
> ===================================================================
> --- lto/lto.c	(revision 272142)
> +++ lto/lto.c	(working copy)
> @@ -420,14 +420,16 @@ do_whole_program_analysis (void)
>  
>    /* TODO: jobserver communication is not supported, yet.  */
>    if (!strcmp (flag_wpa, "jobserver"))
> -    lto_parallelism = PARAM_VALUE (PARAM_MAX_LTO_STREAMING_PARALLELISM);
> +    lto_parallelism = PARAM_VALUE_GLOBAL (PARAM_MAX_LTO_STREAMING_PARALLELISM);
>    else
>      {
>        lto_parallelism = atoi (flag_wpa);
>        if (lto_parallelism <= 0)
>  	lto_parallelism = 0;
> -      if (lto_parallelism >= PARAM_VALUE (PARAM_MAX_LTO_STREAMING_PARALLELISM))
> -	lto_parallelism = PARAM_VALUE (PARAM_MAX_LTO_STREAMING_PARALLELISM);
> +      if (lto_parallelism >= PARAM_VALUE_GLOBAL
> +				 (PARAM_MAX_LTO_STREAMING_PARALLELISM))
> +	lto_parallelism = PARAM_VALUE_GLOBAL
> +			     (PARAM_MAX_LTO_STREAMING_PARALLELISM);
>      }
>  
>    timevar_start (TV_PHASE_OPT_GEN);
> @@ -479,8 +481,8 @@ do_whole_program_analysis (void)
>    else if (flag_lto_partition == LTO_PARTITION_ONE)
>      lto_balanced_map (1, INT_MAX);
>    else if (flag_lto_partition == LTO_PARTITION_BALANCED)
> -    lto_balanced_map (PARAM_VALUE (PARAM_LTO_PARTITIONS),
> -		      PARAM_VALUE (MAX_PARTITION_SIZE));
> +    lto_balanced_map (PARAM_VALUE_GLOBAL (PARAM_LTO_PARTITIONS),
> +		      PARAM_VALUE_GLOBAL (MAX_PARTITION_SIZE));
>    else
>      gcc_unreachable ();
>  
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE Linux GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany;
GF: Felix Imendörffer, Mary Higgins, Sri Rasiah; HRB 21284 (AG NÌrnberg)


More information about the Gcc-patches mailing list