https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103515
--- Comment #2 from Kewen Lin <linkw at gcc dot gnu.org> --- Here I assumed that the current cl optimization/option save and restore scheme wants to keep the global_option/global_option_set same as the one from the initial option processing. After we parsing all attributes/pragmas, we can expect the rs6000_isa_flags back to the default one. The fix seems to require us to take this OPTION_MASK_SAVE_TOC_INDIRECT as one option which would be affected by optimize level. diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 327822e5357..f9ee7044889 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -3478,6 +3478,16 @@ rs6000_override_options_after_change (void) } else if (!OPTION_SET_P (flag_cunroll_grow_size)) flag_cunroll_grow_size = flag_peel_loops || optimize >= 3; + /* If we can shrink-wrap the TOC register save separately, then use + -msave-toc-indirect unless explicitly disabled. */ + if ((rs6000_isa_flags_explicit & OPTION_MASK_SAVE_TOC_INDIRECT) == 0 + && flag_shrink_wrap_separate + && optimize_function_for_speed_p (cfun)) + rs6000_isa_flags |= OPTION_MASK_SAVE_TOC_INDIRECT; + else + rs6000_isa_flags &= ~OPTION_MASK_SAVE_TOC_INDIRECT; Also require us to build one target_node when we are going to save one new optimization_node which isn't the same as the default one, since at that time the optimization level changes and the option is possible to be changed as well. diff --git a/gcc/attribs.c b/gcc/attribs.c index c252f5af07b..3382c095fa8 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -607,7 +607,14 @@ decl_attributes (tree *node, tree attributes, int flags, if (TREE_CODE (*node) == FUNCTION_DECL && optimization_current_node != optimization_default_node && !DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)) - DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node) = optimization_current_node; + { + DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node) = optimization_current_node; + tree target_node + = build_target_option_node (&global_options, &global_options_set); + if (!DECL_FUNCTION_SPECIFIC_TARGET (*node) + && target_node != target_option_default_node) + DECL_FUNCTION_SPECIFIC_TARGET (*node) = target_node; + } /* If this is a function and the user used #pragma GCC target, add the options to the attribute((target(...))) list. */