* testsuite/gcc.target/i386/pr57756.c: New test. * tree.c (build_optimization_node): New parameter. (build_target_option_node): New parameter. * tree.h (build_optimization_node): New parameter. (build_target_option_node): New parameter. * c-family/c-common.c (handle_optimize_attribute): Fix calls to build_optimization_node and build_target_option_node. * c-family/c-pragma.c (handle_pragma_optimize): Ditto. (handle_pragma_push_options): Ditto. * toplev.c (process_options): Ditto. * config/i386/i386-c.c (ix86_target_macros_internal): Ditto. (ix86_pragma_target_parse): Ditto. * config/i386/i386-protos.h (ix86_valid_target_attribute_tree): New parameters. * config/rs6000/rs6000.c (rs6000_option_override_internal): Fix calls to build_optimization_node and build_target_option_node. (rs6000_valid_attribute_p): Ditto. (rs6000_pragma_target_parse): Ditto. * config/i386/i386.c (ix86_option_override_internal): New parameters opts and opts_set. Change ix86_tune_string to access opts->x_ix86_tune_string. Change ix86_isa_flags to access opts->x_ix86_isa_flags. Change ix86_arch_string to access opts->x_ix86_arch_string. Change ix86_stringop_alg to access opts->x_ix86_stringop_alg. Change ix86_pmode to access opts->x_ix86_pmode. Change ix86_abi to access opts->x_ix86_abi. Change ix86_cmodel to access opts->x_ix86_cmodel. Change ix86_asm_dialect to access opts->x_ix86_asm_dialect. Change ix86_isa_flags_explicit to access opts->x_ix86_isa_flags_explicit. Change ix86_dump_tunes to access opts->x_ix86_dump_tunes. Change ix86_regparm to access opts->x_ix86_regparm. Change ix86_branch_cost to access opts->x_ix86_branch_cost. Change ix86_preferred_stack_boundary_arg to access opts->x_ix86_preferred_stack_boundary_arg. Change ix86_force_align_arg_pointer to access opts->x_ix86_force_align_arg_pointer. Change ix86_incoming_stack_boundar_arg to access opts->x_ix86_incoming_stack_boundar_arg. Change ix86_fpmath to access opts->x_ix86_fpmath. Change ix86_veclibabi_type to access opts->x_ix86_veclibabi_type. Change ix86_recip_name to access opts->x_ix86_recip_name. Change ix86_stack_protector_guard to access opts->x_ix86_stack_protector_guard. Change ix86_tune_memcpy_strategy to access opts->x_ix86_tune_memcpy_strategy. Change ix86_tune_memset_strategy to access opts->x_ix86_tune_memset_strategy. Change global_options to access opts. Change global_options_set to access opts_set. (ix86_valid_target_attribute_inner_p): New parameters. Fix recursive call. Fix call to ix86_handle_option and set_option. (ix86_valid_target_attribute_tree): New parameters. Change global_options to access opts. Change global_options_set to access opts_set. Fix call to ix86_valid_target_attribute_inner_p. Change ix86_tune_string to access opts->x_ix86_tune_string. Change ix86_arch_string to access opts->x_ix86_arch_string. Change ix86_fpmath to access opts->x_ix86_fpmath Fix call to ix86_option_override_internal. Fix call to ix86_add_new_builtins. Fix calls to build_optimization_node and build_target_option_node. (ix86_valid_target_attribute_p): Remove access to global_options. Use new gcc_options structure func_options. Fix call to ix86_valid_target_attribute_tree. Fix call to build_optimization_node. (get_builtin_code_for_version): Fix call to ix86_valid_target_attribute_tree. Index: c-family/c-common.c =================================================================== --- c-family/c-common.c (revision 202662) +++ c-family/c-common.c (working copy) @@ -8993,7 +8993,7 @@ handle_optimize_attribute (tree *node, tree name, /* Parse options, and update the vector. */ parse_optimize_options (args, true); DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node) - = build_optimization_node (); + = build_optimization_node (&global_options); /* Restore current options. */ cl_optimization_restore (&global_options, &cur_opts); Index: c-family/c-pragma.c =================================================================== --- c-family/c-pragma.c (revision 202662) +++ c-family/c-pragma.c (working copy) @@ -872,7 +872,7 @@ handle_pragma_optimize (cpp_reader *ARG_UNUSED(dum parse_optimize_options (args, false); current_optimize_pragma = chainon (current_optimize_pragma, args); - optimization_current_node = build_optimization_node (); + optimization_current_node = build_optimization_node (&global_options); c_cpp_builtins_optimize_pragma (parse_in, optimization_previous_node, optimization_current_node); @@ -914,8 +914,8 @@ handle_pragma_push_options (cpp_reader *ARG_UNUSED options_stack = p; /* Save optimization and target flags in binary format. */ - p->optimize_binary = build_optimization_node (); - p->target_binary = build_target_option_node (); + p->optimize_binary = build_optimization_node (&global_options); + p->target_binary = build_target_option_node (&global_options); /* Save optimization and target flags in string list format. */ p->optimize_strings = copy_list (current_optimize_pragma); Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 202662) +++ config/i386/i386.c (working copy) @@ -2333,6 +2333,8 @@ static void ix86_function_specific_print (FILE *, struct cl_target_option *); static bool ix86_valid_target_attribute_p (tree, tree, tree, int); static bool ix86_valid_target_attribute_inner_p (tree, char *[], + struct gcc_options *, + struct gcc_options *, struct gcc_options *); static bool ix86_can_inline_p (tree, tree); static void ix86_set_current_function (tree); @@ -2997,11 +2999,13 @@ set_ix86_tune_features (enum processor_type ix86_t attributes. */ static void -ix86_option_override_internal (bool main_args_p) +ix86_option_override_internal (bool main_args_p, + struct gcc_options *opts, + struct gcc_options *opts_set) { int i; unsigned int ix86_arch_mask, ix86_tune_mask; - const bool ix86_tune_specified = (ix86_tune_string != NULL); + const bool ix86_tune_specified = (opts->x_ix86_tune_string != NULL); const char *prefix; const char *suffix; const char *sw; @@ -3236,7 +3240,7 @@ static void /* Turn off both OPTION_MASK_ABI_64 and OPTION_MASK_ABI_X32 if TARGET_64BIT_DEFAULT is true and TARGET_64BIT is false. */ if (TARGET_64BIT_DEFAULT && !TARGET_64BIT) - ix86_isa_flags &= ~(OPTION_MASK_ABI_64 | OPTION_MASK_ABI_X32); + opts->x_ix86_isa_flags &= ~(OPTION_MASK_ABI_64 | OPTION_MASK_ABI_X32); #ifdef TARGET_BI_ARCH else { @@ -3246,14 +3250,14 @@ static void OPTION_MASK_ABI_64 if OPTION_MASK_ABI_X32 is turned on by -mx32. */ if (TARGET_X32) - ix86_isa_flags &= ~OPTION_MASK_ABI_64; + opts->x_ix86_isa_flags &= ~OPTION_MASK_ABI_64; #else /* When TARGET_BI_ARCH == 2, by default, OPTION_MASK_ABI_X32 is on and OPTION_MASK_ABI_64 is off. We turn off OPTION_MASK_ABI_X32 if OPTION_MASK_ABI_64 is turned on by -m64. */ if (TARGET_LP64) - ix86_isa_flags &= ~OPTION_MASK_ABI_X32; + opts->x_ix86_isa_flags &= ~OPTION_MASK_ABI_X32; #endif } #endif @@ -3262,15 +3266,15 @@ static void { /* Always turn on OPTION_MASK_ISA_64BIT and turn off OPTION_MASK_ABI_64 for TARGET_X32. */ - ix86_isa_flags |= OPTION_MASK_ISA_64BIT; - ix86_isa_flags &= ~OPTION_MASK_ABI_64; + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_64BIT; + opts->x_ix86_isa_flags &= ~OPTION_MASK_ABI_64; } else if (TARGET_LP64) { /* Always turn on OPTION_MASK_ISA_64BIT and turn off OPTION_MASK_ABI_X32 for TARGET_LP64. */ - ix86_isa_flags |= OPTION_MASK_ISA_64BIT; - ix86_isa_flags &= ~OPTION_MASK_ABI_X32; + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_64BIT; + opts->x_ix86_isa_flags &= ~OPTION_MASK_ABI_X32; } #ifdef SUBTARGET_OVERRIDE_OPTIONS @@ -3286,97 +3290,98 @@ static void flag_pic = 2; /* Need to check -mtune=generic first. */ - if (ix86_tune_string) + if (opts->x_ix86_tune_string) { - if (!strcmp (ix86_tune_string, "generic") - || !strcmp (ix86_tune_string, "i686") + if (!strcmp (opts->x_ix86_tune_string, "generic") + || !strcmp (opts->x_ix86_tune_string, "i686") /* As special support for cross compilers we read -mtune=native as -mtune=generic. With native compilers we won't see the -mtune=native, as it was changed by the driver. */ - || !strcmp (ix86_tune_string, "native")) + || !strcmp (opts->x_ix86_tune_string, "native")) { if (TARGET_64BIT) - ix86_tune_string = "generic64"; + opts->x_ix86_tune_string = "generic64"; else - ix86_tune_string = "generic32"; + opts->x_ix86_tune_string = "generic32"; } /* If this call is for setting the option attribute, allow the generic32/generic64 that was previously set. */ else if (!main_args_p - && (!strcmp (ix86_tune_string, "generic32") - || !strcmp (ix86_tune_string, "generic64"))) + && (!strcmp (opts->x_ix86_tune_string, "generic32") + || !strcmp (opts->x_ix86_tune_string, "generic64"))) ; - else if (!strncmp (ix86_tune_string, "generic", 7)) + else if (!strncmp (opts->x_ix86_tune_string, "generic", 7)) error ("bad value (%s) for %stune=%s %s", - ix86_tune_string, prefix, suffix, sw); - else if (!strcmp (ix86_tune_string, "x86-64")) + opts->x_ix86_tune_string, prefix, suffix, sw); + else if (!strcmp (opts->x_ix86_tune_string, "x86-64")) warning (OPT_Wdeprecated, "%stune=x86-64%s is deprecated; use " "%stune=k8%s or %stune=generic%s instead as appropriate", prefix, suffix, prefix, suffix, prefix, suffix); } else { - if (ix86_arch_string) - ix86_tune_string = ix86_arch_string; - if (!ix86_tune_string) + if (opts->x_ix86_arch_string) + opts->x_ix86_tune_string = opts->x_ix86_arch_string; + if (!opts->x_ix86_tune_string) { - ix86_tune_string = cpu_names[TARGET_CPU_DEFAULT]; + opts->x_ix86_tune_string = cpu_names[TARGET_CPU_DEFAULT]; ix86_tune_defaulted = 1; } - /* ix86_tune_string is set to ix86_arch_string or defaulted. We - need to use a sensible tune option. */ - if (!strcmp (ix86_tune_string, "generic") - || !strcmp (ix86_tune_string, "x86-64") - || !strcmp (ix86_tune_string, "i686")) + /* opts->x_ix86_tune_string is set to opts->x_ix86_arch_string + or defaulted. We need to use a sensible tune option. */ + if (!strcmp (opts->x_ix86_tune_string, "generic") + || !strcmp (opts->x_ix86_tune_string, "x86-64") + || !strcmp (opts->x_ix86_tune_string, "i686")) { if (TARGET_64BIT) - ix86_tune_string = "generic64"; + opts->x_ix86_tune_string = "generic64"; else - ix86_tune_string = "generic32"; + opts->x_ix86_tune_string = "generic32"; } } - if (ix86_stringop_alg == rep_prefix_8_byte && !TARGET_64BIT) + if (opts->x_ix86_stringop_alg == rep_prefix_8_byte && !TARGET_64BIT) { /* rep; movq isn't available in 32-bit code. */ error ("-mstringop-strategy=rep_8byte not supported for 32-bit code"); - ix86_stringop_alg = no_stringop; + opts->x_ix86_stringop_alg = no_stringop; } - if (!ix86_arch_string) - ix86_arch_string = TARGET_64BIT ? "x86-64" : SUBTARGET32_DEFAULT_CPU; + if (!opts->x_ix86_arch_string) + opts->x_ix86_arch_string + = TARGET_64BIT ? "x86-64" : SUBTARGET32_DEFAULT_CPU; else ix86_arch_specified = 1; - if (global_options_set.x_ix86_pmode) + if (opts_set->x_ix86_pmode) { - if ((TARGET_LP64 && ix86_pmode == PMODE_SI) - || (!TARGET_64BIT && ix86_pmode == PMODE_DI)) + if ((TARGET_LP64 && opts->x_ix86_pmode == PMODE_SI) + || (!TARGET_64BIT && opts->x_ix86_pmode == PMODE_DI)) error ("address mode %qs not supported in the %s bit mode", TARGET_64BIT ? "short" : "long", TARGET_64BIT ? "64" : "32"); } else - ix86_pmode = TARGET_LP64 ? PMODE_DI : PMODE_SI; + opts->x_ix86_pmode = TARGET_LP64 ? PMODE_DI : PMODE_SI; - if (!global_options_set.x_ix86_abi) - ix86_abi = DEFAULT_ABI; + if (!opts_set->x_ix86_abi) + opts->x_ix86_abi = DEFAULT_ABI; /* For targets using ms ABI enable ms-extensions, if not explicit turned off. For non-ms ABI we turn off this option. */ - if (!global_options_set.x_flag_ms_extensions) + if (!opts_set->x_flag_ms_extensions) flag_ms_extensions = (MS_ABI == DEFAULT_ABI); - if (global_options_set.x_ix86_cmodel) + if (opts_set->x_ix86_cmodel) { - switch (ix86_cmodel) + switch (opts->x_ix86_cmodel) { case CM_SMALL: case CM_SMALL_PIC: if (flag_pic) - ix86_cmodel = CM_SMALL_PIC; + opts->x_ix86_cmodel = CM_SMALL_PIC; if (!TARGET_64BIT) error ("code model %qs not supported in the %s bit mode", "small", "32"); @@ -3385,7 +3390,7 @@ static void case CM_MEDIUM: case CM_MEDIUM_PIC: if (flag_pic) - ix86_cmodel = CM_MEDIUM_PIC; + opts->x_ix86_cmodel = CM_MEDIUM_PIC; if (!TARGET_64BIT) error ("code model %qs not supported in the %s bit mode", "medium", "32"); @@ -3397,7 +3402,7 @@ static void case CM_LARGE: case CM_LARGE_PIC: if (flag_pic) - ix86_cmodel = CM_LARGE_PIC; + opts->x_ix86_cmodel = CM_LARGE_PIC; if (!TARGET_64BIT) error ("code model %qs not supported in the %s bit mode", "large", "32"); @@ -3418,7 +3423,7 @@ static void if (flag_pic) { error ("code model %s does not support PIC mode", "kernel"); - ix86_cmodel = CM_32; + opts->x_ix86_cmodel = CM_32; } if (!TARGET_64BIT) error ("code model %qs not supported in the %s bit mode", @@ -3436,23 +3441,24 @@ static void would otherwise be needed if this object is to be placed in a DLL, and is essentially just as efficient as direct addressing. */ if (TARGET_64BIT && (TARGET_RDOS || TARGET_PECOFF)) - ix86_cmodel = CM_MEDIUM_PIC, flag_pic = 1; + opts->x_ix86_cmodel = CM_MEDIUM_PIC, flag_pic = 1; else if (TARGET_64BIT) - ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL; + opts->x_ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL; else - ix86_cmodel = CM_32; + opts->x_ix86_cmodel = CM_32; } - if (TARGET_MACHO && ix86_asm_dialect == ASM_INTEL) + if (TARGET_MACHO && opts->x_ix86_asm_dialect == ASM_INTEL) { error ("-masm=intel not supported in this configuration"); - ix86_asm_dialect = ASM_ATT; + opts->x_ix86_asm_dialect = ASM_ATT; } - if ((TARGET_64BIT != 0) != ((ix86_isa_flags & OPTION_MASK_ISA_64BIT) != 0)) + if ((TARGET_64BIT != 0) + != ((opts->x_ix86_isa_flags & OPTION_MASK_ISA_64BIT) != 0)) sorry ("%i-bit mode not compiled in", - (ix86_isa_flags & OPTION_MASK_ISA_64BIT) ? 64 : 32); + (opts->x_ix86_isa_flags & OPTION_MASK_ISA_64BIT) ? 64 : 32); for (i = 0; i < pta_size; i++) - if (! strcmp (ix86_arch_string, processor_alias_table[i].name)) + if (! strcmp (opts->x_ix86_arch_string, processor_alias_table[i].name)) { ix86_schedule = processor_alias_table[i].schedule; ix86_arch = processor_alias_table[i].processor; @@ -3464,150 +3470,150 @@ static void "instruction set"); if (processor_alias_table[i].flags & PTA_MMX - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_MMX)) - ix86_isa_flags |= OPTION_MASK_ISA_MMX; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_MMX)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_MMX; if (processor_alias_table[i].flags & PTA_3DNOW - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_3DNOW)) - ix86_isa_flags |= OPTION_MASK_ISA_3DNOW; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_3DNOW)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_3DNOW; if (processor_alias_table[i].flags & PTA_3DNOW_A - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_3DNOW_A)) - ix86_isa_flags |= OPTION_MASK_ISA_3DNOW_A; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_3DNOW_A)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_3DNOW_A; if (processor_alias_table[i].flags & PTA_SSE - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE)) - ix86_isa_flags |= OPTION_MASK_ISA_SSE; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSE; if (processor_alias_table[i].flags & PTA_SSE2 - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE2)) - ix86_isa_flags |= OPTION_MASK_ISA_SSE2; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE2)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSE2; if (processor_alias_table[i].flags & PTA_SSE3 - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE3)) - ix86_isa_flags |= OPTION_MASK_ISA_SSE3; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE3)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSE3; if (processor_alias_table[i].flags & PTA_SSSE3 - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_SSSE3)) - ix86_isa_flags |= OPTION_MASK_ISA_SSSE3; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_SSSE3)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSSE3; if (processor_alias_table[i].flags & PTA_SSE4_1 - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE4_1)) - ix86_isa_flags |= OPTION_MASK_ISA_SSE4_1; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE4_1)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSE4_1; if (processor_alias_table[i].flags & PTA_SSE4_2 - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE4_2)) - ix86_isa_flags |= OPTION_MASK_ISA_SSE4_2; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE4_2)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSE4_2; if (processor_alias_table[i].flags & PTA_AVX - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX)) - ix86_isa_flags |= OPTION_MASK_ISA_AVX; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AVX; if (processor_alias_table[i].flags & PTA_AVX2 - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX2)) - ix86_isa_flags |= OPTION_MASK_ISA_AVX2; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX2)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AVX2; if (processor_alias_table[i].flags & PTA_FMA - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_FMA)) - ix86_isa_flags |= OPTION_MASK_ISA_FMA; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_FMA)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_FMA; if (processor_alias_table[i].flags & PTA_SSE4A - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE4A)) - ix86_isa_flags |= OPTION_MASK_ISA_SSE4A; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE4A)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSE4A; if (processor_alias_table[i].flags & PTA_FMA4 - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_FMA4)) - ix86_isa_flags |= OPTION_MASK_ISA_FMA4; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_FMA4)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_FMA4; if (processor_alias_table[i].flags & PTA_XOP - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_XOP)) - ix86_isa_flags |= OPTION_MASK_ISA_XOP; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_XOP)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_XOP; if (processor_alias_table[i].flags & PTA_LWP - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_LWP)) - ix86_isa_flags |= OPTION_MASK_ISA_LWP; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_LWP)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_LWP; if (processor_alias_table[i].flags & PTA_ABM - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_ABM)) - ix86_isa_flags |= OPTION_MASK_ISA_ABM; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_ABM)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_ABM; if (processor_alias_table[i].flags & PTA_BMI - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_BMI)) - ix86_isa_flags |= OPTION_MASK_ISA_BMI; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_BMI)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_BMI; if (processor_alias_table[i].flags & (PTA_LZCNT | PTA_ABM) - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_LZCNT)) - ix86_isa_flags |= OPTION_MASK_ISA_LZCNT; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_LZCNT)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_LZCNT; if (processor_alias_table[i].flags & PTA_TBM - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_TBM)) - ix86_isa_flags |= OPTION_MASK_ISA_TBM; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_TBM)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_TBM; if (processor_alias_table[i].flags & PTA_BMI2 - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_BMI2)) - ix86_isa_flags |= OPTION_MASK_ISA_BMI2; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_BMI2)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_BMI2; if (processor_alias_table[i].flags & PTA_CX16 - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_CX16)) - ix86_isa_flags |= OPTION_MASK_ISA_CX16; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_CX16)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_CX16; if (processor_alias_table[i].flags & (PTA_POPCNT | PTA_ABM) - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_POPCNT)) - ix86_isa_flags |= OPTION_MASK_ISA_POPCNT; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_POPCNT)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_POPCNT; if (!(TARGET_64BIT && (processor_alias_table[i].flags & PTA_NO_SAHF)) - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_SAHF)) - ix86_isa_flags |= OPTION_MASK_ISA_SAHF; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_SAHF)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SAHF; if (processor_alias_table[i].flags & PTA_MOVBE - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_MOVBE)) - ix86_isa_flags |= OPTION_MASK_ISA_MOVBE; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_MOVBE)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_MOVBE; if (processor_alias_table[i].flags & PTA_AES - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_AES)) - ix86_isa_flags |= OPTION_MASK_ISA_AES; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_AES)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AES; if (processor_alias_table[i].flags & PTA_PCLMUL - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_PCLMUL)) - ix86_isa_flags |= OPTION_MASK_ISA_PCLMUL; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_PCLMUL)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_PCLMUL; if (processor_alias_table[i].flags & PTA_FSGSBASE - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_FSGSBASE)) - ix86_isa_flags |= OPTION_MASK_ISA_FSGSBASE; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_FSGSBASE)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_FSGSBASE; if (processor_alias_table[i].flags & PTA_RDRND - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_RDRND)) - ix86_isa_flags |= OPTION_MASK_ISA_RDRND; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_RDRND)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_RDRND; if (processor_alias_table[i].flags & PTA_F16C - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_F16C)) - ix86_isa_flags |= OPTION_MASK_ISA_F16C; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_F16C)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_F16C; if (processor_alias_table[i].flags & PTA_RTM - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_RTM)) - ix86_isa_flags |= OPTION_MASK_ISA_RTM; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_RTM)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_RTM; if (processor_alias_table[i].flags & PTA_HLE - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_HLE)) - ix86_isa_flags |= OPTION_MASK_ISA_HLE; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_HLE)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_HLE; if (processor_alias_table[i].flags & PTA_PRFCHW - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_PRFCHW)) - ix86_isa_flags |= OPTION_MASK_ISA_PRFCHW; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_PRFCHW)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_PRFCHW; if (processor_alias_table[i].flags & PTA_RDSEED - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_RDSEED)) - ix86_isa_flags |= OPTION_MASK_ISA_RDSEED; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_RDSEED)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_RDSEED; if (processor_alias_table[i].flags & PTA_ADX - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_ADX)) - ix86_isa_flags |= OPTION_MASK_ISA_ADX; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_ADX)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_ADX; if (processor_alias_table[i].flags & PTA_FXSR - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_FXSR)) - ix86_isa_flags |= OPTION_MASK_ISA_FXSR; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_FXSR)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_FXSR; if (processor_alias_table[i].flags & PTA_XSAVE - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_XSAVE)) - ix86_isa_flags |= OPTION_MASK_ISA_XSAVE; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_XSAVE)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_XSAVE; if (processor_alias_table[i].flags & PTA_XSAVEOPT - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_XSAVEOPT)) - ix86_isa_flags |= OPTION_MASK_ISA_XSAVEOPT; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_XSAVEOPT)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_XSAVEOPT; if (processor_alias_table[i].flags & PTA_AVX512F - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX512F)) - ix86_isa_flags |= OPTION_MASK_ISA_AVX512F; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX512F)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AVX512F; if (processor_alias_table[i].flags & PTA_AVX512ER - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX512ER)) - ix86_isa_flags |= OPTION_MASK_ISA_AVX512ER; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX512ER)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AVX512ER; if (processor_alias_table[i].flags & PTA_AVX512PF - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX512PF)) - ix86_isa_flags |= OPTION_MASK_ISA_AVX512PF; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX512PF)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AVX512PF; if (processor_alias_table[i].flags & PTA_AVX512CD - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX512CD)) - ix86_isa_flags |= OPTION_MASK_ISA_AVX512CD; + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX512CD)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AVX512CD; if (processor_alias_table[i].flags & (PTA_PREFETCH_SSE | PTA_SSE)) x86_prefetch_sse = true; break; } - if (!strcmp (ix86_arch_string, "generic")) + if (!strcmp (opts->x_ix86_arch_string, "generic")) error ("generic CPU can be used only for %stune=%s %s", prefix, suffix, sw); - else if (!strncmp (ix86_arch_string, "generic", 7) || i == pta_size) + else if (!strncmp (opts->x_ix86_arch_string, "generic", 7) || i == pta_size) error ("bad value (%s) for %sarch=%s %s", - ix86_arch_string, prefix, suffix, sw); + opts->x_ix86_arch_string, prefix, suffix, sw); ix86_arch_mask = 1u << ix86_arch; for (i = 0; i < X86_ARCH_LAST; ++i) ix86_arch_features[i] = !!(initial_ix86_arch_features[i] & ix86_arch_mask); for (i = 0; i < pta_size; i++) - if (! strcmp (ix86_tune_string, processor_alias_table[i].name)) + if (! strcmp (opts->x_ix86_tune_string, processor_alias_table[i].name)) { ix86_schedule = processor_alias_table[i].schedule; ix86_tune = processor_alias_table[i].processor; @@ -3617,9 +3623,9 @@ static void { if (ix86_tune_defaulted) { - ix86_tune_string = "x86-64"; + opts->x_ix86_tune_string = "x86-64"; for (i = 0; i < pta_size; i++) - if (! strcmp (ix86_tune_string, + if (! strcmp (opts->x_ix86_tune_string, processor_alias_table[i].name)) break; ix86_schedule = processor_alias_table[i].schedule; @@ -3657,9 +3663,9 @@ static void if (ix86_tune_specified && i == pta_size) error ("bad value (%s) for %stune=%s %s", - ix86_tune_string, prefix, suffix, sw); + opts->x_ix86_tune_string, prefix, suffix, sw); - set_ix86_tune_features (ix86_tune, ix86_dump_tunes); + set_ix86_tune_features (ix86_tune, opts->x_ix86_dump_tunes); #ifndef USE_IX86_FRAME_POINTER #define USE_IX86_FRAME_POINTER 0 @@ -3673,7 +3679,7 @@ static void in case they weren't overwritten by command line options. */ if (TARGET_64BIT) { - if (optimize >= 1 && !global_options_set.x_flag_omit_frame_pointer) + if (optimize >= 1 && !opts_set->x_flag_omit_frame_pointer) flag_omit_frame_pointer = !USE_X86_64_FRAME_POINTER; if (flag_asynchronous_unwind_tables == 2) flag_unwind_tables = flag_asynchronous_unwind_tables = 1; @@ -3682,7 +3688,7 @@ static void } else { - if (optimize >= 1 && !global_options_set.x_flag_omit_frame_pointer) + if (optimize >= 1 && !opts_set->x_flag_omit_frame_pointer) flag_omit_frame_pointer = !(USE_IX86_FRAME_POINTER || optimize_size); if (flag_asynchronous_unwind_tables == 2) flag_asynchronous_unwind_tables = !USE_IX86_FRAME_POINTER; @@ -3700,19 +3706,19 @@ static void init_machine_status = ix86_init_machine_status; /* Validate -mregparm= value. */ - if (global_options_set.x_ix86_regparm) + if (opts_set->x_ix86_regparm) { if (TARGET_64BIT) warning (0, "-mregparm is ignored in 64-bit mode"); - if (ix86_regparm > REGPARM_MAX) + if (opts->x_ix86_regparm > REGPARM_MAX) { error ("-mregparm=%d is not between 0 and %d", - ix86_regparm, REGPARM_MAX); - ix86_regparm = 0; + opts->x_ix86_regparm, REGPARM_MAX); + opts->x_ix86_regparm = 0; } } if (TARGET_64BIT) - ix86_regparm = REGPARM_MAX; + opts->x_ix86_regparm = REGPARM_MAX; /* Default align_* from the processor table. */ if (align_loops == 0) @@ -3731,8 +3737,8 @@ static void } /* Provide default for -mbranch-cost= value. */ - if (!global_options_set.x_ix86_branch_cost) - ix86_branch_cost = ix86_cost->branch_cost; + if (!opts_set->x_ix86_branch_cost) + opts->x_ix86_branch_cost = ix86_cost->branch_cost; if (TARGET_64BIT) { @@ -3742,9 +3748,10 @@ static void explicitly disable any of these. In particular, disabling SSE and MMX for kernel code is extremely useful. */ if (!ix86_arch_specified) - ix86_isa_flags + opts->x_ix86_isa_flags |= ((OPTION_MASK_ISA_SSE2 | OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_MMX - | TARGET_SUBTARGET64_ISA_DEFAULT) & ~ix86_isa_flags_explicit); + | TARGET_SUBTARGET64_ISA_DEFAULT) + & ~opts->x_ix86_isa_flags_explicit); if (TARGET_RTD) warning (0, "%srtd%s is ignored in 64bit mode", prefix, suffix); @@ -3754,8 +3761,8 @@ static void target_flags |= TARGET_SUBTARGET32_DEFAULT & ~target_flags_explicit; if (!ix86_arch_specified) - ix86_isa_flags - |= TARGET_SUBTARGET32_ISA_DEFAULT & ~ix86_isa_flags_explicit; + opts->x_ix86_isa_flags + |= TARGET_SUBTARGET32_ISA_DEFAULT & ~opts->x_ix86_isa_flags_explicit; /* i386 ABI does not specify red zone. It still makes sense to use it when programmer takes care to stack from being destroyed. */ @@ -3786,7 +3793,8 @@ static void /* Turn on MMX builtins for -msse. */ if (TARGET_SSE) - ix86_isa_flags |= OPTION_MASK_ISA_MMX & ~ix86_isa_flags_explicit; + opts->x_ix86_isa_flags + |= OPTION_MASK_ISA_MMX & ~opts->x_ix86_isa_flags_explicit; /* Enable SSE prefetch. */ if (TARGET_SSE || (TARGET_PRFCHW && !TARGET_3DNOW)) @@ -3794,49 +3802,52 @@ static void /* Enable prefetch{,w} instructions for -m3dnow. */ if (TARGET_3DNOW) - ix86_isa_flags |= OPTION_MASK_ISA_PRFCHW & ~ix86_isa_flags_explicit; + opts->x_ix86_isa_flags + |= OPTION_MASK_ISA_PRFCHW & ~opts->x_ix86_isa_flags_explicit; /* Enable popcnt instruction for -msse4.2 or -mabm. */ if (TARGET_SSE4_2 || TARGET_ABM) - ix86_isa_flags |= OPTION_MASK_ISA_POPCNT & ~ix86_isa_flags_explicit; + opts->x_ix86_isa_flags + |= OPTION_MASK_ISA_POPCNT & ~opts->x_ix86_isa_flags_explicit; /* Enable lzcnt instruction for -mabm. */ if (TARGET_ABM) - ix86_isa_flags |= OPTION_MASK_ISA_LZCNT & ~ix86_isa_flags_explicit; + opts->x_ix86_isa_flags + |= OPTION_MASK_ISA_LZCNT & ~opts->x_ix86_isa_flags_explicit; /* Validate -mpreferred-stack-boundary= value or default it to PREFERRED_STACK_BOUNDARY_DEFAULT. */ ix86_preferred_stack_boundary = PREFERRED_STACK_BOUNDARY_DEFAULT; - if (global_options_set.x_ix86_preferred_stack_boundary_arg) + if (opts_set->x_ix86_preferred_stack_boundary_arg) { int min = (TARGET_64BIT ? (TARGET_SSE ? 4 : 3) : 2); int max = (TARGET_SEH ? 4 : 12); - if (ix86_preferred_stack_boundary_arg < min - || ix86_preferred_stack_boundary_arg > max) + if (opts->x_ix86_preferred_stack_boundary_arg < min + || opts->x_ix86_preferred_stack_boundary_arg > max) { if (min == max) error ("-mpreferred-stack-boundary is not supported " "for this target"); else error ("-mpreferred-stack-boundary=%d is not between %d and %d", - ix86_preferred_stack_boundary_arg, min, max); + opts->x_ix86_preferred_stack_boundary_arg, min, max); } else ix86_preferred_stack_boundary - = (1 << ix86_preferred_stack_boundary_arg) * BITS_PER_UNIT; + = (1 << opts->x_ix86_preferred_stack_boundary_arg) * BITS_PER_UNIT; } /* Set the default value for -mstackrealign. */ - if (ix86_force_align_arg_pointer == -1) - ix86_force_align_arg_pointer = STACK_REALIGN_DEFAULT; + if (opts->x_ix86_force_align_arg_pointer == -1) + opts->x_ix86_force_align_arg_pointer = STACK_REALIGN_DEFAULT; ix86_default_incoming_stack_boundary = PREFERRED_STACK_BOUNDARY; /* Validate -mincoming-stack-boundary= value or default it to MIN_STACK_BOUNDARY/PREFERRED_STACK_BOUNDARY. */ ix86_incoming_stack_boundary = ix86_default_incoming_stack_boundary; - if (global_options_set.x_ix86_incoming_stack_boundary_arg) + if (opts_set->x_ix86_incoming_stack_boundary_arg) { if (ix86_incoming_stack_boundary_arg < (TARGET_64BIT ? 4 : 2) || ix86_incoming_stack_boundary_arg > 12) @@ -3856,32 +3867,32 @@ static void && ! TARGET_SSE) error ("%ssseregparm%s used without SSE enabled", prefix, suffix); - if (global_options_set.x_ix86_fpmath) + if (opts_set->x_ix86_fpmath) { - if (ix86_fpmath & FPMATH_SSE) + if (opts->x_ix86_fpmath & FPMATH_SSE) { if (!TARGET_SSE) { warning (0, "SSE instruction set disabled, using 387 arithmetics"); - ix86_fpmath = FPMATH_387; + opts->x_ix86_fpmath = FPMATH_387; } - else if ((ix86_fpmath & FPMATH_387) && !TARGET_80387) + else if ((opts->x_ix86_fpmath & FPMATH_387) && !TARGET_80387) { warning (0, "387 instruction set disabled, using SSE arithmetics"); - ix86_fpmath = FPMATH_SSE; + opts->x_ix86_fpmath = FPMATH_SSE; } } } else - ix86_fpmath = TARGET_FPMATH_DEFAULT; + opts->x_ix86_fpmath = TARGET_FPMATH_DEFAULT; /* If the i387 is disabled, then do not return values in it. */ if (!TARGET_80387) target_flags &= ~MASK_FLOAT_RETURNS; /* Use external vectorized library in vectorizing intrinsics. */ - if (global_options_set.x_ix86_veclibabi_type) - switch (ix86_veclibabi_type) + if (opts_set->x_ix86_veclibabi_type) + switch (opts->x_ix86_veclibabi_type) { case ix86_veclibabi_type_svml: ix86_veclib_handler = ix86_veclibabi_svml; @@ -3946,20 +3957,20 @@ static void maybe_set_param_value (PARAM_SIMULTANEOUS_PREFETCHES, ix86_tune_cost->simultaneous_prefetches, - global_options.x_param_values, - global_options_set.x_param_values); + opts->x_param_values, + opts_set->x_param_values); maybe_set_param_value (PARAM_L1_CACHE_LINE_SIZE, ix86_tune_cost->prefetch_block, - global_options.x_param_values, - global_options_set.x_param_values); + opts->x_param_values, + opts_set->x_param_values); maybe_set_param_value (PARAM_L1_CACHE_SIZE, ix86_tune_cost->l1_cache_size, - global_options.x_param_values, - global_options_set.x_param_values); + opts->x_param_values, + opts_set->x_param_values); maybe_set_param_value (PARAM_L2_CACHE_SIZE, ix86_tune_cost->l2_cache_size, - global_options.x_param_values, - global_options_set.x_param_values); + opts->x_param_values, + opts_set->x_param_values); /* Enable sw prefetching at -O3 for CPUS that prefetching is helpful. */ if (flag_prefetch_loop_arrays < 0 @@ -4066,9 +4077,9 @@ static void target_flags |= MASK_PREFER_AVX128; } - if (ix86_recip_name) + if (opts->x_ix86_recip_name) { - char *p = ASTRDUP (ix86_recip_name); + char *p = ASTRDUP (opts->x_ix86_recip_name); char *q; unsigned int mask, i; bool invert; @@ -4125,23 +4136,24 @@ static void options. */ if (main_args_p) target_option_default_node = target_option_current_node - = build_target_option_node (); + = build_target_option_node (opts); /* Handle stack protector */ - if (!global_options_set.x_ix86_stack_protector_guard) - ix86_stack_protector_guard = TARGET_HAS_BIONIC ? SSP_GLOBAL : SSP_TLS; + if (!opts_set->x_ix86_stack_protector_guard) + opts->x_ix86_stack_protector_guard + = TARGET_HAS_BIONIC ? SSP_GLOBAL : SSP_TLS; /* Handle -mmemcpy-strategy= and -mmemset-strategy= */ - if (ix86_tune_memcpy_strategy) + if (opts->x_ix86_tune_memcpy_strategy) { - char *str = xstrdup (ix86_tune_memcpy_strategy); + char *str = xstrdup (opts->x_ix86_tune_memcpy_strategy); ix86_parse_stringop_strategy_string (str, false); free (str); } - if (ix86_tune_memset_strategy) + if (opts->x_ix86_tune_memset_strategy) { - char *str = xstrdup (ix86_tune_memset_strategy); + char *str = xstrdup (opts->x_ix86_tune_memset_strategy); ix86_parse_stringop_strategy_string (str, true); free (str); } @@ -4158,7 +4170,7 @@ ix86_option_override (void) 1, PASS_POS_INSERT_AFTER }; - ix86_option_override_internal (true); + ix86_option_override_internal (true, &global_options, &global_options_set); /* This needs to be done at start up. It's convenient to do it here. */ @@ -4337,6 +4349,8 @@ ix86_function_specific_print (FILE *file, int inde static bool ix86_valid_target_attribute_inner_p (tree args, char *p_strings[], + struct gcc_options *opts, + struct gcc_options *opts_set, struct gcc_options *enum_opts_set) { char *next_optstr; @@ -4453,7 +4467,8 @@ ix86_valid_target_attribute_inner_p (tree args, ch for (; args; args = TREE_CHAIN (args)) if (TREE_VALUE (args) && !ix86_valid_target_attribute_inner_p (TREE_VALUE (args), - p_strings, enum_opts_set)) + p_strings, opts, opts_set, + enum_opts_set)) ret = false; return ret; @@ -4536,7 +4551,7 @@ ix86_valid_target_attribute_inner_p (tree args, ch struct cl_decoded_option decoded; generate_option (opt, NULL, opt_set_p, CL_TARGET, &decoded); - ix86_handle_option (&global_options, &global_options_set, + ix86_handle_option (opts, opts_set, &decoded, input_location); } @@ -4569,7 +4584,7 @@ ix86_valid_target_attribute_inner_p (tree args, ch arg_ok = opt_enum_arg_to_value (opt, p + opt_len, &value, CL_TARGET); if (arg_ok) - set_option (&global_options, enum_opts_set, opt, value, + set_option (opts, enum_opts_set, opt, value, p + opt_len, DK_UNSPECIFIED, input_location, global_dc); else @@ -4587,13 +4602,14 @@ ix86_valid_target_attribute_inner_p (tree args, ch } /* Return a TARGET_OPTION_NODE tree of the target options listed or NULL. */ - tree -ix86_valid_target_attribute_tree (tree args) +ix86_valid_target_attribute_tree (tree args, + struct gcc_options *opts, + struct gcc_options *opts_set) { const char *orig_arch_string = ix86_arch_string; const char *orig_tune_string = ix86_tune_string; - enum fpmath_unit orig_fpmath_set = global_options_set.x_ix86_fpmath; + enum fpmath_unit orig_fpmath_set = opts_set->x_ix86_fpmath; int orig_tune_defaulted = ix86_tune_defaulted; int orig_arch_specified = ix86_arch_specified; char *option_strings[IX86_FUNCTION_SPECIFIC_MAX] = { NULL, NULL }; @@ -4606,16 +4622,16 @@ tree memset (&enum_opts_set, 0, sizeof (enum_opts_set)); /* Process each of the options on the chain. */ - if (! ix86_valid_target_attribute_inner_p (args, option_strings, - &enum_opts_set)) + if (! ix86_valid_target_attribute_inner_p (args, option_strings, opts, + opts_set, &enum_opts_set)) return error_mark_node; /* If the changed options are different from the default, rerun ix86_option_override_internal, and then save the options away. The string options are are attribute options, and will be undone when we copy the save structure. */ - if (ix86_isa_flags != def->x_ix86_isa_flags - || target_flags != def->x_target_flags + if (opts->x_ix86_isa_flags != def->x_ix86_isa_flags + || opts->x_target_flags != def->x_target_flags || option_strings[IX86_FUNCTION_SPECIFIC_ARCH] || option_strings[IX86_FUNCTION_SPECIFIC_TUNE] || enum_opts_set.x_ix86_fpmath) @@ -4623,37 +4639,37 @@ tree /* If we are using the default tune= or arch=, undo the string assigned, and use the default. */ if (option_strings[IX86_FUNCTION_SPECIFIC_ARCH]) - ix86_arch_string = option_strings[IX86_FUNCTION_SPECIFIC_ARCH]; + opts->x_ix86_arch_string = option_strings[IX86_FUNCTION_SPECIFIC_ARCH]; else if (!orig_arch_specified) - ix86_arch_string = NULL; + opts->x_ix86_arch_string = NULL; if (option_strings[IX86_FUNCTION_SPECIFIC_TUNE]) - ix86_tune_string = option_strings[IX86_FUNCTION_SPECIFIC_TUNE]; + opts->x_ix86_tune_string = option_strings[IX86_FUNCTION_SPECIFIC_TUNE]; else if (orig_tune_defaulted) - ix86_tune_string = NULL; + opts->x_ix86_tune_string = NULL; /* If fpmath= is not set, and we now have sse2 on 32-bit, use it. */ if (enum_opts_set.x_ix86_fpmath) - global_options_set.x_ix86_fpmath = (enum fpmath_unit) 1; + opts_set->x_ix86_fpmath = (enum fpmath_unit) 1; else if (!TARGET_64BIT && TARGET_SSE) { - ix86_fpmath = (enum fpmath_unit) (FPMATH_SSE | FPMATH_387); - global_options_set.x_ix86_fpmath = (enum fpmath_unit) 1; + opts->x_ix86_fpmath = (enum fpmath_unit) (FPMATH_SSE | FPMATH_387); + opts_set->x_ix86_fpmath = (enum fpmath_unit) 1; } /* Do any overrides, such as arch=xxx, or tune=xxx support. */ - ix86_option_override_internal (false); + ix86_option_override_internal (false, opts, opts_set); /* Add any builtin functions with the new isa if any. */ - ix86_add_new_builtins (ix86_isa_flags); + ix86_add_new_builtins (opts->x_ix86_isa_flags); /* Save the current options unless we are validating options for #pragma. */ - t = build_target_option_node (); + t = build_target_option_node (opts); - ix86_arch_string = orig_arch_string; - ix86_tune_string = orig_tune_string; - global_options_set.x_ix86_fpmath = orig_fpmath_set; + opts->x_ix86_arch_string = orig_arch_string; + opts->x_ix86_tune_string = orig_tune_string; + opts_set->x_ix86_fpmath = orig_fpmath_set; /* Free up memory allocated to hold the strings */ for (i = 0; i < IX86_FUNCTION_SPECIFIC_MAX; i++) @@ -4671,7 +4687,8 @@ ix86_valid_target_attribute_p (tree fndecl, tree args, int ARG_UNUSED (flags)) { - struct cl_target_option cur_target; + struct gcc_options func_options; + tree new_target, new_optimize; bool ret = true; /* attribute((target("default"))) does nothing, beyond @@ -4682,22 +4699,29 @@ ix86_valid_target_attribute_p (tree fndecl, && strcmp (TREE_STRING_POINTER (TREE_VALUE (args)), "default") == 0) return true; - tree old_optimize = build_optimization_node (); - tree new_target, new_optimize; + tree old_optimize = build_optimization_node (&global_options); + + /* Get the optimization options of the current function. */ tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl); + + if (!func_optimize) + func_optimize = old_optimize; - /* If the function changed the optimization levels as well as setting target - options, start with the optimizations specified. */ - if (func_optimize && func_optimize != old_optimize) - cl_optimization_restore (&global_options, - TREE_OPTIMIZATION (func_optimize)); + memset (&func_options, 0, sizeof (func_options)); + + cl_optimization_restore (&func_options, + TREE_OPTIMIZATION (func_optimize)); - /* The target attributes may also change some optimization flags, so update - the optimization options if necessary. */ - cl_target_option_save (&cur_target, &global_options); - new_target = ix86_valid_target_attribute_tree (args); - new_optimize = build_optimization_node (); + /* Initialize func_options to the default before its target options can + be set. */ + cl_target_option_restore (&func_options, + TREE_TARGET_OPTION (target_option_default_node)); + new_target = ix86_valid_target_attribute_tree (args, &func_options, + &global_options_set); + + new_optimize = build_optimization_node (&func_options); + if (new_target == error_mark_node) ret = false; @@ -4709,12 +4733,6 @@ ix86_valid_target_attribute_p (tree fndecl, DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize; } - cl_target_option_restore (&global_options, &cur_target); - - if (old_optimize != new_optimize) - cl_optimization_restore (&global_options, - TREE_OPTIMIZATION (old_optimize)); - return ret; } @@ -29327,7 +29345,8 @@ get_builtin_code_for_version (tree decl, tree *pre if (strstr (attrs_str, "arch=") != NULL) { cl_target_option_save (&cur_target, &global_options); - target_node = ix86_valid_target_attribute_tree (attrs); + target_node = ix86_valid_target_attribute_tree (attrs, &global_options, + &global_options_set); gcc_assert (target_node); new_target = TREE_TARGET_OPTION (target_node); Index: config/i386/i386-c.c =================================================================== --- config/i386/i386-c.c (revision 202662) +++ config/i386/i386-c.c (working copy) @@ -370,7 +370,7 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_fla static bool ix86_pragma_target_parse (tree args, tree pop_target) { - tree prev_tree = build_target_option_node (); + tree prev_tree = build_target_option_node (&global_options); tree cur_tree; struct cl_target_option *prev_opt; struct cl_target_option *cur_opt; @@ -390,7 +390,8 @@ ix86_pragma_target_parse (tree args, tree pop_targ } else { - cur_tree = ix86_valid_target_attribute_tree (args); + cur_tree = ix86_valid_target_attribute_tree (args, &global_options, + &global_options_set); if (!cur_tree || cur_tree == error_mark_node) { cl_target_option_restore (&global_options, Index: config/i386/i386-protos.h =================================================================== --- config/i386/i386-protos.h (revision 202662) +++ config/i386/i386-protos.h (working copy) @@ -220,7 +220,9 @@ extern int ix86_constant_alignment (tree, int); extern tree ix86_handle_shared_attribute (tree *, tree, tree, int, bool *); extern tree ix86_handle_selectany_attribute (tree *, tree, tree, int, bool *); extern int x86_field_alignment (tree, int); -extern tree ix86_valid_target_attribute_tree (tree); +extern tree ix86_valid_target_attribute_tree (tree, + struct gcc_options *, + struct gcc_options *); extern unsigned int ix86_get_callcvt (const_tree); #endif Index: config/rs6000/rs6000.c =================================================================== --- config/rs6000/rs6000.c (revision 202662) +++ config/rs6000/rs6000.c (working copy) @@ -3664,7 +3664,7 @@ rs6000_option_override_internal (bool global_init_ /* Save the initial options in case the user does function specific options */ if (global_init_p) target_option_default_node = target_option_current_node - = build_target_option_node (); + = build_target_option_node (&global_options); /* If not explicitly specified via option, decide whether to generate the extra blr's required to preserve the link stack on some cpus (eg, 476). */ @@ -29434,7 +29434,7 @@ rs6000_valid_attribute_p (tree fndecl, { struct cl_target_option cur_target; bool ret; - tree old_optimize = build_optimization_node (); + tree old_optimize = build_optimization_node (&global_options); tree new_target, new_optimize; tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl); @@ -29461,7 +29461,7 @@ rs6000_valid_attribute_p (tree fndecl, fprintf (stderr, "--------------------\n"); } - old_optimize = build_optimization_node (); + old_optimize = build_optimization_node (&global_options); func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl); /* If the function changed the optimization levels as well as setting target @@ -29480,12 +29480,12 @@ rs6000_valid_attribute_p (tree fndecl, if (ret) { ret = rs6000_option_override_internal (false); - new_target = build_target_option_node (); + new_target = build_target_option_node (&global_options); } else new_target = NULL; - new_optimize = build_optimization_node (); + new_optimize = build_optimization_node (&global_options); if (!new_target) ret = false; @@ -29515,7 +29515,7 @@ rs6000_valid_attribute_p (tree fndecl, bool rs6000_pragma_target_parse (tree args, tree pop_target) { - tree prev_tree = build_target_option_node (); + tree prev_tree = build_target_option_node (&global_options); tree cur_tree; struct cl_target_option *prev_opt, *cur_opt; HOST_WIDE_INT prev_flags, cur_flags, diff_flags; @@ -29552,7 +29552,8 @@ rs6000_pragma_target_parse (tree args, tree pop_ta rs6000_cpu_index = rs6000_tune_index = -1; if (!rs6000_inner_target_options (args, false) || !rs6000_option_override_internal (false) - || (cur_tree = build_target_option_node ()) == NULL_TREE) + || (cur_tree = build_target_option_node (&global_options)) + == NULL_TREE) { if (TARGET_DEBUG_BUILTIN || TARGET_DEBUG_TARGET) fprintf (stderr, "invalid pragma\n"); Index: testsuite/gcc.target/i386/pr57756.c =================================================================== --- testsuite/gcc.target/i386/pr57756.c (revision 0) +++ testsuite/gcc.target/i386/pr57756.c (revision 0) @@ -0,0 +1,20 @@ +/* callee cannot be inlined into caller because it has a higher + target ISA. */ +/* { dg-do compile } */ + +__attribute__((always_inline,target("sse4.2"))) +__inline int callee () /* { dg-error "inlining failed in call to always_inline" } */ +{ + return 0; +} + +__attribute__((target("sse"))) +__inline int caller () +{ + return callee(); /* { dg-error "called from here" } */ +} + +int main () +{ + return caller(); +} Index: toplev.c =================================================================== --- toplev.c (revision 202662) +++ toplev.c (working copy) @@ -1573,7 +1573,7 @@ process_options (void) DK_ERROR, UNKNOWN_LOCATION); /* Save the current optimization options. */ - optimization_default_node = build_optimization_node (); + optimization_default_node = build_optimization_node (&global_options); optimization_current_node = optimization_default_node; } Index: tree.c =================================================================== --- tree.c (revision 202662) +++ tree.c (working copy) @@ -11486,10 +11486,10 @@ cl_option_hash_eq (const void *x, const void *y) return (memcmp (xp, yp, len) == 0); } -/* Build an OPTIMIZATION_NODE based on the current options. */ +/* Build an OPTIMIZATION_NODE based on the options in OPTS. */ tree -build_optimization_node (void) +build_optimization_node (struct gcc_options *opts) { tree t; void **slot; @@ -11497,7 +11497,7 @@ tree /* Use the cache of optimization nodes. */ cl_optimization_save (TREE_OPTIMIZATION (cl_optimization_node), - &global_options); + opts); slot = htab_find_slot (cl_option_hash_table, cl_optimization_node, INSERT); t = (tree) *slot; @@ -11514,10 +11514,10 @@ tree return t; } -/* Build a TARGET_OPTION_NODE based on the current options. */ +/* Build a TARGET_OPTION_NODE based on the options in OPTS. */ tree -build_target_option_node (void) +build_target_option_node (struct gcc_options *opts) { tree t; void **slot; @@ -11525,7 +11525,7 @@ tree /* Use the cache of optimization nodes. */ cl_target_option_save (TREE_TARGET_OPTION (cl_target_option_node), - &global_options); + opts); slot = htab_find_slot (cl_option_hash_table, cl_target_option_node, INSERT); t = (tree) *slot; Index: tree.h =================================================================== --- tree.h (revision 202662) +++ tree.h (working copy) @@ -2584,16 +2584,16 @@ extern vec **decl_debug_args_insert ( #define TREE_OPTIMIZATION_BASE_OPTABS(NODE) \ (OPTIMIZATION_NODE_CHECK (NODE)->optimization.base_optabs) -/* Return a tree node that encapsulates the current optimization options. */ -extern tree build_optimization_node (void); +/* Return a tree node that encapsulates the optimization options in OPTS. */ +extern tree build_optimization_node (struct gcc_options *opts); extern void init_tree_optimization_optabs (tree); #define TREE_TARGET_OPTION(NODE) \ (&TARGET_OPTION_NODE_CHECK (NODE)->target_option.opts) -/* Return a tree node that encapsulates the current target options. */ -extern tree build_target_option_node (void); +/* Return a tree node that encapsulates the target options in OPTS. */ +extern tree build_target_option_node (struct gcc_options *opts); #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)