public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Christophe Lyon <christophe.lyon@linaro.org>
To: Richard Biener <rguenther@suse.de>
Cc: Jakub Jelinek <jakub@redhat.com>,
	gcc Patches <gcc-patches@gcc.gnu.org>,
	 Richard Earnshaw <Richard.Earnshaw@foss.arm.com>,
	"Joseph S. Myers" <joseph@codesourcery.com>
Subject: Re: [PATCH] options: Save and restore opts_set for Optimization and Target options
Date: Mon, 14 Sep 2020 10:06:14 +0200	[thread overview]
Message-ID: <CAKdteObZs=t1FLs4A3tR7FEq7XQ6vZJQHfswyEBzVoDvjy6h6Q@mail.gmail.com> (raw)
In-Reply-To: <nycvar.YFH.7.76.2009140832480.9963@zhemvz.fhfr.qr>

On Mon, 14 Sep 2020 at 08:33, Richard Biener <rguenther@suse.de> wrote:
>
> On Sun, 13 Sep 2020, Jakub Jelinek wrote:
>
> > On Fri, Sep 11, 2020 at 11:29:52AM +0200, Jakub Jelinek via Gcc-patches wrote:
> > > On Fri, Sep 11, 2020 at 09:46:37AM +0200, Christophe Lyon via Gcc-patches wrote:
> > > > I'm seeing an ICE with this new test on most of my arm configurations,
> > > > for instance:
> > > > --target arm-none-linux-gnueabi --with-cpu cortex-a9
> > > > /aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-arm-none-linux-gnueabi/gcc3/gcc/xgcc
> > > > -B/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-ar
> > > > m-none-linux-gnueabi/gcc3/gcc/ c_lto_pr96939_0.o c_lto_pr96939_1.o
> > > > -fdiagnostics-plain-output -flto -O2 -o
> > > > gcc-target-arm-lto-pr96939-01.exe
> > >
> > > Seems a latent issue.
> > > Neither cl_optimization_{save,restore} nor cl_target_option_{save,restore}
> > > (nor any of the target hooks they call) saves or restores any opts_set
> > > values, so I think opts_set can be trusted only during option processing (if
> > > at all), but not later.
> > > So, short term a fix would be IMHO just stop using opts_set altogether in
> > > arm_configure_build_target, it doesn't make much sense to me, it should test
> > > if those strings are non-NULL instead, or at least do that when it is
> > > invoked from arm_option_restore (e.g. could be done by calling it with
> > > opts instead of &global_options_set ).
> > > Longer term, the question is if cl_optimization_{save,restore} and
> > > cl_target_option_{save,restore} shouldn't be changed not to only
> > > save/restore the options, but also save the opts_set flags.
> > > It could be done e.g. by adding a bool array or set of bool members
> > > to struct cl_optimization and struct cl_target_option , or even more compact
> > > by using bitmasks, pack each 64 adjacent option flags into a UHWI element
> > > of an array.
> >
> > So, I've tried under debugger how it behaves and seems global_options_set
> > is really an or of whether an option has been ever seen as explicit, either
> > on the command line or in any of the option pragmas or optimize/target
> > attributes seen so far, so it isn't something that can be relied on.
> >
> > The following patch implements the saving/restoring of the opts_set bits
> > (though only for the options/variables saved by the generic options-save.c
> > code, for the target specific stuff that isn't handled by the generic code
> > the opts_set argument is now passed to the hook and the backends can choose
> > e.g. to use a TargetSave variable to save the flags either individually or
> > together in some bitmask (or ignore it if they never need opts_set for the
> > options).
> >
> > Bootstrapped/regtested on x86_64-linux, i686-linux, armv7hl-linux-gnueabi,
> > aarch64-linux, powerpc64le-linux and lto bootstrapped on x86_64-linux, ok
> > for trunk?
>

Hi Jakub,

This patch is causing build failures in libgcc when targeting
arm-none-eabi with multilibs enabled:
I see an error with -marm -mfpu=auto -march=armv5te+fp -mfloat-abi=hard
when compiling /libgcc/config/arm/pr-support.c:
/tmp/5619380_8.tmpdir/ccxsqYqf.s: Assembler messages:
/tmp/5619380_8.tmpdir/ccxsqYqf.s:290: Error: selected processor does
not support `uxtb r3,r3' in ARM mode
/tmp/5619380_8.tmpdir/ccxsqYqf.s:387: Error: selected processor does
not support `uxth r2,r4' in ARM mode

and similar with /libgcc/config/arm/unwind-arm.c:
/tmp/5619380_8.tmpdir/ccB9Efuf.s: Assembler messages:
/tmp/5619380_8.tmpdir/ccB9Efuf.s:396: Error: selected processor does
not support `ubfx r0,r3,#24,#4' in ARM mode
/tmp/5619380_8.tmpdir/ccB9Efuf.s:852: Error: selected processor does
not support `uxtb r10,r9' in ARM mode
/tmp/5619380_8.tmpdir/ccB9Efuf.s:1776: Error: selected processor does
not support `uxtb r2,r2' in ARM mode
/tmp/5619380_8.tmpdir/ccB9Efuf.s:2658: Error: selected processor does
not support `uxth r4,r2' in ARM mode
/tmp/5619380_8.tmpdir/ccB9Efuf.s:2751: Error: selected processor does
not support `uxth r5,r2' in ARM mode
/tmp/5619380_8.tmpdir/ccB9Efuf.s:2914: Error: selected processor does
not support `uxth ip,r2' in ARM mode

Looks like you opened a can of worms :-)



> OK.
>
> Richard.
>
> > This patch itself doesn't fix the testcase failing on arm, but a follow up
> > patch will.
> >
> > 2020-09-13  Jakub Jelinek  <jakub@redhat.com>
> >
> > gcc/
> >       * opt-read.awk: Also initialize extra_target_var_types array.
> >       * opth-gen.awk: Emit explicit_mask arrays to struct cl_optimization
> >       and cl_target_option.  Adjust cl_optimization_save,
> >       cl_optimization_restore, cl_target_option_save and
> >       cl_target_option_restore declarations.
> >       * optc-save-gen.awk: Add opts_set argument to cl_optimization_save,
> >       cl_optimization_restore, cl_target_option_save and
> >       cl_target_option_restore functions and save or restore opts_set
> >       next to the opts values into or from explicit_mask arrays.
> >       In cl_target_option_eq and cl_optimization_option_eq compare
> >       explicit_mask arrays, in cl_target_option_hash and cl_optimization_hash
> >       hash them and in cl_target_option_stream_out,
> >       cl_target_option_stream_in, cl_optimization_stream_out and
> >       cl_optimization_stream_in stream them.
> >       * tree.h (build_optimization_node, build_target_option_node): Add
> >       opts_set argument.
> >       * tree.c (build_optimization_node): Add opts_set argument, pass it
> >       to cl_optimization_save.
> >       (build_target_option_node): Add opts_set argument, pass it to
> >       cl_target_option_save.
> >       * function.c (invoke_set_current_function_hook): Adjust
> >       cl_optimization_restore caller.
> >       * ipa-inline-transform.c (inline_call): Adjust cl_optimization_restore
> >       and build_optimization_node callers.
> >       * target.def (TARGET_OPTION_SAVE, TARGET_OPTION_RESTORE): Add opts_set
> >       argument.
> >       * target-globals.c (save_target_globals_default_opts): Adjust
> >       cl_optimization_restore callers.
> >       * toplev.c (process_options): Adjust build_optimization_node and
> >       cl_optimization_restore callers.
> >       (target_reinit): Adjust cl_optimization_restore caller.
> >       * tree-streamer-in.c (lto_input_ts_function_decl_tree_pointers):
> >       Adjust build_optimization_node and cl_optimization_restore callers.
> >       * doc/tm.texi: Updated.
> >       * config/aarch64/aarch64.c (aarch64_override_options): Adjust
> >       build_target_option_node caller.
> >       (aarch64_option_save, aarch64_option_restore): Add opts_set argument.
> >       (aarch64_set_current_function): Adjust cl_target_option_restore
> >       caller.
> >       (aarch64_option_valid_attribute_p): Adjust cl_target_option_save,
> >       cl_target_option_restore, cl_optimization_restore,
> >       build_optimization_node and build_target_option_node callers.
> >       * config/aarch64/aarch64-c.c (aarch64_pragma_target_parse): Adjust
> >       cl_target_option_restore and build_target_option_node callers.
> >       * config/arm/arm.c (arm_option_save, arm_option_restore): Add
> >       opts_set argument.
> >       (arm_option_override): Adjust cl_target_option_save,
> >       build_optimization_node and build_target_option_node callers.
> >       (arm_set_current_function): Adjust cl_target_option_restore caller.
> >       (arm_valid_target_attribute_tree): Adjust build_target_option_node
> >       caller.
> >       (add_attribute): Formatting fix.
> >       (arm_valid_target_attribute_p): Adjust cl_optimization_restore,
> >       cl_target_option_restore, arm_valid_target_attribute_tree and
> >       build_optimization_node callers.
> >       * config/arm/arm-c.c (arm_pragma_target_parse): Adjust
> >       cl_target_option_restore callers.
> >       * config/csky/csky.c (csky_option_override): Adjust
> >       build_target_option_node and cl_target_option_save callers.
> >       * config/gcn/gcn.c (gcn_fixup_accel_lto_options): Adjust
> >       build_optimization_node and cl_optimization_restore callers.
> >       * config/i386/i386-builtins.c (get_builtin_code_for_version):
> >       Adjust cl_target_option_save and cl_target_option_restore
> >       callers.
> >       * config/i386/i386-c.c (ix86_pragma_target_parse): Adjust
> >       build_target_option_node and cl_target_option_restore callers.
> >       * config/i386/i386-options.c (ix86_function_specific_save,
> >       ix86_function_specific_restore): Add opts_set arguments.
> >       (ix86_valid_target_attribute_tree): Adjust build_target_option_node
> >       caller.
> >       (ix86_valid_target_attribute_p): Adjust build_optimization_node,
> >       cl_optimization_restore, cl_target_option_restore,
> >       ix86_valid_target_attribute_tree and build_optimization_node callers.
> >       (ix86_option_override_internal): Adjust build_target_option_node
> >       caller.
> >       (ix86_reset_previous_fndecl, ix86_set_current_function): Adjust
> >       cl_target_option_restore callers.
> >       * config/i386/i386-options.h (ix86_function_specific_save,
> >       ix86_function_specific_restore): Add opts_set argument.
> >       * config/nios2/nios2.c (nios2_option_override): Adjust
> >       build_target_option_node caller.
> >       (nios2_option_save, nios2_option_restore): Add opts_set argument.
> >       (nios2_valid_target_attribute_tree): Adjust build_target_option_node
> >       caller.
> >       (nios2_valid_target_attribute_p): Adjust build_optimization_node,
> >       cl_optimization_restore, cl_target_option_save and
> >       cl_target_option_restore callers.
> >       (nios2_set_current_function, nios2_pragma_target_parse): Adjust
> >       cl_target_option_restore callers.
> >       * config/pru/pru.c (pru_option_override): Adjust
> >       build_target_option_node caller.
> >       (pru_set_current_function): Adjust cl_target_option_restore
> >       callers.
> >       * config/rs6000/rs6000.c (rs6000_debug_reg_global): Adjust
> >       cl_target_option_save caller.
> >       (rs6000_option_override_internal): Adjust build_target_option_node
> >       caller.
> >       (rs6000_valid_attribute_p): Adjust build_optimization_node,
> >       cl_optimization_restore, cl_target_option_save,
> >       cl_target_option_restore and build_target_option_node callers.
> >       (rs6000_pragma_target_parse): Adjust cl_target_option_restore and
> >       build_target_option_node callers.
> >       (rs6000_activate_target_options): Adjust cl_target_option_restore
> >       callers.
> >       (rs6000_function_specific_save, rs6000_function_specific_restore):
> >       Add opts_set argument.
> >       * config/s390/s390.c (s390_function_specific_restore): Likewise.
> >       (s390_option_override_internal): Adjust s390_function_specific_restore
> >       caller.
> >       (s390_option_override, s390_valid_target_attribute_tree): Adjust
> >       build_target_option_node caller.
> >       (s390_valid_target_attribute_p): Adjust build_optimization_node,
> >       cl_optimization_restore and cl_target_option_restore callers.
> >       (s390_activate_target_options): Adjust cl_target_option_restore
> >       caller.
> >       * config/s390/s390-c.c (s390_cpu_cpp_builtins): Adjust
> >       cl_target_option_save caller.
> >       (s390_pragma_target_parse): Adjust build_target_option_node and
> >       cl_target_option_restore callers.
> > gcc/c-family/
> >       * c-attribs.c (handle_optimize_attribute): Adjust
> >       cl_optimization_save, cl_optimization_restore and
> >       build_optimization_node callers.
> >       * c-pragma.c (handle_pragma_optimize): Adjust
> >       build_optimization_node caller.
> >       (handle_pragma_push_options): Adjust
> >       build_optimization_node and build_target_option_node callers.
> >       (handle_pragma_pop_options, handle_pragma_reset_options):
> >       Adjust cl_optimization_restore callers.
> > gcc/go/
> >       * go-gcc.cc (Gcc_backend::function): Adjust
> >       cl_optimization_save, cl_optimization_restore and
> >       build_optimization_node callers.
> > gcc/ada/
> >       * gcc-interface/trans.c (gigi): Adjust build_optimization_node
> >       caller.
> >
> > --- gcc/opt-read.awk.jj       2020-07-28 15:39:09.970756750 +0200
> > +++ gcc/opt-read.awk  2020-09-11 17:35:54.012530779 +0200
> > @@ -71,6 +71,7 @@ BEGIN {
> >                       n_target_save++
> >
> >                       extra_target_vars[n_extra_target_vars] = name
> > +                     extra_target_var_types[n_extra_target_vars] = type
> >                       n_extra_target_vars++
> >               }
> >               else if ($1 == "HeaderInclude") {
> > --- gcc/opth-gen.awk.jj       2020-07-28 15:39:09.971756736 +0200
> > +++ gcc/opth-gen.awk  2020-09-11 17:27:48.203628206 +0200
> > @@ -137,6 +137,7 @@ n_opt_short = 0;
> >  n_opt_int = 0;
> >  n_opt_enum = 0;
> >  n_opt_other = 0;
> > +n_opt_explicit = 4;
> >  var_opt_char[0] = "unsigned char x_optimize";
> >  var_opt_char[1] = "unsigned char x_optimize_size";
> >  var_opt_char[2] = "unsigned char x_optimize_debug";
> > @@ -152,6 +153,7 @@ for (i = 0; i < n_opts; i++) {
> >                       continue;
> >
> >               var_opt_seen[name]++;
> > +             n_opt_explicit++;
> >               otype = var_type_struct(flags[i]);
> >               if (otype ~ "^((un)?signed +)?int *$")
> >                       var_opt_int[n_opt_int++] = otype "x_" name;
> > @@ -190,6 +192,9 @@ for (i = 0; i < n_opt_char; i++) {
> >       print "  " var_opt_char[i] ";";
> >  }
> >
> > +print "  /* " n_opt_explicit " members */";
> > +print "  unsigned HOST_WIDE_INT explicit_mask[" int ((n_opt_explicit + 63) / 64) "];";
> > +
> >  print "};";
> >  print "";
> >
> > @@ -203,6 +208,7 @@ n_target_short = 0;
> >  n_target_int = 0;
> >  n_target_enum = 0;
> >  n_target_other = 0;
> > +n_target_explicit = n_extra_target_vars;
> >
> >  for (i = 0; i < n_target_save; i++) {
> >       if (target_save_decl[i] ~ "^((un)?signed +)?int +[_" alnum "]+$")
> > @@ -232,6 +238,7 @@ if (have_save) {
> >                               continue;
> >
> >                       var_save_seen[name]++;
> > +                     n_target_explicit++;
> >                       otype = var_type_struct(flags[i])
> >                       if (otype ~ "^((un)?signed +)?int *$")
> >                               var_target_int[n_target_int++] = otype "x_" name;
> > @@ -251,6 +258,7 @@ if (have_save) {
> >       }
> >  } else {
> >       var_target_int[n_target_int++] = "int x_target_flags";
> > +     n_target_explicit++;
> >  }
> >
> >  for (i = 0; i < n_target_other; i++) {
> > @@ -273,14 +281,17 @@ for (i = 0; i < n_target_char; i++) {
> >       print "  " var_target_char[i] ";";
> >  }
> >
> > +print "  /* " n_target_explicit " members */";
> > +print "  unsigned HOST_WIDE_INT explicit_mask[" int ((n_target_explicit + 63) / 64) "];";
> > +
> >  print "};";
> >  print "";
> >  print "";
> >  print "/* Save optimization variables into a structure.  */"
> > -print "extern void cl_optimization_save (struct cl_optimization *, struct gcc_options *);";
> > +print "extern void cl_optimization_save (struct cl_optimization *, struct gcc_options *, struct gcc_options *);";
> >  print "";
> >  print "/* Restore optimization variables from a structure.  */";
> > -print "extern void cl_optimization_restore (struct gcc_options *, struct cl_optimization *);";
> > +print "extern void cl_optimization_restore (struct gcc_options *, struct gcc_options *, struct cl_optimization *);";
> >  print "";
> >  print "/* Print optimization variables from a structure.  */";
> >  print "extern void cl_optimization_print (FILE *, int, struct cl_optimization *);";
> > @@ -289,10 +300,10 @@ print "/* Print different optimization v
> >  print "extern void cl_optimization_print_diff (FILE *, int, cl_optimization *ptr1, cl_optimization *ptr2);";
> >  print "";
> >  print "/* Save selected option variables into a structure.  */"
> > -print "extern void cl_target_option_save (struct cl_target_option *, struct gcc_options *);";
> > +print "extern void cl_target_option_save (struct cl_target_option *, struct gcc_options *, struct gcc_options *);";
> >  print "";
> >  print "/* Restore selected option variables from a structure.  */"
> > -print "extern void cl_target_option_restore (struct gcc_options *, struct cl_target_option *);";
> > +print "extern void cl_target_option_restore (struct gcc_options *, struct gcc_options *, struct cl_target_option *);";
> >  print "";
> >  print "/* Print target option variables from a structure.  */";
> >  print "extern void cl_target_option_print (FILE *, int, struct cl_target_option *);";
> > --- gcc/optc-save-gen.awk.jj  2020-07-28 15:39:09.971756736 +0200
> > +++ gcc/optc-save-gen.awk     2020-09-11 17:38:31.524230167 +0200
> > @@ -78,7 +78,8 @@ for (i = 0; i < n_opts; i++) {
> >
> >  print "/* Save optimization variables into a structure.  */"
> >  print "void";
> > -print "cl_optimization_save (struct cl_optimization *ptr, struct gcc_options *opts)";
> > +print "cl_optimization_save (struct cl_optimization *ptr, struct gcc_options *opts,";
> > +print "                    struct gcc_options *opts_set)";
> >  print "{";
> >
> >  n_opt_char = 4;
> > @@ -116,9 +117,10 @@ for (i = 0; i < n_opts; i++) {
> >               else if (otype ~ "^((un)?signed +)?short *$")
> >                       var_opt_short[n_opt_short++] = name;
> >
> > -             else if (otype ~ ("^enum +[_" alnum "]+ *"))
> > +             else if (otype ~ ("^enum +[_" alnum "]+ *")) {
> > +                     var_opt_enum_type[n_opt_enum] = otype;
> >                       var_opt_enum[n_opt_enum++] = name;
> > -
> > +             }
> >               else if (otype ~ "^((un)?signed +)?char *$") {
> >                       var_opt_char[n_opt_char++] = name;
> >                       if (otype ~ "^unsigned +char *$")
> > @@ -166,12 +168,88 @@ for (i = 0; i < n_opt_string; i++) {
> >       print "  ptr->x_" var_opt_string[i] " = opts->x_" var_opt_string[i] ";";
> >  }
> >
> > +print "";
> > +print "  unsigned HOST_WIDE_INT mask = 0;";
> > +
> > +j = 0;
> > +k = 0;
> > +for (i = 0; i < n_opt_other; i++) {
> > +     print "  if (opts_set->x_" var_opt_other[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
> > +     j++;
> > +     if (j == 64) {
> > +             print "  ptr->explicit_mask[" k "] = mask;";
> > +             print "  mask = 0;";
> > +             j = 0;
> > +             k++;
> > +     }
> > +}
> > +
> > +for (i = 0; i < n_opt_int; i++) {
> > +     print "  if (opts_set->x_" var_opt_int[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
> > +     j++;
> > +     if (j == 64) {
> > +             print "  ptr->explicit_mask[" k "] = mask;";
> > +             print "  mask = 0;";
> > +             j = 0;
> > +             k++;
> > +     }
> > +}
> > +
> > +for (i = 0; i < n_opt_enum; i++) {
> > +     print "  if (opts_set->x_" var_opt_enum[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
> > +     j++;
> > +     if (j == 64) {
> > +             print "  ptr->explicit_mask[" k "] = mask;";
> > +             print "  mask = 0;";
> > +             j = 0;
> > +             k++;
> > +     }
> > +}
> > +
> > +for (i = 0; i < n_opt_short; i++) {
> > +     print "  if (opts_set->x_" var_opt_short[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
> > +     j++;
> > +     if (j == 64) {
> > +             print "  ptr->explicit_mask[" k "] = mask;";
> > +             print "  mask = 0;";
> > +             j = 0;
> > +             k++;
> > +     }
> > +}
> > +
> > +for (i = 0; i < n_opt_char; i++) {
> > +     print "  if (opts_set->x_" var_opt_char[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
> > +     j++;
> > +     if (j == 64) {
> > +             print "  ptr->explicit_mask[" k "] = mask;";
> > +             print "  mask = 0;";
> > +             j = 0;
> > +             k++;
> > +     }
> > +}
> > +
> > +for (i = 0; i < n_opt_string; i++) {
> > +     print "  if (opts_set->x_" var_opt_string[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
> > +     j++;
> > +     if (j == 64) {
> > +             print "  ptr->explicit_mask[" k "] = mask;";
> > +             print "  mask = 0;";
> > +             j = 0;
> > +             k++;
> > +     }
> > +}
> > +
> > +if (j != 0) {
> > +     print "  ptr->explicit_mask[" k "] = mask;";
> > +}
> > +
> >  print "}";
> >
> >  print "";
> >  print "/* Restore optimization options from a structure.  */";
> >  print "void";
> > -print "cl_optimization_restore (struct gcc_options *opts, struct cl_optimization *ptr)";
> > +print "cl_optimization_restore (struct gcc_options *opts, struct gcc_options *opts_set,";
> > +print "                       struct cl_optimization *ptr)";
> >  print "{";
> >
> >  for (i = 0; i < n_opt_other; i++) {
> > @@ -198,6 +276,77 @@ for (i = 0; i < n_opt_string; i++) {
> >       print "  opts->x_" var_opt_string[i] " = ptr->x_" var_opt_string[i] ";";
> >  }
> >
> > +print "";
> > +print "  unsigned HOST_WIDE_INT mask;";
> > +
> > +j = 64;
> > +k = 0;
> > +for (i = 0; i < n_opt_other; i++) {
> > +     if (j == 64) {
> > +             print "  mask = ptr->explicit_mask[" k "];";
> > +             k++;
> > +             j = 0;
> > +     }
> > +     print "  opts_set->x_" var_opt_other[i] " = (mask & 1) != 0;";
> > +     print "  mask >>= 1;"
> > +     j++;
> > +}
> > +
> > +for (i = 0; i < n_opt_int; i++) {
> > +     if (j == 64) {
> > +             print "  mask = ptr->explicit_mask[" k "];";
> > +             k++;
> > +             j = 0;
> > +     }
> > +     print "  opts_set->x_" var_opt_int[i] " = (mask & 1) != 0;";
> > +     print "  mask >>= 1;"
> > +     j++;
> > +}
> > +
> > +for (i = 0; i < n_opt_enum; i++) {
> > +     if (j == 64) {
> > +             print "  mask = ptr->explicit_mask[" k "];";
> > +             k++;
> > +             j = 0;
> > +     }
> > +     print "  opts_set->x_" var_opt_enum[i] " = static_cast<" var_opt_enum_type[i] ">((mask & 1) != 0);";
> > +     print "  mask >>= 1;"
> > +     j++;
> > +}
> > +
> > +for (i = 0; i < n_opt_short; i++) {
> > +     if (j == 64) {
> > +             print "  mask = ptr->explicit_mask[" k "];";
> > +             k++;
> > +             j = 0;
> > +     }
> > +     print "  opts_set->x_" var_opt_short[i] " = (mask & 1) != 0;";
> > +     print "  mask >>= 1;"
> > +     j++;
> > +}
> > +
> > +for (i = 0; i < n_opt_char; i++) {
> > +     if (j == 64) {
> > +             print "  mask = ptr->explicit_mask[" k "];";
> > +             k++;
> > +             j = 0;
> > +     }
> > +     print "  opts_set->x_" var_opt_char[i] " = (mask & 1) != 0;";
> > +     print "  mask >>= 1;"
> > +     j++;
> > +}
> > +
> > +for (i = 0; i < n_opt_string; i++) {
> > +     if (j == 64) {
> > +             print "  mask = ptr->explicit_mask[" k "];";
> > +             k++;
> > +             j = 0;
> > +     }
> > +     print "  opts_set->x_" var_opt_string[i] " = (mask & 1) ? \"\" : nullptr;";
> > +     print "  mask >>= 1;"
> > +     j++;
> > +}
> > +
> >  print "  targetm.override_options_after_change ();";
> >  print "}";
> >
> > @@ -344,7 +493,8 @@ print "}";
> >  print "";
> >  print "/* Save selected option variables into a structure.  */"
> >  print "void";
> > -print "cl_target_option_save (struct cl_target_option *ptr, struct gcc_options *opts)";
> > +print "cl_target_option_save (struct cl_target_option *ptr, struct gcc_options *opts,";
> > +print "                     struct gcc_options *opts_set)";
> >  print "{";
> >
> >  n_target_char = 0;
> > @@ -372,9 +522,10 @@ if (have_save) {
> >                       else if (otype ~ "^((un)?signed +)?short *$")
> >                               var_target_short[n_target_short++] = name;
> >
> > -                     else if (otype ~ ("^enum +[_" alnum "]+ *$"))
> > +                     else if (otype ~ ("^enum +[_" alnum "]+ *$")) {
> > +                             var_target_enum_type[n_target_enum] = otype;
> >                               var_target_enum[n_target_enum++] = name;
> > -
> > +                     }
> >                       else if (otype ~ "^((un)?signed +)?char *$") {
> >                               var_target_char[n_target_char++] = name;
> >                               if (otype ~ "^unsigned +char *$")
> > @@ -409,7 +560,7 @@ if (have_assert)
> >       print "";
> >
> >  print "  if (targetm.target_option.save)";
> > -print "    targetm.target_option.save (ptr, opts);";
> > +print "    targetm.target_option.save (ptr, opts, opts_set);";
> >  print "";
> >
> >  for (i = 0; i < n_extra_target_vars; i++) {
> > @@ -440,12 +591,99 @@ for (i = 0; i < n_target_string; i++) {
> >       print "  ptr->x_" var_target_string[i] " = opts->x_" var_target_string[i] ";";
> >  }
> >
> > +print "";
> > +print "  unsigned HOST_WIDE_INT mask = 0;";
> > +
> > +j = 0;
> > +k = 0;
> > +for (i = 0; i < n_extra_target_vars; i++) {
> > +     print "  if (opts_set->x_" extra_target_vars[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
> > +     j++;
> > +     if (j == 64) {
> > +             print "  ptr->explicit_mask[" k "] = mask;";
> > +             print "  mask = 0;";
> > +             j = 0;
> > +             k++;
> > +     }
> > +}
> > +
> > +for (i = 0; i < n_target_other; i++) {
> > +     print "  if (opts_set->x_" var_target_other[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
> > +     j++;
> > +     if (j == 64) {
> > +             print "  ptr->explicit_mask[" k "] = mask;";
> > +             print "  mask = 0;";
> > +             j = 0;
> > +             k++;
> > +     }
> > +}
> > +
> > +for (i = 0; i < n_target_enum; i++) {
> > +     print "  if (opts_set->x_" var_target_enum[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
> > +     j++;
> > +     if (j == 64) {
> > +             print "  ptr->explicit_mask[" k "] = mask;";
> > +             print "  mask = 0;";
> > +             j = 0;
> > +             k++;
> > +     }
> > +}
> > +
> > +for (i = 0; i < n_target_int; i++) {
> > +     print "  if (opts_set->x_" var_target_int[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
> > +     j++;
> > +     if (j == 64) {
> > +             print "  ptr->explicit_mask[" k "] = mask;";
> > +             print "  mask = 0;";
> > +             j = 0;
> > +             k++;
> > +     }
> > +}
> > +
> > +for (i = 0; i < n_target_short; i++) {
> > +     print "  if (opts_set->x_" var_target_short[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
> > +     j++;
> > +     if (j == 64) {
> > +             print "  ptr->explicit_mask[" k "] = mask;";
> > +             print "  mask = 0;";
> > +             j = 0;
> > +             k++;
> > +     }
> > +}
> > +
> > +for (i = 0; i < n_target_char; i++) {
> > +     print "  if (opts_set->x_" var_target_char[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
> > +     j++;
> > +     if (j == 64) {
> > +             print "  ptr->explicit_mask[" k "] = mask;";
> > +             print "  mask = 0;";
> > +             j = 0;
> > +             k++;
> > +     }
> > +}
> > +
> > +for (i = 0; i < n_target_string; i++) {
> > +     print "  if (opts_set->x_" var_target_string[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
> > +     j++;
> > +     if (j == 64) {
> > +             print "  ptr->explicit_mask[" k "] = mask;";
> > +             print "  mask = 0;";
> > +             j = 0;
> > +             k++;
> > +     }
> > +}
> > +
> > +if (j != 0) {
> > +     print "  ptr->explicit_mask[" k "] = mask;";
> > +}
> > +
> >  print "}";
> >
> >  print "";
> >  print "/* Restore selected current options from a structure.  */";
> >  print "void";
> > -print "cl_target_option_restore (struct gcc_options *opts, struct cl_target_option *ptr)";
> > +print "cl_target_option_restore (struct gcc_options *opts, struct gcc_options *opts_set,";
> > +print "                        struct cl_target_option *ptr)";
> >  print "{";
> >
> >  for (i = 0; i < n_extra_target_vars; i++) {
> > @@ -476,11 +714,101 @@ for (i = 0; i < n_target_string; i++) {
> >       print "  opts->x_" var_target_string[i] " = ptr->x_" var_target_string[i] ";";
> >  }
> >
> > +print "";
> > +print "  unsigned HOST_WIDE_INT mask;";
> > +
> > +j = 64;
> > +k = 0;
> > +for (i = 0; i < n_extra_target_vars; i++) {
> > +     if (j == 64) {
> > +             print "  mask = ptr->explicit_mask[" k "];";
> > +             k++;
> > +             j = 0;
> > +     }
> > +     if (extra_target_var_types[i] ~ ("^enum +[_" alnum "]+ *$")) {
> > +             print "  opts_set->x_" extra_target_vars[i] " = static_cast<" extra_target_var_types[i] ">((mask & 1) != 0);";
> > +     }
> > +     else if (extra_target_var_types[i] ~ "^const char \\**$") {
> > +             print "  opts_set->x_" extra_target_vars[i] " = (mask & 1) ? \"\" : nullptr;";
> > +     }
> > +     else {
> > +             print "  opts_set->x_" extra_target_vars[i] " = (mask & 1) != 0;";
> > +     }
> > +     print "  mask >>= 1;"
> > +     j++;
> > +}
> > +
> > +for (i = 0; i < n_target_other; i++) {
> > +     if (j == 64) {
> > +             print "  mask = ptr->explicit_mask[" k "];";
> > +             k++;
> > +             j = 0;
> > +     }
> > +     print "  opts_set->x_" var_target_other[i] " = (mask & 1) != 0;";
> > +     print "  mask >>= 1;"
> > +     j++;
> > +}
> > +
> > +for (i = 0; i < n_target_enum; i++) {
> > +     if (j == 64) {
> > +             print "  mask = ptr->explicit_mask[" k "];";
> > +             k++;
> > +             j = 0;
> > +     }
> > +     print "  opts_set->x_" var_target_enum[i] " = static_cast<" var_target_enum_type[i] ">((mask & 1) != 0);";
> > +     print "  mask >>= 1;"
> > +     j++;
> > +}
> > +
> > +for (i = 0; i < n_target_int; i++) {
> > +     if (j == 64) {
> > +             print "  mask = ptr->explicit_mask[" k "];";
> > +             k++;
> > +             j = 0;
> > +     }
> > +     print "  opts_set->x_" var_target_int[i] " = (mask & 1) != 0;";
> > +     print "  mask >>= 1;"
> > +     j++;
> > +}
> > +
> > +for (i = 0; i < n_target_short; i++) {
> > +     if (j == 64) {
> > +             print "  mask = ptr->explicit_mask[" k "];";
> > +             k++;
> > +             j = 0;
> > +     }
> > +     print "  opts_set->x_" var_target_short[i] " = (mask & 1) != 0;";
> > +     print "  mask >>= 1;"
> > +     j++;
> > +}
> > +
> > +for (i = 0; i < n_target_char; i++) {
> > +     if (j == 64) {
> > +             print "  mask = ptr->explicit_mask[" k "];";
> > +             k++;
> > +             j = 0;
> > +     }
> > +     print "  opts_set->x_" var_target_char[i] " = (mask & 1) != 0;";
> > +     print "  mask >>= 1;"
> > +     j++;
> > +}
> > +
> > +for (i = 0; i < n_target_string; i++) {
> > +     if (j == 64) {
> > +             print "  mask = ptr->explicit_mask[" k "];";
> > +             k++;
> > +             j = 0;
> > +     }
> > +     print "  opts_set->x_" var_target_string[i] " = (mask & 1) ? \"\" : nullptr;";
> > +     print "  mask >>= 1;"
> > +     j++;
> > +}
> > +
> >  # This must occur after the normal variables in case the code depends on those
> >  # variables.
> >  print "";
> >  print "  if (targetm.target_option.restore)";
> > -print "    targetm.target_option.restore (opts, ptr);";
> > +print "    targetm.target_option.restore (opts, opts_set, ptr);";
> >
> >  print "}";
> >
> > @@ -726,6 +1054,10 @@ for (i = 0; i < n_target_val; i++) {
> >       print "    return false;";
> >  }
> >
> > +print "  for (size_t i = 0; i < sizeof (ptr1->explicit_mask) / sizeof (ptr1->explicit_mask[0]); i++)";
> > +print "    if (ptr1->explicit_mask[i] != ptr2->explicit_mask[i])";
> > +print "      return false;"
> > +
> >  print "  return true;";
> >
> >  print "}";
> > @@ -754,6 +1086,8 @@ for (i = 0; i < n_target_val; i++) {
> >       name = var_target_val[i]
> >       print "  hstate.add_hwi (ptr->" name");";
> >  }
> > +print "  for (size_t i = 0; i < sizeof (ptr->explicit_mask) / sizeof (ptr->explicit_mask[0]); i++)";
> > +print "    hstate.add_hwi (ptr->explicit_mask[i]);";
> >  print "  return hstate.end ();";
> >  print "}";
> >
> > @@ -778,6 +1112,10 @@ for (i = 0; i < n_target_val; i++) {
> >       name = var_target_val[i]
> >       print "  bp_pack_value (bp, ptr->" name", 64);";
> >  }
> > +
> > +print "  for (size_t i = 0; i < sizeof (ptr->explicit_mask) / sizeof (ptr->explicit_mask[0]); i++)";
> > +print "    bp_pack_value (bp, ptr->explicit_mask[i], 64);";
> > +
> >  print "}";
> >
> >  print "";
> > @@ -804,6 +1142,9 @@ for (i = 0; i < n_target_val; i++) {
> >       print "  ptr->" name" = (" var_target_val_type[i] ") bp_unpack_value (bp, 64);";
> >  }
> >
> > +print "  for (size_t i = 0; i < sizeof (ptr->explicit_mask) / sizeof (ptr->explicit_mask[0]); i++)";
> > +print "    ptr->explicit_mask[i] = bp_unpack_value (bp, 64);";
> > +
> >  print "}";
> >
> >  print "/* free heap memory used by target options  */";
> > @@ -869,6 +1210,8 @@ for (i = 0; i < n_opt_val; i++) {
> >       else
> >               print "  hstate.add_hwi (ptr->" name");";
> >  }
> > +print "  for (size_t i = 0; i < sizeof (ptr->explicit_mask) / sizeof (ptr->explicit_mask[0]); i++)";
> > +print "    hstate.add_hwi (ptr->explicit_mask[i]);";
> >  print "  return hstate.end ();";
> >  print "}";
> >
> > @@ -896,6 +1239,9 @@ for (i = 0; i < n_opt_val; i++) {
> >               print "    return false;";
> >       }
> >  }
> > +print "  for (size_t i = 0; i < sizeof (ptr1->explicit_mask) / sizeof (ptr1->explicit_mask[0]); i++)";
> > +print "    if (ptr1->explicit_mask[i] != ptr2->explicit_mask[i])";
> > +print "      return false;"
> >  print "  return true;";
> >  print "}";
> >
> > @@ -914,6 +1260,8 @@ for (i = 0; i < n_opt_val; i++) {
> >       else
> >               print "  bp_pack_value (bp, ptr->" name", 64);";
> >  }
> > +print "  for (size_t i = 0; i < sizeof (ptr->explicit_mask) / sizeof (ptr->explicit_mask[0]); i++)";
> > +print "    bp_pack_value (bp, ptr->explicit_mask[i], 64);";
> >  print "}";
> >
> >  print "";
> > @@ -935,6 +1283,8 @@ for (i = 0; i < n_opt_val; i++) {
> >       else
> >             print "  ptr->" name" = (" var_opt_val_type[i] ") bp_unpack_value (bp, 64);";
> >  }
> > +print "  for (size_t i = 0; i < sizeof (ptr->explicit_mask) / sizeof (ptr->explicit_mask[0]); i++)";
> > +print "    ptr->explicit_mask[i] = bp_unpack_value (bp, 64);";
> >  print "}";
> >  print "/* Free heap memory used by optimization options  */";
> >  print "void";
> > --- gcc/tree.h.jj     2020-09-03 21:53:35.236793726 +0200
> > +++ gcc/tree.h        2020-09-11 16:08:03.909026724 +0200
> > @@ -3272,8 +3272,10 @@ extern vec<tree, va_gc> **decl_debug_arg
> >  #define TREE_OPTIMIZATION_BASE_OPTABS(NODE) \
> >    (OPTIMIZATION_NODE_CHECK (NODE)->optimization.base_optabs)
> >
> > -/* Return a tree node that encapsulates the optimization options in OPTS.  */
> > -extern tree build_optimization_node (struct gcc_options *opts);
> > +/* Return a tree node that encapsulates the optimization options in OPTS
> > +   and OPTS_SET.  */
> > +extern tree build_optimization_node (struct gcc_options *opts,
> > +                                  struct gcc_options *opts_set);
> >
> >  #define TREE_TARGET_OPTION(NODE) \
> >    (TARGET_OPTION_NODE_CHECK (NODE)->target_option.opts)
> > @@ -3281,8 +3283,10 @@ extern tree build_optimization_node (str
> >  #define TREE_TARGET_GLOBALS(NODE) \
> >    (TARGET_OPTION_NODE_CHECK (NODE)->target_option.globals)
> >
> > -/* Return a tree node that encapsulates the target options in OPTS.  */
> > -extern tree build_target_option_node (struct gcc_options *opts);
> > +/* Return a tree node that encapsulates the target options in OPTS and
> > +   OPTS_SET.  */
> > +extern tree build_target_option_node (struct gcc_options *opts,
> > +                                   struct gcc_options *opts_set);
> >
> >  extern void prepare_target_option_nodes_for_pch (void);
> >
> > --- gcc/tree.c.jj     2020-09-01 09:17:28.129109462 +0200
> > +++ gcc/tree.c        2020-09-11 16:12:24.199201570 +0200
> > @@ -12574,17 +12574,18 @@ cl_option_hasher::equal (tree x, tree y)
> >      gcc_unreachable ();
> >  }
> >
> > -/* Build an OPTIMIZATION_NODE based on the options in OPTS.  */
> > +/* Build an OPTIMIZATION_NODE based on the options in OPTS and OPTS_SET.  */
> >
> >  tree
> > -build_optimization_node (struct gcc_options *opts)
> > +build_optimization_node (struct gcc_options *opts,
> > +                      struct gcc_options *opts_set)
> >  {
> >    tree t;
> >
> >    /* Use the cache of optimization nodes.  */
> >
> >    cl_optimization_save (TREE_OPTIMIZATION (cl_optimization_node),
> > -                     opts);
> > +                     opts, opts_set);
> >
> >    tree *slot = cl_option_hash_table->find_slot (cl_optimization_node, INSERT);
> >    t = *slot;
> > @@ -12601,17 +12602,18 @@ build_optimization_node (struct gcc_opti
> >    return t;
> >  }
> >
> > -/* Build a TARGET_OPTION_NODE based on the options in OPTS.  */
> > +/* Build a TARGET_OPTION_NODE based on the options in OPTS and OPTS_SET.  */
> >
> >  tree
> > -build_target_option_node (struct gcc_options *opts)
> > +build_target_option_node (struct gcc_options *opts,
> > +                       struct gcc_options *opts_set)
> >  {
> >    tree t;
> >
> >    /* Use the cache of optimization nodes.  */
> >
> >    cl_target_option_save (TREE_TARGET_OPTION (cl_target_option_node),
> > -                      opts);
> > +                      opts, opts_set);
> >
> >    tree *slot = cl_option_hash_table->find_slot (cl_target_option_node, INSERT);
> >    t = *slot;
> > --- gcc/function.c.jj 2020-08-27 18:42:35.547712976 +0200
> > +++ gcc/function.c    2020-09-11 15:59:15.889778934 +0200
> > @@ -4664,7 +4664,8 @@ invoke_set_current_function_hook (tree f
> >        if (optimization_current_node != opts)
> >       {
> >         optimization_current_node = opts;
> > -       cl_optimization_restore (&global_options, TREE_OPTIMIZATION (opts));
> > +       cl_optimization_restore (&global_options, &global_options_set,
> > +                                TREE_OPTIMIZATION (opts));
> >       }
> >
> >        targetm.set_current_function (fndecl);
> > --- gcc/ipa-inline-transform.c.jj     2020-04-30 19:22:27.290722552 +0200
> > +++ gcc/ipa-inline-transform.c        2020-09-11 16:11:42.451815554 +0200
> > @@ -380,14 +380,15 @@ inline_call (struct cgraph_edge *e, bool
> >        && opt_for_fn (to->decl, flag_strict_aliasing))
> >      {
> >        struct gcc_options opts = global_options;
> > +      struct gcc_options opts_set = global_options_set;
> >
> > -      cl_optimization_restore (&opts, opts_for_fn (to->decl));
> > +      cl_optimization_restore (&opts, &opts_set, opts_for_fn (to->decl));
> >        opts.x_flag_strict_aliasing = false;
> >        if (dump_file)
> >       fprintf (dump_file, "Dropping flag_strict_aliasing on %s\n",
> >                to->dump_name ());
> >        DECL_FUNCTION_SPECIFIC_OPTIMIZATION (to->decl)
> > -      = build_optimization_node (&opts);
> > +      = build_optimization_node (&opts, &opts_set);
> >        reload_optimization_node = true;
> >      }
> >
> > @@ -420,8 +421,9 @@ inline_call (struct cgraph_edge *e, bool
> >            != opt_for_fn (to->decl, flag_errno_math))
> >       {
> >         struct gcc_options opts = global_options;
> > +       struct gcc_options opts_set = global_options_set;
> >
> > -       cl_optimization_restore (&opts, opts_for_fn (to->decl));
> > +       cl_optimization_restore (&opts, &opts_set, opts_for_fn (to->decl));
> >         opts.x_flag_rounding_math
> >           = opt_for_fn (callee->decl, flag_rounding_math);
> >         opts.x_flag_trapping_math
> > @@ -448,7 +450,7 @@ inline_call (struct cgraph_edge *e, bool
> >           fprintf (dump_file, "Copying FP flags from %s to %s\n",
> >                    callee->dump_name (), to->dump_name ());
> >         DECL_FUNCTION_SPECIFIC_OPTIMIZATION (to->decl)
> > -          = build_optimization_node (&opts);
> > +          = build_optimization_node (&opts, &opts_set);
> >         reload_optimization_node = true;
> >       }
> >      }
> > --- gcc/target.def.jj 2020-07-28 15:39:09.985756544 +0200
> > +++ gcc/target.def    2020-09-11 16:57:49.379071059 +0200
> > @@ -6376,7 +6376,8 @@ DEFHOOK
> >  in the @code{struct cl_target_option} structure for function-specific\n\
> >  options from the @code{struct gcc_options} structure.\n\
> >  @xref{Option file format}.",
> > - void, (struct cl_target_option *ptr, struct gcc_options *opts), NULL)
> > + void, (struct cl_target_option *ptr, struct gcc_options *opts,
> > +     struct gcc_options *opts_set), NULL)
> >
> >  /* Function to restore any extra target state from the target options
> >     structure.  */
> > @@ -6385,7 +6386,8 @@ DEFHOOK
> >   "This hook is called to restore any additional target-specific\n\
> >  information in the @code{struct cl_target_option} structure for\n\
> >  function-specific options to the @code{struct gcc_options} structure.",
> > - void, (struct gcc_options *opts, struct cl_target_option *ptr), NULL)
> > + void, (struct gcc_options *opts, struct gcc_options *opts_set,
> > +     struct cl_target_option *ptr), NULL)
> >
> >  /* Function to update target-specific option information after being
> >     streamed in.  */
> > --- gcc/target-globals.c.jj   2020-01-12 11:54:36.937405503 +0100
> > +++ gcc/target-globals.c      2020-09-11 16:01:11.156087362 +0200
> > @@ -108,11 +108,11 @@ save_target_globals_default_opts ()
> >        attribute.  */
> >        optimization_current_node = optimization_default_node;
> >        cl_optimization_restore
> > -     (&global_options,
> > +     (&global_options, &global_options_set,
> >        TREE_OPTIMIZATION (optimization_default_node));
> >        globals = save_target_globals ();
> >        optimization_current_node = opts;
> > -      cl_optimization_restore (&global_options,
> > +      cl_optimization_restore (&global_options, &global_options_set,
> >                              TREE_OPTIMIZATION (opts));
> >        return globals;
> >      }
> > --- gcc/toplev.c.jj   2020-08-12 17:00:35.255269682 +0200
> > +++ gcc/toplev.c      2020-09-11 16:05:23.500382155 +0200
> > @@ -1867,7 +1867,8 @@ process_options (void)
> >                                      DK_ERROR, UNKNOWN_LOCATION);
> >
> >    /* Save the current optimization options.  */
> > -  optimization_default_node = build_optimization_node (&global_options);
> > +  optimization_default_node
> > +    = build_optimization_node (&global_options, &global_options_set);
> >    optimization_current_node = optimization_default_node;
> >
> >    if (flag_checking >= 2)
> > @@ -2075,7 +2076,7 @@ target_reinit (void)
> >      {
> >        optimization_current_node = optimization_default_node;
> >        cl_optimization_restore
> > -     (&global_options,
> > +     (&global_options, &global_options_set,
> >        TREE_OPTIMIZATION (optimization_default_node));
> >      }
> >    this_fn_optabs = this_target_optabs;
> > @@ -2107,7 +2108,7 @@ target_reinit (void)
> >    if (saved_optimization_current_node != optimization_default_node)
> >      {
> >        optimization_current_node = saved_optimization_current_node;
> > -      cl_optimization_restore (&global_options,
> > +      cl_optimization_restore (&global_options, &global_options_set,
> >                              TREE_OPTIMIZATION (optimization_current_node));
> >      }
> >    this_fn_optabs = saved_this_fn_optabs;
> > --- gcc/tree-streamer-in.c.jj 2020-08-27 18:42:35.691710903 +0200
> > +++ gcc/tree-streamer-in.c    2020-09-11 16:03:32.015019201 +0200
> > @@ -800,11 +800,12 @@ lto_input_ts_function_decl_tree_pointers
> >      tree opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr);
> >      if (opts)
> >        {
> > -     struct gcc_options tmp;
> > +     struct gcc_options tmp, tmp_set;
> >       init_options_struct (&tmp, NULL);
> > -     cl_optimization_restore (&tmp, TREE_OPTIMIZATION (opts));
> > -     finish_options (&tmp, &global_options_set, UNKNOWN_LOCATION);
> > -     opts = build_optimization_node (&tmp);
> > +     memset (&tmp_set, 0, sizeof (tmp_set));
> > +     cl_optimization_restore (&tmp, &tmp_set, TREE_OPTIMIZATION (opts));
> > +     finish_options (&tmp, &tmp_set, UNKNOWN_LOCATION);
> > +     opts = build_optimization_node (&tmp, &tmp_set);
> >       DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr) = opts;
> >        }
> >    }
> > --- gcc/doc/tm.texi.jj        2020-08-03 22:54:51.414531719 +0200
> > +++ gcc/doc/tm.texi   2020-09-11 17:11:02.447396061 +0200
> > @@ -10493,14 +10493,14 @@ the function declaration to hold a point
> >  @code{struct cl_target_option} structure.
> >  @end deftypefn
> >
> > -@deftypefn {Target Hook} void TARGET_OPTION_SAVE (struct cl_target_option *@var{ptr}, struct gcc_options *@var{opts})
> > +@deftypefn {Target Hook} void TARGET_OPTION_SAVE (struct cl_target_option *@var{ptr}, struct gcc_options *@var{opts}, struct gcc_options *@var{opts_set})
> >  This hook is called to save any additional target-specific information
> >  in the @code{struct cl_target_option} structure for function-specific
> >  options from the @code{struct gcc_options} structure.
> >  @xref{Option file format}.
> >  @end deftypefn
> >
> > -@deftypefn {Target Hook} void TARGET_OPTION_RESTORE (struct gcc_options *@var{opts}, struct cl_target_option *@var{ptr})
> > +@deftypefn {Target Hook} void TARGET_OPTION_RESTORE (struct gcc_options *@var{opts}, struct gcc_options *@var{opts_set}, struct cl_target_option *@var{ptr})
> >  This hook is called to restore any additional target-specific
> >  information in the @code{struct cl_target_option} structure for
> >  function-specific options to the @code{struct gcc_options} structure.
> > --- gcc/c-family/c-attribs.c.jj       2020-07-28 15:39:09.663760971 +0200
> > +++ gcc/c-family/c-attribs.c  2020-09-11 16:10:15.736090887 +0200
> > @@ -4448,7 +4448,7 @@ handle_optimize_attribute (tree *node, t
> >        tree old_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node);
> >
> >        /* Save current options.  */
> > -      cl_optimization_save (&cur_opts, &global_options);
> > +      cl_optimization_save (&cur_opts, &global_options, &global_options_set);
> >
> >        /* If we previously had some optimization options, use them as the
> >        default.  */
> > @@ -4460,16 +4460,17 @@ handle_optimize_attribute (tree *node, t
> >       }
> >
> >        if (old_opts)
> > -     cl_optimization_restore (&global_options,
> > +     cl_optimization_restore (&global_options, &global_options_set,
> >                                TREE_OPTIMIZATION (old_opts));
> >
> >        /* Parse options, and update the vector.  */
> >        parse_optimize_options (args, true);
> >        DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)
> > -     = build_optimization_node (&global_options);
> > +     = build_optimization_node (&global_options, &global_options_set);
> >
> >        /* Restore current options.  */
> > -      cl_optimization_restore (&global_options, &cur_opts);
> > +      cl_optimization_restore (&global_options, &global_options_set,
> > +                            &cur_opts);
> >        if (saved_global_options != NULL)
> >       {
> >         cl_optimization_compare (saved_global_options, &global_options);
> > --- gcc/c-family/c-pragma.c.jj        2020-07-28 15:39:09.667760916 +0200
> > +++ gcc/c-family/c-pragma.c   2020-09-11 16:06:16.289607003 +0200
> > @@ -987,7 +987,8 @@ handle_pragma_optimize (cpp_reader *ARG_
> >
> >        parse_optimize_options (args, false);
> >        current_optimize_pragma = chainon (current_optimize_pragma, args);
> > -      optimization_current_node = build_optimization_node (&global_options);
> > +      optimization_current_node
> > +     = build_optimization_node (&global_options, &global_options_set);
> >        c_cpp_builtins_optimize_pragma (parse_in,
> >                                     optimization_previous_node,
> >                                     optimization_current_node);
> > @@ -1034,8 +1035,10 @@ handle_pragma_push_options (cpp_reader *
> >        p->saved_global_options = XNEW (gcc_options);
> >        *p->saved_global_options = global_options;
> >      }
> > -  p->optimize_binary = build_optimization_node (&global_options);
> > -  p->target_binary = build_target_option_node (&global_options);
> > +  p->optimize_binary = build_optimization_node (&global_options,
> > +                                             &global_options_set);
> > +  p->target_binary = build_target_option_node (&global_options,
> > +                                            &global_options_set);
> >
> >    /* Save optimization and target flags in string list format.  */
> >    p->optimize_strings = copy_list (current_optimize_pragma);
> > @@ -1079,7 +1082,7 @@ handle_pragma_pop_options (cpp_reader *A
> >    if (p->optimize_binary != optimization_current_node)
> >      {
> >        tree old_optimize = optimization_current_node;
> > -      cl_optimization_restore (&global_options,
> > +      cl_optimization_restore (&global_options, &global_options_set,
> >                              TREE_OPTIMIZATION (p->optimize_binary));
> >        c_cpp_builtins_optimize_pragma (parse_in, old_optimize,
> >                                     p->optimize_binary);
> > @@ -1122,7 +1125,7 @@ handle_pragma_reset_options (cpp_reader
> >    if (new_optimize != optimization_current_node)
> >      {
> >        tree old_optimize = optimization_current_node;
> > -      cl_optimization_restore (&global_options,
> > +      cl_optimization_restore (&global_options, &global_options_set,
> >                              TREE_OPTIMIZATION (new_optimize));
> >        c_cpp_builtins_optimize_pragma (parse_in, old_optimize, new_optimize);
> >        optimization_current_node = new_optimize;
> > --- gcc/go/go-gcc.cc.jj       2020-04-16 07:17:15.546027891 +0200
> > +++ gcc/go/go-gcc.cc  2020-09-11 16:29:40.921956541 +0200
> > @@ -3281,13 +3281,15 @@ Gcc_backend::function(Btype* fntype, con
> >        if (pos == name.length())
> >       {
> >         struct cl_optimization cur_opts;
> > -       cl_optimization_save(&cur_opts, &global_options);
> > +       cl_optimization_save(&cur_opts, &global_options,
> > +                            &global_options_set);
> >         global_options.x_optimize_size = 1;
> >         global_options.x_optimize_fast = 0;
> >         global_options.x_optimize_debug = 0;
> >         DECL_FUNCTION_SPECIFIC_OPTIMIZATION(decl) =
> > -         build_optimization_node(&global_options);
> > -       cl_optimization_restore(&global_options, &cur_opts);
> > +         build_optimization_node(&global_options, &global_options_set);
> > +       cl_optimization_restore(&global_options, &global_options_set,
> > +                               &cur_opts);
> >       }
> >      }
> >
> > --- gcc/ada/gcc-interface/trans.c.jj  2020-08-27 18:42:35.426714718 +0200
> > +++ gcc/ada/gcc-interface/trans.c     2020-09-11 16:26:03.658151145 +0200
> > @@ -678,7 +678,8 @@ gigi (Node_Id gnat_root,
> >
> >    /* Save the current optimization options again after the above possible
> >       global_options changes.  */
> > -  optimization_default_node = build_optimization_node (&global_options);
> > +  optimization_default_node
> > +    = build_optimization_node (&global_options, &global_options_set);
> >    optimization_current_node = optimization_default_node;
> >
> >    /* Now translate the compilation unit proper.  */
> > --- gcc/config/aarch64/aarch64.c.jj   2020-09-01 13:03:16.699738649 +0200
> > +++ gcc/config/aarch64/aarch64.c      2020-09-11 17:10:51.382558685 +0200
> > @@ -15034,7 +15034,7 @@ aarch64_override_options (void)
> >    /* Save these options as the default ones in case we push and pop them later
> >       while processing functions with potential target attributes.  */
> >    target_option_default_node = target_option_current_node
> > -      = build_target_option_node (&global_options);
> > +    = build_target_option_node (&global_options, &global_options_set);
> >  }
> >
> >  /* Implement targetm.override_options_after_change.  */
> > @@ -15109,7 +15109,8 @@ initialize_aarch64_code_model (struct gc
> >  /* Implement TARGET_OPTION_SAVE.  */
> >
> >  static void
> > -aarch64_option_save (struct cl_target_option *ptr, struct gcc_options *opts)
> > +aarch64_option_save (struct cl_target_option *ptr, struct gcc_options *opts,
> > +                  struct gcc_options */* opts_set */)
> >  {
> >    ptr->x_aarch64_override_tune_string = opts->x_aarch64_override_tune_string;
> >    ptr->x_aarch64_branch_protection_string
> > @@ -15120,7 +15121,9 @@ aarch64_option_save (struct cl_target_op
> >     using the information saved in PTR.  */
> >
> >  static void
> > -aarch64_option_restore (struct gcc_options *opts, struct cl_target_option *ptr)
> > +aarch64_option_restore (struct gcc_options *opts,
> > +                     struct gcc_options */* opts_set */,
> > +                     struct cl_target_option *ptr)
> >  {
> >    opts->x_explicit_tune_core = ptr->x_explicit_tune_core;
> >    selected_tune = aarch64_get_tune_cpu (ptr->x_explicit_tune_core);
> > @@ -15210,7 +15213,8 @@ aarch64_set_current_function (tree fndec
> >    aarch64_previous_fndecl = fndecl;
> >
> >    /* First set the target options.  */
> > -  cl_target_option_restore (&global_options, TREE_TARGET_OPTION (new_tree));
> > +  cl_target_option_restore (&global_options, &global_options_set,
> > +                         TREE_TARGET_OPTION (new_tree));
> >
> >    aarch64_save_restore_target_globals (new_tree);
> >  }
> > @@ -15709,17 +15713,18 @@ aarch64_option_valid_attribute_p (tree f
> >      }
> >    tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
> >
> > -  old_optimize = build_optimization_node (&global_options);
> > +  old_optimize
> > +    = build_optimization_node (&global_options, &global_options_set);
> >    func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
> >
> >    /* 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,
> > +    cl_optimization_restore (&global_options, &global_options_set,
> >                            TREE_OPTIMIZATION (func_optimize));
> >
> >    /* Save the current target options to restore at the end.  */
> > -  cl_target_option_save (&cur_target, &global_options);
> > +  cl_target_option_save (&cur_target, &global_options, &global_options_set);
> >
> >    /* If fndecl already has some target attributes applied to it, unpack
> >       them so that we add this attribute on top of them, rather than
> > @@ -15730,11 +15735,12 @@ aarch64_option_valid_attribute_p (tree f
> >       = TREE_TARGET_OPTION (existing_target);
> >
> >        if (existing_options)
> > -     cl_target_option_restore (&global_options, existing_options);
> > +     cl_target_option_restore (&global_options, &global_options_set,
> > +                               existing_options);
> >      }
> >    else
> > -    cl_target_option_restore (&global_options,
> > -                     TREE_TARGET_OPTION (target_option_current_node));
> > +    cl_target_option_restore (&global_options, &global_options_set,
> > +                           TREE_TARGET_OPTION (target_option_current_node));
> >
> >    ret = aarch64_process_target_attr (args);
> >
> > @@ -15754,12 +15760,14 @@ aarch64_option_valid_attribute_p (tree f
> >         aarch64_init_simd_builtins ();
> >         current_target_pragma = saved_current_target_pragma;
> >       }
> > -      new_target = build_target_option_node (&global_options);
> > +      new_target = build_target_option_node (&global_options,
> > +                                          &global_options_set);
> >      }
> >    else
> >      new_target = NULL;
> >
> > -  new_optimize = build_optimization_node (&global_options);
> > +  new_optimize = build_optimization_node (&global_options,
> > +                                       &global_options_set);
> >
> >    if (fndecl && ret)
> >      {
> > @@ -15769,10 +15777,10 @@ aarch64_option_valid_attribute_p (tree f
> >       DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize;
> >      }
> >
> > -  cl_target_option_restore (&global_options, &cur_target);
> > +  cl_target_option_restore (&global_options, &global_options_set, &cur_target);
> >
> >    if (old_optimize != new_optimize)
> > -    cl_optimization_restore (&global_options,
> > +    cl_optimization_restore (&global_options, &global_options_set,
> >                            TREE_OPTIMIZATION (old_optimize));
> >    return ret;
> >  }
> > --- gcc/config/aarch64/aarch64-c.c.jj 2020-09-10 20:51:28.079311491 +0200
> > +++ gcc/config/aarch64/aarch64-c.c    2020-09-11 16:31:21.098483571 +0200
> > @@ -242,12 +242,12 @@ aarch64_pragma_target_parse (tree args,
> >    else
> >      {
> >        pop_target = pop_target ? pop_target : target_option_default_node;
> > -      cl_target_option_restore (&global_options,
> > +      cl_target_option_restore (&global_options, &global_options_set,
> >                               TREE_TARGET_OPTION (pop_target));
> >      }
> >
> >    target_option_current_node
> > -    = build_target_option_node (&global_options);
> > +    = build_target_option_node (&global_options, &global_options_set);
> >
> >    aarch64_reset_previous_fndecl ();
> >    /* For the definitions, ensure all newly defined macros are considered
> > --- gcc/config/arm/arm.c.jj   2020-09-10 17:40:06.090914964 +0200
> > +++ gcc/config/arm/arm.c      2020-09-11 17:44:28.643014087 +0200
> > @@ -247,8 +247,9 @@ static tree arm_build_builtin_va_list (v
> >  static void arm_expand_builtin_va_start (tree, rtx);
> >  static tree arm_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *);
> >  static void arm_option_override (void);
> > -static void arm_option_save (struct cl_target_option *, struct gcc_options *);
> > -static void arm_option_restore (struct gcc_options *,
> > +static void arm_option_save (struct cl_target_option *, struct gcc_options *,
> > +                          struct gcc_options *);
> > +static void arm_option_restore (struct gcc_options *, struct gcc_options *,
> >                               struct cl_target_option *);
> >  static void arm_override_options_after_change (void);
> >  static void arm_option_print (FILE *, int, struct cl_target_option *);
> > @@ -3043,7 +3044,8 @@ arm_override_options_after_change (void)
> >
> >  /* Implement TARGET_OPTION_SAVE.  */
> >  static void
> > -arm_option_save (struct cl_target_option *ptr, struct gcc_options *opts)
> > +arm_option_save (struct cl_target_option *ptr, struct gcc_options *opts,
> > +              struct gcc_options */* opts_set */)
> >  {
> >    ptr->x_arm_arch_string = opts->x_arm_arch_string;
> >    ptr->x_arm_cpu_string = opts->x_arm_cpu_string;
> > @@ -3052,13 +3054,13 @@ arm_option_save (struct cl_target_option
> >
> >  /* Implement TARGET_OPTION_RESTORE.  */
> >  static void
> > -arm_option_restore (struct gcc_options *opts, struct cl_target_option *ptr)
> > +arm_option_restore (struct gcc_options *opts, struct gcc_options *opts_set,
> > +                 struct cl_target_option *ptr)
> >  {
> >    opts->x_arm_arch_string = ptr->x_arm_arch_string;
> >    opts->x_arm_cpu_string = ptr->x_arm_cpu_string;
> >    opts->x_arm_tune_string = ptr->x_arm_tune_string;
> > -  arm_configure_build_target (&arm_active_target, ptr, &global_options_set,
> > -                           false);
> > +  arm_configure_build_target (&arm_active_target, ptr, opts_set, false);
> >  }
> >
> >  /* Reset options between modes that the user has specified.  */
> > @@ -3457,7 +3459,7 @@ arm_option_override (void)
> >        arm_fpu_index = (enum fpu_type) fpu_index;
> >      }
> >
> > -  cl_target_option_save (&opts, &global_options);
> > +  cl_target_option_save (&opts, &global_options, &global_options_set);
> >    arm_configure_build_target (&arm_active_target, &opts, &global_options_set,
> >                             true);
> >
> > @@ -3682,7 +3684,8 @@ arm_option_override (void)
> >      flag_schedule_fusion = 0;
> >
> >    /* Need to remember initial options before they are overriden.  */
> > -  init_optimize = build_optimization_node (&global_options);
> > +  init_optimize = build_optimization_node (&global_options,
> > +                                        &global_options_set);
> >
> >    arm_options_perform_arch_sanity_checks ();
> >    arm_option_override_internal (&global_options, &global_options_set);
> > @@ -3691,7 +3694,7 @@ arm_option_override (void)
> >
> >    /* Create the default target_options structure.  */
> >    target_option_default_node = target_option_current_node
> > -    = build_target_option_node (&global_options);
> > +    = build_target_option_node (&global_options, &global_options_set);
> >
> >    /* Register global variables with the garbage collector.  */
> >    arm_add_gc_roots ();
> > @@ -32332,7 +32335,8 @@ arm_set_current_function (tree fndecl)
> >    arm_previous_fndecl = fndecl;
> >
> >    /* First set the target options.  */
> > -  cl_target_option_restore (&global_options, TREE_TARGET_OPTION (new_tree));
> > +  cl_target_option_restore (&global_options, &global_options_set,
> > +                         TREE_TARGET_OPTION (new_tree));
> >
> >    save_restore_target_globals (new_tree);
> >
> > @@ -32534,7 +32538,7 @@ arm_valid_target_attribute_tree (tree ar
> >    if (!arm_valid_target_attribute_rec (args, opts))
> >      return NULL_TREE;
> >
> > -  cl_target_option_save (&cl_opts, opts);
> > +  cl_target_option_save (&cl_opts, opts, opts_set);
> >    arm_configure_build_target (&arm_active_target, &cl_opts, opts_set, false);
> >    arm_option_check_internal (opts);
> >    /* Do any overrides, such as global options arch=xxx.
> > @@ -32543,11 +32547,11 @@ arm_valid_target_attribute_tree (tree ar
> >    arm_options_perform_arch_sanity_checks ();
> >    arm_option_override_internal (opts, opts_set);
> >
> > -  return build_target_option_node (opts);
> > +  return build_target_option_node (opts, opts_set);
> >  }
> >
> >  static void
> > -add_attribute  (const char * mode, tree *attributes)
> > +add_attribute (const char * mode, tree *attributes)
> >  {
> >    size_t len = strlen (mode);
> >    tree value = build_string (len, mode);
> > @@ -32599,7 +32603,7 @@ arm_valid_target_attribute_p (tree fndec
> >                             tree args, int ARG_UNUSED (flags))
> >  {
> >    bool ret = true;
> > -  struct gcc_options func_options;
> > +  struct gcc_options func_options, func_options_set;
> >    tree cur_tree, new_optimize;
> >    gcc_assert ((fndecl != NULL_TREE) && (args != NULL_TREE));
> >
> > @@ -32615,22 +32619,23 @@ arm_valid_target_attribute_p (tree fndec
> >    memset (&func_options, 0, sizeof (func_options));
> >    init_options_struct (&func_options, NULL);
> >    lang_hooks.init_options_struct (&func_options);
> > +  memset (&func_options_set, 0, sizeof (func_options_set));
> >
> >    /* Initialize func_options to the defaults.  */
> > -  cl_optimization_restore (&func_options,
> > +  cl_optimization_restore (&func_options, &func_options_set,
> >                          TREE_OPTIMIZATION (func_optimize));
> >
> > -  cl_target_option_restore (&func_options,
> > +  cl_target_option_restore (&func_options, &func_options_set,
> >                           TREE_TARGET_OPTION (target_option_default_node));
> >
> >    /* Set func_options flags with new target mode.  */
> >    cur_tree = arm_valid_target_attribute_tree (args, &func_options,
> > -                                           &global_options_set);
> > +                                           &func_options_set);
> >
> >    if (cur_tree == NULL_TREE)
> >      ret = false;
> >
> > -  new_optimize = build_optimization_node (&func_options);
> > +  new_optimize = build_optimization_node (&func_options, &func_options_set);
> >
> >    DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = cur_tree;
> >
> > --- gcc/config/arm/arm-c.c.jj 2020-04-08 18:15:36.698950309 +0200
> > +++ gcc/config/arm/arm-c.c    2020-09-11 16:39:09.967580092 +0200
> > @@ -390,7 +390,7 @@ arm_pragma_target_parse (tree args, tree
> >    if (! args)
> >      {
> >        cur_tree = ((pop_target) ? pop_target : target_option_default_node);
> > -      cl_target_option_restore (&global_options,
> > +      cl_target_option_restore (&global_options, &global_options_set,
> >                               TREE_TARGET_OPTION (cur_tree));
> >      }
> >    else
> > @@ -399,7 +399,7 @@ arm_pragma_target_parse (tree args, tree
> >                                                 &global_options_set);
> >        if (cur_tree == NULL_TREE)
> >       {
> > -       cl_target_option_restore (&global_options,
> > +       cl_target_option_restore (&global_options, &global_options_set,
> >                                   TREE_TARGET_OPTION (prev_tree));
> >         return false;
> >       }
> > --- gcc/config/csky/csky.c.jj 2020-01-12 11:54:36.294415204 +0100
> > +++ gcc/config/csky/csky.c    2020-09-11 16:44:08.649172796 +0200
> > @@ -2435,7 +2435,7 @@ csky_option_override (void)
> >    /* Create the default target_options structure.  We need this early
> >       to configure the overall build target.  */
> >    target_option_default_node = target_option_current_node
> > -                          = build_target_option_node (&global_options);
> > +    = build_target_option_node (&global_options, &global_options_set);
> >
> >    csky_configure_build_target (&csky_active_target,
> >                             TREE_TARGET_OPTION (target_option_default_node),
> > @@ -2600,7 +2600,7 @@ csky_option_override (void)
> >
> >    /* Resynchronize the saved target options.  */
> >    cl_target_option_save (TREE_TARGET_OPTION (target_option_default_node),
> > -                      &global_options);
> > +                      &global_options, &global_options_set);
> >
> >  #ifdef ENABLE_TPF_DEBUG
> >    /* Don't emit DWARF4 unless specifically selected.  The TPF
> > --- gcc/config/gcn/gcn.c.jj   2020-07-28 15:39:09.722760160 +0200
> > +++ gcc/config/gcn/gcn.c      2020-09-11 16:45:33.187925370 +0200
> > @@ -4974,26 +4974,28 @@ gcn_fixup_accel_lto_options (tree fndecl
> >    if (!func_optimize)
> >      return;
> >
> > -  tree old_optimize = build_optimization_node (&global_options);
> > +  tree old_optimize
> > +    = build_optimization_node (&global_options, &global_options_set);
> >    tree new_optimize;
> >
> >    /* If the function changed the optimization levels as well as
> >       setting target options, start with the optimizations
> >       specified.  */
> >    if (func_optimize != old_optimize)
> > -    cl_optimization_restore (&global_options,
> > +    cl_optimization_restore (&global_options, &global_options_set,
> >                            TREE_OPTIMIZATION (func_optimize));
> >
> >    gcn_option_override ();
> >
> >    /* The target attributes may also change some optimization flags,
> >       so update the optimization options if necessary.  */
> > -  new_optimize = build_optimization_node (&global_options);
> > +  new_optimize = build_optimization_node (&global_options,
> > +                                       &global_options_set);
> >
> >    if (old_optimize != new_optimize)
> >      {
> >        DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize;
> > -      cl_optimization_restore (&global_options,
> > +      cl_optimization_restore (&global_options, &global_options_set,
> >                              TREE_OPTIMIZATION (old_optimize));
> >      }
> >  }
> > --- gcc/config/i386/i386-builtins.c.jj        2020-08-18 07:50:18.508923120 +0200
> > +++ gcc/config/i386/i386-builtins.c   2020-09-11 16:14:44.230142120 +0200
> > @@ -1866,7 +1866,8 @@ get_builtin_code_for_version (tree decl,
> >       before the ssse3 version. */
> >    if (strstr (attrs_str, "arch=") != NULL)
> >      {
> > -      cl_target_option_save (&cur_target, &global_options);
> > +      cl_target_option_save (&cur_target, &global_options,
> > +                          &global_options_set);
> >        target_node
> >       = ix86_valid_target_attribute_tree (decl, attrs, &global_options,
> >                                           &global_options_set, 0);
> > @@ -1935,7 +1936,8 @@ get_builtin_code_for_version (tree decl,
> >             break;
> >           }
> >
> > -      cl_target_option_restore (&global_options, &cur_target);
> > +      cl_target_option_restore (&global_options, &global_options_set,
> > +                             &cur_target);
> >
> >        if (predicate_list && arg_str == NULL)
> >       {
> > --- gcc/config/i386/i386-c.c.jj       2020-07-28 15:39:09.730760050 +0200
> > +++ gcc/config/i386/i386-c.c  2020-09-11 16:18:57.889411553 +0200
> > @@ -603,7 +603,8 @@ ix86_target_macros_internal (HOST_WIDE_I
> >  static bool
> >  ix86_pragma_target_parse (tree args, tree pop_target)
> >  {
> > -  tree prev_tree = build_target_option_node (&global_options);
> > +  tree prev_tree
> > +    = build_target_option_node (&global_options, &global_options_set);
> >    tree cur_tree;
> >    struct cl_target_option *prev_opt;
> >    struct cl_target_option *cur_opt;
> > @@ -621,7 +622,7 @@ ix86_pragma_target_parse (tree args, tre
> >    if (! args)
> >      {
> >        cur_tree = (pop_target ? pop_target : target_option_default_node);
> > -      cl_target_option_restore (&global_options,
> > +      cl_target_option_restore (&global_options, &global_options_set,
> >                               TREE_TARGET_OPTION (cur_tree));
> >      }
> >    else
> > @@ -631,7 +632,7 @@ ix86_pragma_target_parse (tree args, tre
> >                                                  &global_options_set, 0);
> >        if (!cur_tree || cur_tree == error_mark_node)
> >         {
> > -         cl_target_option_restore (&global_options,
> > +         cl_target_option_restore (&global_options, &global_options_set,
> >                                     TREE_TARGET_OPTION (prev_tree));
> >           return false;
> >         }
> > --- gcc/config/i386/i386-options.c.jj 2020-08-27 11:34:53.690525016 +0200
> > +++ gcc/config/i386/i386-options.c    2020-09-11 17:03:12.563313262 +0200
> > @@ -627,7 +627,8 @@ ix86_debug_options (void)
> >
> >  void
> >  ix86_function_specific_save (struct cl_target_option *ptr,
> > -                          struct gcc_options *opts)
> > +                          struct gcc_options *opts,
> > +                          struct gcc_options */* opts_set */)
> >  {
> >    ptr->arch = ix86_arch;
> >    ptr->schedule = ix86_schedule;
> > @@ -754,6 +755,7 @@ set_ix86_tune_features (struct gcc_optio
> >
> >  void
> >  ix86_function_specific_restore (struct gcc_options *opts,
> > +                             struct gcc_options */* opts_set */,
> >                               struct cl_target_option *ptr)
> >  {
> >    enum processor_type old_tune = ix86_tune;
> > @@ -1356,7 +1358,7 @@ ix86_valid_target_attribute_tree (tree f
> >
> >        /* Save the current options unless we are validating options for
> >        #pragma.  */
> > -      t = build_target_option_node (opts);
> > +      t = build_target_option_node (opts, opts_set);
> >
> >        opts->x_ix86_arch_string = orig_arch_string;
> >        opts->x_ix86_tune_string = orig_tune_string;
> > @@ -1377,7 +1379,7 @@ ix86_valid_target_attribute_p (tree fnde
> >                              tree args,
> >                              int flags)
> >  {
> > -  struct gcc_options func_options;
> > +  struct gcc_options func_options, func_options_set;
> >    tree new_target, new_optimize;
> >    bool ret = true;
> >
> > @@ -1389,7 +1391,8 @@ ix86_valid_target_attribute_p (tree fnde
> >        && strcmp (TREE_STRING_POINTER (TREE_VALUE (args)), "default") == 0)
> >      return true;
> >
> > -  tree old_optimize = build_optimization_node (&global_options);
> > +  tree old_optimize = build_optimization_node (&global_options,
> > +                                            &global_options_set);
> >
> >    /* Get the optimization options of the current function.  */
> >    tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
> > @@ -1401,21 +1404,22 @@ ix86_valid_target_attribute_p (tree fnde
> >    memset (&func_options, 0, sizeof (func_options));
> >    init_options_struct (&func_options, NULL);
> >    lang_hooks.init_options_struct (&func_options);
> > -
> > -  cl_optimization_restore (&func_options,
> > +  memset (&func_options_set, 0, sizeof (func_options_set));
> > +
> > +  cl_optimization_restore (&func_options, &func_options_set,
> >                          TREE_OPTIMIZATION (func_optimize));
> >
> >    /* Initialize func_options to the default before its target options can
> >       be set.  */
> > -  cl_target_option_restore (&func_options,
> > +  cl_target_option_restore (&func_options, &func_options_set,
> >                           TREE_TARGET_OPTION (target_option_default_node));
> >
> >    /* FLAGS == 1 is used for target_clones attribute.  */
> >    new_target
> >      = ix86_valid_target_attribute_tree (fndecl, args, &func_options,
> > -                                     &global_options_set, flags == 1);
> > +                                     &func_options_set, flags == 1);
> >
> > -  new_optimize = build_optimization_node (&func_options);
> > +  new_optimize = build_optimization_node (&func_options, &func_options_set);
> >
> >    if (new_target == error_mark_node)
> >      ret = false;
> > @@ -2954,7 +2958,7 @@ ix86_option_override_internal (bool main
> >       options.  */
> >    if (main_args_p)
> >      target_option_default_node = target_option_current_node
> > -      = build_target_option_node (opts);
> > +      = build_target_option_node (opts, opts_set);
> >
> >    if (opts->x_flag_cf_protection != CF_NONE)
> >      opts->x_flag_cf_protection
> > @@ -2991,7 +2995,8 @@ void
> >  ix86_reset_previous_fndecl (void)
> >  {
> >    tree new_tree = target_option_current_node;
> > -  cl_target_option_restore (&global_options, TREE_TARGET_OPTION (new_tree));
> > +  cl_target_option_restore (&global_options, &global_options_set,
> > +                         TREE_TARGET_OPTION (new_tree));
> >    if (TREE_TARGET_GLOBALS (new_tree))
> >      restore_target_globals (TREE_TARGET_GLOBALS (new_tree));
> >    else if (new_tree == target_option_default_node)
> > @@ -3250,7 +3255,8 @@ ix86_set_current_function (tree fndecl)
> >
> >    if (old_tree != new_tree)
> >      {
> > -      cl_target_option_restore (&global_options, TREE_TARGET_OPTION (new_tree));
> > +      cl_target_option_restore (&global_options, &global_options_set,
> > +                             TREE_TARGET_OPTION (new_tree));
> >        if (TREE_TARGET_GLOBALS (new_tree))
> >       restore_target_globals (TREE_TARGET_GLOBALS (new_tree));
> >        else if (new_tree == target_option_default_node)
> > --- gcc/config/i386/i386-options.h.jj 2020-01-12 11:54:36.324414751 +0100
> > +++ gcc/config/i386/i386-options.h    2020-09-11 17:01:12.493080892 +0200
> > @@ -70,8 +70,10 @@ extern const char *stringop_alg_names[];
> >
> >  void ix86_add_new_builtins (HOST_WIDE_INT isa, HOST_WIDE_INT isa2);
> >  void ix86_function_specific_save (struct cl_target_option *,
> > -                               struct gcc_options *opts);
> > +                               struct gcc_options *opts,
> > +                               struct gcc_options *opts_set);
> >  void ix86_function_specific_restore (struct gcc_options *opts,
> > +                                  struct gcc_options *opts_set,
> >                                    struct cl_target_option *);
> >  void ix86_function_specific_post_stream_in (struct cl_target_option *);
> >  void ix86_function_specific_print (FILE *, int,
> > --- gcc/config/nios2/nios2.c.jj       2020-01-12 11:54:36.374413997 +0100
> > +++ gcc/config/nios2/nios2.c  2020-09-11 17:05:11.456562954 +0200
> > @@ -1448,7 +1448,7 @@ nios2_option_override (void)
> >    /* Save the initial options in case the user does function specific
> >       options.  */
> >    target_option_default_node = target_option_current_node
> > -    = build_target_option_node (&global_options);
> > +    = build_target_option_node (&global_options, &global_options_set);
> >  }
> >
> >
> > @@ -4137,7 +4137,8 @@ nios2_deregister_custom_code (unsigned i
> >
> >  static void
> >  nios2_option_save (struct cl_target_option *ptr,
> > -                struct gcc_options *opts ATTRIBUTE_UNUSED)
> > +                struct gcc_options *opts ATTRIBUTE_UNUSED,
> > +                struct gcc_options *opts_set ATTRIBUTE_UNUSED)
> >  {
> >    unsigned int i;
> >    for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
> > @@ -4150,6 +4151,7 @@ nios2_option_save (struct cl_target_opti
> >
> >  static void
> >  nios2_option_restore (struct gcc_options *opts ATTRIBUTE_UNUSED,
> > +                   struct gcc_options *opts_set ATTRIBUTE_UNUSED,
> >                     struct cl_target_option *ptr)
> >  {
> >    unsigned int i;
> > @@ -4310,7 +4312,7 @@ nios2_valid_target_attribute_tree (tree
> >    if (!nios2_valid_target_attribute_rec (args))
> >      return NULL_TREE;
> >    nios2_custom_check_insns ();
> > -  return build_target_option_node (&global_options);
> > +  return build_target_option_node (&global_options, &global_options_set);
> >  }
> >
> >  /* Hook to validate attribute((target("string"))).  */
> > @@ -4321,21 +4323,22 @@ nios2_valid_target_attribute_p (tree fnd
> >  {
> >    struct cl_target_option cur_target;
> >    bool ret = true;
> > -  tree old_optimize = build_optimization_node (&global_options);
> > +  tree old_optimize
> > +    = build_optimization_node (&global_options, &global_options_set);
> >    tree new_target, new_optimize;
> >    tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
> >
> >    /* 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,
> > +    cl_optimization_restore (&global_options, &global_options_set,
> >                            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);
> > +  cl_target_option_save (&cur_target, &global_options, &global_options_set);
> >    new_target = nios2_valid_target_attribute_tree (args);
> > -  new_optimize = build_optimization_node (&global_options);
> > +  new_optimize = build_optimization_node (&global_options, &global_options_set);
> >
> >    if (!new_target)
> >      ret = false;
> > @@ -4348,10 +4351,10 @@ nios2_valid_target_attribute_p (tree fnd
> >       DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize;
> >      }
> >
> > -  cl_target_option_restore (&global_options, &cur_target);
> > +  cl_target_option_restore (&global_options, &global_options_set, &cur_target);
> >
> >    if (old_optimize != new_optimize)
> > -    cl_optimization_restore (&global_options,
> > +    cl_optimization_restore (&global_options, &global_options_set,
> >                            TREE_OPTIMIZATION (old_optimize));
> >    return ret;
> >  }
> > @@ -4381,7 +4384,7 @@ nios2_set_current_function (tree fndecl)
> >
> >        else if (new_tree)
> >       {
> > -       cl_target_option_restore (&global_options,
> > +       cl_target_option_restore (&global_options, &global_options_set,
> >                                   TREE_TARGET_OPTION (new_tree));
> >         target_reinit ();
> >       }
> > @@ -4391,7 +4394,7 @@ nios2_set_current_function (tree fndecl)
> >         struct cl_target_option *def
> >           = TREE_TARGET_OPTION (target_option_current_node);
> >
> > -       cl_target_option_restore (&global_options, def);
> > +       cl_target_option_restore (&global_options, &global_options_set, def);
> >         target_reinit ();
> >       }
> >      }
> > @@ -4409,7 +4412,7 @@ nios2_pragma_target_parse (tree args, tr
> >        cur_tree = ((pop_target)
> >                 ? pop_target
> >                 : target_option_default_node);
> > -      cl_target_option_restore (&global_options,
> > +      cl_target_option_restore (&global_options, &global_options_set,
> >                               TREE_TARGET_OPTION (cur_tree));
> >      }
> >    else
> > --- gcc/config/pru/pru.c.jj   2020-07-28 15:39:09.749759789 +0200
> > +++ gcc/config/pru/pru.c      2020-09-11 16:48:26.048374673 +0200
> > @@ -621,7 +621,7 @@ pru_option_override (void)
> >    /* Save the initial options in case the user does function specific
> >       options.  */
> >    target_option_default_node = target_option_current_node
> > -    = build_target_option_node (&global_options);
> > +    = build_target_option_node (&global_options, &global_options_set);
> >
> >    /* Due to difficulties in implementing the TI ABI with GCC,
> >       at least check and error-out if GCC cannot compile a
> > @@ -2848,7 +2848,7 @@ pru_set_current_function (tree fndecl)
> >
> >        else if (new_tree)
> >       {
> > -       cl_target_option_restore (&global_options,
> > +       cl_target_option_restore (&global_options, &global_options_set,
> >                                   TREE_TARGET_OPTION (new_tree));
> >         target_reinit ();
> >       }
> > @@ -2858,7 +2858,7 @@ pru_set_current_function (tree fndecl)
> >         struct cl_target_option *def
> >           = TREE_TARGET_OPTION (target_option_current_node);
> >
> > -       cl_target_option_restore (&global_options, def);
> > +       cl_target_option_restore (&global_options, &global_options_set, def);
> >         target_reinit ();
> >       }
> >      }
> > --- gcc/config/rs6000/rs6000.c.jj     2020-08-30 14:05:37.697594792 +0200
> > +++ gcc/config/rs6000/rs6000.c        2020-09-11 17:48:46.870240459 +0200
> > @@ -2393,7 +2393,7 @@ rs6000_debug_reg_global (void)
> >    else
> >      fprintf (stderr, DEBUG_FMT_S, "tune", "<none>");
> >
> > -  cl_target_option_save (&cl_opts, &global_options);
> > +  cl_target_option_save (&cl_opts, &global_options, &global_options_set);
> >    rs6000_print_isa_options (stderr, 0, "rs6000_isa_flags",
> >                           rs6000_isa_flags);
> >
> > @@ -4768,7 +4768,7 @@ rs6000_option_override_internal (bool gl
> >    /* 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 (&global_options);
> > +      = build_target_option_node (&global_options, &global_options_set);
> >
> >    /* 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).  */
> > @@ -23616,18 +23616,19 @@ rs6000_valid_attribute_p (tree fndecl,
> >        && strcmp (TREE_STRING_POINTER (TREE_VALUE (args)), "default") == 0)
> >      return true;
> >
> > -  old_optimize = build_optimization_node (&global_options);
> > +  old_optimize = build_optimization_node (&global_options,
> > +                                       &global_options_set);
> >    func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
> >
> >    /* 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,
> > +    cl_optimization_restore (&global_options, &global_options_set,
> >                            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);
> > +  cl_target_option_save (&cur_target, &global_options, &global_options_set);
> >    rs6000_cpu_index = rs6000_tune_index = -1;
> >    ret = rs6000_inner_target_options (args, true);
> >
> > @@ -23635,12 +23636,14 @@ rs6000_valid_attribute_p (tree fndecl,
> >    if (ret)
> >      {
> >        ret = rs6000_option_override_internal (false);
> > -      new_target = build_target_option_node (&global_options);
> > +      new_target = build_target_option_node (&global_options,
> > +                                          &global_options_set);
> >      }
> >    else
> >      new_target = NULL;
> >
> > -  new_optimize = build_optimization_node (&global_options);
> > +  new_optimize = build_optimization_node (&global_options,
> > +                                       &global_options_set);
> >
> >    if (!new_target)
> >      ret = false;
> > @@ -23653,10 +23656,10 @@ rs6000_valid_attribute_p (tree fndecl,
> >       DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize;
> >      }
> >
> > -  cl_target_option_restore (&global_options, &cur_target);
> > +  cl_target_option_restore (&global_options, &global_options_set, &cur_target);
> >
> >    if (old_optimize != new_optimize)
> > -    cl_optimization_restore (&global_options,
> > +    cl_optimization_restore (&global_options, &global_options_set,
> >                            TREE_OPTIMIZATION (old_optimize));
> >
> >    return ret;
> > @@ -23670,7 +23673,8 @@ rs6000_valid_attribute_p (tree fndecl,
> >  bool
> >  rs6000_pragma_target_parse (tree args, tree pop_target)
> >  {
> > -  tree prev_tree = build_target_option_node (&global_options);
> > +  tree prev_tree = build_target_option_node (&global_options,
> > +                                          &global_options_set);
> >    tree cur_tree;
> >    struct cl_target_option *prev_opt, *cur_opt;
> >    HOST_WIDE_INT prev_flags, cur_flags, diff_flags;
> > @@ -23699,7 +23703,7 @@ rs6000_pragma_target_parse (tree args, t
> >        cur_tree = ((pop_target)
> >                 ? pop_target
> >                 : target_option_default_node);
> > -      cl_target_option_restore (&global_options,
> > +      cl_target_option_restore (&global_options, &global_options_set,
> >                               TREE_TARGET_OPTION (cur_tree));
> >      }
> >    else
> > @@ -23707,7 +23711,8 @@ rs6000_pragma_target_parse (tree args, t
> >        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 (&global_options))
> > +       || (cur_tree = build_target_option_node (&global_options,
> > +                                                &global_options_set))
> >            == NULL_TREE)
> >       {
> >         if (TARGET_DEBUG_BUILTIN || TARGET_DEBUG_TARGET)
> > @@ -23762,7 +23767,8 @@ static GTY(()) tree rs6000_previous_fnde
> >  void
> >  rs6000_activate_target_options (tree new_tree)
> >  {
> > -  cl_target_option_restore (&global_options, TREE_TARGET_OPTION (new_tree));
> > +  cl_target_option_restore (&global_options, &global_options_set,
> > +                         TREE_TARGET_OPTION (new_tree));
> >    if (TREE_TARGET_GLOBALS (new_tree))
> >      restore_target_globals (TREE_TARGET_GLOBALS (new_tree));
> >    else if (new_tree == target_option_default_node)
> > @@ -23853,7 +23859,8 @@ rs6000_set_current_function (tree fndecl
> >
> >  static void
> >  rs6000_function_specific_save (struct cl_target_option *ptr,
> > -                            struct gcc_options *opts)
> > +                            struct gcc_options *opts,
> > +                            struct gcc_options */* opts_set */)
> >  {
> >    ptr->x_rs6000_isa_flags = opts->x_rs6000_isa_flags;
> >    ptr->x_rs6000_isa_flags_explicit = opts->x_rs6000_isa_flags_explicit;
> > @@ -23863,6 +23870,7 @@ rs6000_function_specific_save (struct cl
> >
> >  static void
> >  rs6000_function_specific_restore (struct gcc_options *opts,
> > +                               struct gcc_options */* opts_set */,
> >                                 struct cl_target_option *ptr)
> >
> >  {
> > --- gcc/config/s390/s390.c.jj 2020-08-12 12:45:58.247689146 +0200
> > +++ gcc/config/s390/s390.c    2020-09-11 17:55:21.994465519 +0200
> > @@ -15207,6 +15207,7 @@ s390_loop_unroll_adjust (unsigned nunrol
> >
> >  static void
> >  s390_function_specific_restore (struct gcc_options *opts,
> > +                             struct gcc_options */* opts_set */,
> >                               struct cl_target_option *ptr ATTRIBUTE_UNUSED)
> >  {
> >    opts->x_s390_cost_pointer = (long)processor_table[opts->x_s390_tune].cost;
> > @@ -15230,7 +15231,7 @@ s390_override_options_after_change (void
> >
> >  static void
> >  s390_option_override_internal (struct gcc_options *opts,
> > -                            const struct gcc_options *opts_set)
> > +                            struct gcc_options *opts_set)
> >  {
> >    /* Architecture mode defaults according to ABI.  */
> >    if (!(opts_set->x_target_flags & MASK_ZARCH))
> > @@ -15444,7 +15445,7 @@ s390_option_override_internal (struct gc
> >
> >    /* Call target specific restore function to do post-init work.  At the moment,
> >       this just sets opts->x_s390_cost_pointer.  */
> > -  s390_function_specific_restore (opts, NULL);
> > +  s390_function_specific_restore (opts, opts_set, NULL);
> >
> >    /* Check whether -mfentry is supported. It cannot be used in 31-bit mode,
> >       because 31-bit PLT stubs assume that %r12 contains GOT address, which is
> > @@ -15513,7 +15514,8 @@ s390_option_override (void)
> >
> >    /* Save the initial options in case the user does function specific
> >       options.  */
> > -  target_option_default_node = build_target_option_node (&global_options);
> > +  target_option_default_node
> > +    = build_target_option_node (&global_options, &global_options_set);
> >    target_option_current_node = target_option_default_node;
> >
> >    /* This cannot reside in s390_option_optimization_table since HAVE_prefetch
> > @@ -15803,7 +15805,7 @@ s390_valid_target_attribute_tree (tree a
> >        s390_option_override_internal (opts, &new_opts_set);
> >        /* Save the current options unless we are validating options for
> >        #pragma.  */
> > -      t = build_target_option_node (opts);
> > +      t = build_target_option_node (opts, &new_opts_set);
> >      }
> >    return t;
> >  }
> > @@ -15816,7 +15818,7 @@ s390_valid_target_attribute_p (tree fnde
> >                              tree args,
> >                              int ARG_UNUSED (flags))
> >  {
> > -  struct gcc_options func_options;
> > +  struct gcc_options func_options, func_options_set;
> >    tree new_target, new_optimize;
> >    bool ret = true;
> >
> > @@ -15828,7 +15830,8 @@ s390_valid_target_attribute_p (tree fnde
> >        && strcmp (TREE_STRING_POINTER (TREE_VALUE (args)), "default") == 0)
> >      return true;
> >
> > -  tree old_optimize = build_optimization_node (&global_options);
> > +  tree old_optimize
> > +    = build_optimization_node (&global_options, &global_options_set);
> >
> >    /* Get the optimization options of the current function.  */
> >    tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
> > @@ -15840,19 +15843,21 @@ s390_valid_target_attribute_p (tree fnde
> >    memset (&func_options, 0, sizeof (func_options));
> >    init_options_struct (&func_options, NULL);
> >    lang_hooks.init_options_struct (&func_options);
> > +  memset (&func_options_set, 0, sizeof (func_options_set));
> >
> > -  cl_optimization_restore (&func_options, TREE_OPTIMIZATION (func_optimize));
> > +  cl_optimization_restore (&func_options, &func_options_set,
> > +                        TREE_OPTIMIZATION (func_optimize));
> >
> >    /* Initialize func_options to the default before its target options can
> >       be set.  */
> > -  cl_target_option_restore (&func_options,
> > +  cl_target_option_restore (&func_options, &func_options_set,
> >                           TREE_TARGET_OPTION (target_option_default_node));
> >
> >    new_target = s390_valid_target_attribute_tree (args, &func_options,
> >                                                &global_options_set,
> >                                                (args ==
> >                                                 current_target_pragma));
> > -  new_optimize = build_optimization_node (&func_options);
> > +  new_optimize = build_optimization_node (&func_options, &func_options_set);
> >    if (new_target == error_mark_node)
> >      ret = false;
> >    else if (fndecl && new_target)
> > @@ -15990,7 +15995,8 @@ s390_indirect_branch_settings (tree fnde
> >  void
> >  s390_activate_target_options (tree new_tree)
> >  {
> > -  cl_target_option_restore (&global_options, TREE_TARGET_OPTION (new_tree));
> > +  cl_target_option_restore (&global_options, &global_options_set,
> > +                         TREE_TARGET_OPTION (new_tree));
> >    if (TREE_TARGET_GLOBALS (new_tree))
> >      restore_target_globals (TREE_TARGET_GLOBALS (new_tree));
> >    else if (new_tree == target_option_default_node)
> > --- gcc/config/s390/s390-c.c.jj       2020-01-12 11:54:36.409413469 +0100
> > +++ gcc/config/s390/s390-c.c  2020-09-11 17:50:54.169379921 +0200
> > @@ -388,7 +388,7 @@ s390_cpu_cpp_builtins (cpp_reader *pfile
> >      cpp_define (pfile, "__s390x__");
> >    if (TARGET_LONG_DOUBLE_128)
> >      cpp_define (pfile, "__LONG_DOUBLE_128__");
> > -  cl_target_option_save (&opts, &global_options);
> > +  cl_target_option_save (&opts, &global_options, &global_options_set);
> >    s390_cpu_cpp_builtins_internal (pfile, &opts, NULL);
> >  }
> >
> > @@ -400,7 +400,8 @@ s390_cpu_cpp_builtins (cpp_reader *pfile
> >  static bool
> >  s390_pragma_target_parse (tree args, tree pop_target)
> >  {
> > -  tree prev_tree = build_target_option_node (&global_options);
> > +  tree prev_tree = build_target_option_node (&global_options,
> > +                                          &global_options_set);
> >    tree cur_tree;
> >
> >    if (! args)
> > @@ -411,7 +412,7 @@ s390_pragma_target_parse (tree args, tre
> >                                                  &global_options_set, true);
> >        if (!cur_tree || cur_tree == error_mark_node)
> >       {
> > -       cl_target_option_restore (&global_options,
> > +       cl_target_option_restore (&global_options, &global_options_set,
> >                                   TREE_TARGET_OPTION (prev_tree));
> >         return false;
> >       }
> >
> >
> >       Jakub
> >
> >
>
> --
> Richard Biener <rguenther@suse.de>
> SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
> Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)

  reply	other threads:[~2020-09-14  8:06 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-08  8:45 [PATCH] arm: Fix up arm_override_options_after_change [PR96939] Jakub Jelinek
2020-09-08 22:01 ` Jeff Law
2020-09-10  8:51 ` [PATCH] arm: Fix up arm_override_options_after_change_1 Jakub Jelinek
2020-09-10 14:11   ` Kyrylo Tkachov
2020-09-10 14:58     ` Jeff Law
2020-09-10 15:01     ` Jakub Jelinek
2020-09-10 15:04       ` Kyrylo Tkachov
2020-09-11  7:46 ` [PATCH] arm: Fix up arm_override_options_after_change [PR96939] Christophe Lyon
2020-09-11  9:29   ` Jakub Jelinek
2020-09-13  8:29     ` [PATCH] options: Save and restore opts_set for Optimization and Target options Jakub Jelinek
2020-09-14  6:32       ` Richard Biener
2020-09-14  8:06         ` Christophe Lyon [this message]
2020-09-28 19:50       ` Stefan Schulze Frielinghaus
2020-09-28 19:58         ` Jakub Jelinek
2020-09-30  9:32         ` Jakub Jelinek
2020-09-30 11:21           ` Stefan Schulze Frielinghaus
2020-09-30 11:39             ` Jakub Jelinek
2020-09-30 13:24               ` Stefan Schulze Frielinghaus
2020-10-02  8:46                 ` Jakub Jelinek
2020-10-02 14:21                   ` Stefan Schulze Frielinghaus
2020-10-03  8:41                     ` Jakub Jelinek
2020-10-03 18:02                       ` Richard Biener
2020-10-04  7:13                   ` Andreas Schwab
2020-10-04 19:16                     ` Jakub Jelinek
2020-10-05  7:08                       ` Jakub Jelinek
2020-10-05  7:10                         ` Richard Biener
2020-10-06  9:28                       ` Andreas Schwab
2020-10-06 13:20                         ` [PATCH] options: Avoid unused variable mask warning [PR97305] Jakub Jelinek
2020-10-06 13:32                           ` Richard Biener

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAKdteObZs=t1FLs4A3tR7FEq7XQ6vZJQHfswyEBzVoDvjy6h6Q@mail.gmail.com' \
    --to=christophe.lyon@linaro.org \
    --cc=Richard.Earnshaw@foss.arm.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jakub@redhat.com \
    --cc=joseph@codesourcery.com \
    --cc=rguenther@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).