public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] arm: Fix up arm_override_options_after_change [PR96939]
@ 2020-09-08  8:45 Jakub Jelinek
  2020-09-08 22:01 ` Jeff Law
                   ` (2 more replies)
  0 siblings, 3 replies; 29+ messages in thread
From: Jakub Jelinek @ 2020-09-08  8:45 UTC (permalink / raw)
  To: Richard Earnshaw, Kyrylo Tkachov; +Cc: gcc-patches

Hi!

As mentioned in the PR, the testcase fails to link, because when set_cfun is
being called on the crc function, arm_override_options_after_change is
called from set_cfun -> invoke_set_current_function_hook:
      /* Change optimization options if needed.  */
      if (optimization_current_node != opts)
        {
          optimization_current_node = opts;
          cl_optimization_restore (&global_options, TREE_OPTIMIZATION (opts));
        }
and at that point target_option_default_node actually matches even the
current state of options, so this means armv7 (or whatever) arch is set as
arm_active_target, then
      targetm.set_current_function (fndecl);
is called later in that function, which because the crc function's
DECL_FUNCTION_SPECIFIC_TARGET is different from the current one will do:
  cl_target_option_restore (&global_options, TREE_TARGET_OPTION (new_tree));
which calls arm_option_restore and sets arm_active_target to armv8-a+crc
(so far so good).
Later arm_set_current_function calls:
  save_restore_target_globals (new_tree);
which in this case calls:
      /* Call target_reinit and save the state for TARGET_GLOBALS.  */
      TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts ();
which because optimization_current_node != optimization_default_node
(the testcase is LTO, so all functions have their
DECL_FUNCTION_SPECIFIC_TARGET and TREE_OPTIMIZATION nodes) will call:
      cl_optimization_restore
        (&global_options,
         TREE_OPTIMIZATION (optimization_default_node));
and
      cl_optimization_restore (&global_options,
                               TREE_OPTIMIZATION (opts));
The problem is that these call arm_override_options_after_change again,
and that one uses the target_option_default_node as what to set the
arm_active_target to (i.e. back to armv7 or whatever, but not to the
armv8-a+crc that should be the active target for the crc function).
That means we then error on the builtin call in that function.

Now, the targetm.override_options_after_change hook is called always at the
end of cl_optimization_restore, i.e. when we change the Optimization marked
generic options.  So it seems unnecessary to call arm_configure_build_target
at that point (nothing it depends on changed), and additionally incorrect
(because it uses the target_option_default_node, rather than the current
set of options; we'd need to revert
https://gcc.gnu.org/legacy-ml/gcc-patches/2016-12/msg01390.html
otherwise so that it works again with global_options otherwise).
The options that arm_configure_build_target cares about will change only
during option parsing (which is where it is called already), or during
arm_set_current_function, where it is done during the
cl_target_option_restore.
Now, arm_override_options_after_change_1 wants to adjust the
str_align_functions, which depends on the current Optimization options (e.g.
optimize_size and flag_align_options and str_align_functions) as well as
the target options target_flags, so IMHO needs to be called both
when the Optimization options (possibly) change, i.e. from
the targetm.override_options_after_change hook, and from when the target
options change (set_current_function hook).

Bootstrapped/regtested on armv7hl-linux-gnueabi, ok for trunk?

Looking further at arm_override_options_after_change_1, it also seems to be
incorrect, rather than testing
!opts->x_str_align_functions
it should be really testing
!opts_set->x_str_align_functions
and get &global_options_set or similar passed to it as additional opts_set
argument.  That is because otherwise the decision will be sticky, while it
should be done whenever use provided -falign-functions but didn't provide
-falign-functions= (either on the command line, or through optimize
attribute or pragma).

2020-09-08  Jakub Jelinek  <jakub@redhat.com>

	PR target/96939
	* config/arm/arm.c (arm_override_options_after_change): Don't call
	arm_configure_build_target here.
	(arm_set_current_function): Call arm_override_options_after_change_1
	at the end.

	* gcc.target/arm/lto/pr96939_0.c: New test.
	* gcc.target/arm/lto/pr96939_1.c: New file.

--- gcc/config/arm/arm.c.jj	2020-07-30 15:04:38.136293101 +0200
+++ gcc/config/arm/arm.c	2020-09-07 10:43:54.809561852 +0200
@@ -3037,10 +3037,6 @@ arm_override_options_after_change_1 (str
 static void
 arm_override_options_after_change (void)
 {
-  arm_configure_build_target (&arm_active_target,
-			      TREE_TARGET_OPTION (target_option_default_node),
-			      &global_options_set, false);
-
   arm_override_options_after_change_1 (&global_options);
 }
 
@@ -32338,6 +32334,8 @@ arm_set_current_function (tree fndecl)
   cl_target_option_restore (&global_options, TREE_TARGET_OPTION (new_tree));
 
   save_restore_target_globals (new_tree);
+
+  arm_override_options_after_change_1 (&global_options);
 }
 
 /* Implement TARGET_OPTION_PRINT.  */
--- gcc/testsuite/gcc.target/arm/lto/pr96939_0.c.jj	2020-09-07 11:26:45.909937609 +0200
+++ gcc/testsuite/gcc.target/arm/lto/pr96939_0.c	2020-09-07 11:29:18.722706535 +0200
@@ -0,0 +1,15 @@
+/* PR target/96939 */
+/* { dg-lto-do link } */
+/* { dg-require-effective-target arm_arch_v8a_ok } */
+/* { dg-lto-options { { -flto -O2 } } } */
+
+extern unsigned crc (unsigned, const void *);
+typedef unsigned (*fnptr) (unsigned, const void *);
+volatile fnptr fn;
+
+int
+main ()
+{
+  fn = crc;
+  return 0;
+}
--- gcc/testsuite/gcc.target/arm/lto/pr96939_1.c.jj	2020-09-07 11:26:49.365887153 +0200
+++ gcc/testsuite/gcc.target/arm/lto/pr96939_1.c	2020-09-07 11:25:13.885281180 +0200
@@ -0,0 +1,10 @@
+/* PR target/96939 */
+/* { dg-options "-march=armv8-a+crc" } */
+
+#include <arm_acle.h>
+
+unsigned
+crc (unsigned x, const void *y)
+{
+  return __crc32cw (x, *(unsigned *) y);
+}

	Jakub


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] arm: Fix up arm_override_options_after_change [PR96939]
  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-11  7:46 ` [PATCH] arm: Fix up arm_override_options_after_change [PR96939] Christophe Lyon
  2 siblings, 0 replies; 29+ messages in thread
From: Jeff Law @ 2020-09-08 22:01 UTC (permalink / raw)
  To: Jakub Jelinek, Richard Earnshaw, Kyrylo Tkachov; +Cc: gcc-patches

On Tue, 2020-09-08 at 10:45 +0200, Jakub Jelinek via Gcc-patches wrote:
> Hi!
> 
> As mentioned in the PR, the testcase fails to link, because when set_cfun is
> being called on the crc function, arm_override_options_after_change is
> called from set_cfun -> invoke_set_current_function_hook:
>       /* Change optimization options if needed.  */
>       if (optimization_current_node != opts)
>         {
>           optimization_current_node = opts;
>           cl_optimization_restore (&global_options, TREE_OPTIMIZATION (opts));
>         }
> and at that point target_option_default_node actually matches even the
> current state of options, so this means armv7 (or whatever) arch is set as
> arm_active_target, then
>       targetm.set_current_function (fndecl);
> is called later in that function, which because the crc function's
> DECL_FUNCTION_SPECIFIC_TARGET is different from the current one will do:
>   cl_target_option_restore (&global_options, TREE_TARGET_OPTION (new_tree));
> which calls arm_option_restore and sets arm_active_target to armv8-a+crc
> (so far so good).
> Later arm_set_current_function calls:
>   save_restore_target_globals (new_tree);
> which in this case calls:
>       /* Call target_reinit and save the state for TARGET_GLOBALS.  */
>       TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts ();
> which because optimization_current_node != optimization_default_node
> (the testcase is LTO, so all functions have their
> DECL_FUNCTION_SPECIFIC_TARGET and TREE_OPTIMIZATION nodes) will call:
>       cl_optimization_restore
>         (&global_options,
>          TREE_OPTIMIZATION (optimization_default_node));
> and
>       cl_optimization_restore (&global_options,
>                                TREE_OPTIMIZATION (opts));
> The problem is that these call arm_override_options_after_change again,
> and that one uses the target_option_default_node as what to set the
> arm_active_target to (i.e. back to armv7 or whatever, but not to the
> armv8-a+crc that should be the active target for the crc function).
> That means we then error on the builtin call in that function.
> 
> Now, the targetm.override_options_after_change hook is called always at the
> end of cl_optimization_restore, i.e. when we change the Optimization marked
> generic options.  So it seems unnecessary to call arm_configure_build_target
> at that point (nothing it depends on changed), and additionally incorrect
> (because it uses the target_option_default_node, rather than the current
> set of options; we'd need to revert
> https://gcc.gnu.org/legacy-ml/gcc-patches/2016-12/msg01390.html
> otherwise so that it works again with global_options otherwise).
> The options that arm_configure_build_target cares about will change only
> during option parsing (which is where it is called already), or during
> arm_set_current_function, where it is done during the
> cl_target_option_restore.
> Now, arm_override_options_after_change_1 wants to adjust the
> str_align_functions, which depends on the current Optimization options (e.g.
> optimize_size and flag_align_options and str_align_functions) as well as
> the target options target_flags, so IMHO needs to be called both
> when the Optimization options (possibly) change, i.e. from
> the targetm.override_options_after_change hook, and from when the target
> options change (set_current_function hook).
> 
> Bootstrapped/regtested on armv7hl-linux-gnueabi, ok for trunk?
> 
> Looking further at arm_override_options_after_change_1, it also seems to be
> incorrect, rather than testing
> !opts->x_str_align_functions
> it should be really testing
> !opts_set->x_str_align_functions
> and get &global_options_set or similar passed to it as additional opts_set
> argument.  That is because otherwise the decision will be sticky, while it
> should be done whenever use provided -falign-functions but didn't provide
> -falign-functions= (either on the command line, or through optimize
> attribute or pragma).
> 
> 2020-09-08  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR target/96939
> 	* config/arm/arm.c (arm_override_options_after_change): Don't call
> 	arm_configure_build_target here.
> 	(arm_set_current_function): Call arm_override_options_after_change_1
> 	at the end.
> 
> 	* gcc.target/arm/lto/pr96939_0.c: New test.
> 	* gcc.target/arm/lto/pr96939_1.c: New file.
Any objection if I pull this into the Fedora tree and build a new GCC at some
point in the relatively new future (once approved).  Similarly for your lto vs
linenumber patch?

Jeff


^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH] arm: Fix up arm_override_options_after_change_1
  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 ` Jakub Jelinek
  2020-09-10 14:11   ` Kyrylo Tkachov
  2020-09-11  7:46 ` [PATCH] arm: Fix up arm_override_options_after_change [PR96939] Christophe Lyon
  2 siblings, 1 reply; 29+ messages in thread
From: Jakub Jelinek @ 2020-09-10  8:51 UTC (permalink / raw)
  To: Richard Earnshaw, Kyrylo Tkachov, gcc-patches

On Tue, Sep 08, 2020 at 10:45:12AM +0200, Jakub Jelinek via Gcc-patches wrote:
> Looking further at arm_override_options_after_change_1, it also seems to be
> incorrect, rather than testing
> !opts->x_str_align_functions
> it should be really testing
> !opts_set->x_str_align_functions
> and get &global_options_set or similar passed to it as additional opts_set
> argument.  That is because otherwise the decision will be sticky, while it
> should be done whenever use provided -falign-functions but didn't provide
> -falign-functions= (either on the command line, or through optimize
> attribute or pragma).

Here is a fix for that (incremental change on top of the previous patch).
Bootstrapped/regtested on armv7hl-linux-gnueabi, ok for trunk?

2020-09-10  Jakub Jelinek  <jakub@redhat.com>

	* config/arm/arm.c (arm_override_options_after_change_1): Add opts_set
	argument, test opts_set->x_str_align_functions rather than
	opts->x_str_align_functions.
	(arm_override_options_after_change, arm_option_override_internal,
	arm_set_current_function): Adjust callers.

--- gcc/config/arm/arm.c.jj	2020-09-09 09:19:42.911419411 +0200
+++ gcc/config/arm/arm.c	2020-09-09 09:28:02.392897384 +0200
@@ -3024,10 +3024,11 @@ static GTY(()) bool thumb_flipper;
 static GTY(()) tree init_optimize;
 
 static void
-arm_override_options_after_change_1 (struct gcc_options *opts)
+arm_override_options_after_change_1 (struct gcc_options *opts,
+				     struct gcc_options *opts_set)
 {
   /* -falign-functions without argument: supply one.  */
-  if (opts->x_flag_align_functions && !opts->x_str_align_functions)
+  if (opts->x_flag_align_functions && !opts_set->x_str_align_functions)
     opts->x_str_align_functions = TARGET_THUMB_P (opts->x_target_flags)
       && opts->x_optimize_size ? "2" : "4";
 }
@@ -3037,7 +3038,7 @@ arm_override_options_after_change_1 (str
 static void
 arm_override_options_after_change (void)
 {
-  arm_override_options_after_change_1 (&global_options);
+  arm_override_options_after_change_1 (&global_options, &global_options_set);
 }
 
 /* Implement TARGET_OPTION_SAVE.  */
@@ -3065,7 +3066,7 @@ static void
 arm_option_override_internal (struct gcc_options *opts,
 			      struct gcc_options *opts_set)
 {
-  arm_override_options_after_change_1 (opts);
+  arm_override_options_after_change_1 (opts, opts_set);
 
   if (TARGET_INTERWORK && !bitmap_bit_p (arm_active_target.isa, isa_bit_thumb))
     {
@@ -32335,7 +32336,7 @@ arm_set_current_function (tree fndecl)
 
   save_restore_target_globals (new_tree);
 
-  arm_override_options_after_change_1 (&global_options);
+  arm_override_options_after_change_1 (&global_options, &global_options_set);
 }
 
 /* Implement TARGET_OPTION_PRINT.  */


	Jakub


^ permalink raw reply	[flat|nested] 29+ messages in thread

* RE: [PATCH] arm: Fix up arm_override_options_after_change_1
  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
  0 siblings, 2 replies; 29+ messages in thread
From: Kyrylo Tkachov @ 2020-09-10 14:11 UTC (permalink / raw)
  To: Jakub Jelinek, Richard Earnshaw, gcc-patches

Hi Jakub,

> -----Original Message-----
> From: Jakub Jelinek <jakub@redhat.com>
> Sent: 10 September 2020 09:51
> To: Richard Earnshaw <Richard.Earnshaw@foss.arm.com>; Kyrylo Tkachov
> <Kyrylo.Tkachov@arm.com>; gcc-patches@gcc.gnu.org
> Subject: [PATCH] arm: Fix up arm_override_options_after_change_1
> 
> On Tue, Sep 08, 2020 at 10:45:12AM +0200, Jakub Jelinek via Gcc-patches
> wrote:
> > Looking further at arm_override_options_after_change_1, it also seems to
> be
> > incorrect, rather than testing
> > !opts->x_str_align_functions
> > it should be really testing
> > !opts_set->x_str_align_functions
> > and get &global_options_set or similar passed to it as additional opts_set
> > argument.  That is because otherwise the decision will be sticky, while it
> > should be done whenever use provided -falign-functions but didn't provide
> > -falign-functions= (either on the command line, or through optimize
> > attribute or pragma).
> 
> Here is a fix for that (incremental change on top of the previous patch).
> Bootstrapped/regtested on armv7hl-linux-gnueabi, ok for trunk?

This looks ok to me.
Please commit to master so we can get some wider testing before backporting.

Thanks,
Kyrill

> 
> 2020-09-10  Jakub Jelinek  <jakub@redhat.com>
> 
> 	* config/arm/arm.c (arm_override_options_after_change_1): Add
> opts_set
> 	argument, test opts_set->x_str_align_functions rather than
> 	opts->x_str_align_functions.
> 	(arm_override_options_after_change, arm_option_override_internal,
> 	arm_set_current_function): Adjust callers.
> 
> --- gcc/config/arm/arm.c.jj	2020-09-09 09:19:42.911419411 +0200
> +++ gcc/config/arm/arm.c	2020-09-09 09:28:02.392897384 +0200
> @@ -3024,10 +3024,11 @@ static GTY(()) bool thumb_flipper;
>  static GTY(()) tree init_optimize;
> 
>  static void
> -arm_override_options_after_change_1 (struct gcc_options *opts)
> +arm_override_options_after_change_1 (struct gcc_options *opts,
> +				     struct gcc_options *opts_set)
>  {
>    /* -falign-functions without argument: supply one.  */
> -  if (opts->x_flag_align_functions && !opts->x_str_align_functions)
> +  if (opts->x_flag_align_functions && !opts_set->x_str_align_functions)
>      opts->x_str_align_functions = TARGET_THUMB_P (opts->x_target_flags)
>        && opts->x_optimize_size ? "2" : "4";
>  }
> @@ -3037,7 +3038,7 @@ arm_override_options_after_change_1 (str
>  static void
>  arm_override_options_after_change (void)
>  {
> -  arm_override_options_after_change_1 (&global_options);
> +  arm_override_options_after_change_1 (&global_options,
> &global_options_set);
>  }
> 
>  /* Implement TARGET_OPTION_SAVE.  */
> @@ -3065,7 +3066,7 @@ static void
>  arm_option_override_internal (struct gcc_options *opts,
>  			      struct gcc_options *opts_set)
>  {
> -  arm_override_options_after_change_1 (opts);
> +  arm_override_options_after_change_1 (opts, opts_set);
> 
>    if (TARGET_INTERWORK && !bitmap_bit_p (arm_active_target.isa,
> isa_bit_thumb))
>      {
> @@ -32335,7 +32336,7 @@ arm_set_current_function (tree fndecl)
> 
>    save_restore_target_globals (new_tree);
> 
> -  arm_override_options_after_change_1 (&global_options);
> +  arm_override_options_after_change_1 (&global_options,
> &global_options_set);
>  }
> 
>  /* Implement TARGET_OPTION_PRINT.  */
> 
> 
> 	Jakub


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] arm: Fix up arm_override_options_after_change_1
  2020-09-10 14:11   ` Kyrylo Tkachov
@ 2020-09-10 14:58     ` Jeff Law
  2020-09-10 15:01     ` Jakub Jelinek
  1 sibling, 0 replies; 29+ messages in thread
From: Jeff Law @ 2020-09-10 14:58 UTC (permalink / raw)
  To: Kyrylo Tkachov, Jakub Jelinek, Richard Earnshaw, gcc-patches

On Thu, 2020-09-10 at 14:11 +0000, Kyrylo Tkachov wrote:
> Hi Jakub,
> 
> > -----Original Message-----
> > From: Jakub Jelinek <jakub@redhat.com>
> > Sent: 10 September 2020 09:51
> > To: Richard Earnshaw <Richard.Earnshaw@foss.arm.com>; Kyrylo Tkachov
> > <Kyrylo.Tkachov@arm.com>; gcc-patches@gcc.gnu.org
> > Subject: [PATCH] arm: Fix up arm_override_options_after_change_1
> > 
> > On Tue, Sep 08, 2020 at 10:45:12AM +0200, Jakub Jelinek via Gcc-patches
> > wrote:
> > > Looking further at arm_override_options_after_change_1, it also seems to
> > be
> > > incorrect, rather than testing
> > > !opts->x_str_align_functions
> > > it should be really testing
> > > !opts_set->x_str_align_functions
> > > and get &global_options_set or similar passed to it as additional opts_set
> > > argument.  That is because otherwise the decision will be sticky, while it
> > > should be done whenever use provided -falign-functions but didn't provide
> > > -falign-functions= (either on the command line, or through optimize
> > > attribute or pragma).
> > 
> > Here is a fix for that (incremental change on top of the previous patch).
> > Bootstrapped/regtested on armv7hl-linux-gnueabi, ok for trunk?
> 
> This looks ok to me.
> Please commit to master so we can get some wider testing before backporting.
FWIW, I've done about a dozen package builds in Fedora with this patch to verify
it fixes the neon vs lto issues.  It's far from wide testing though ;-)  I've
asked Jakub to include it in the next GCC build he does for Fedora so that we can
remove those LTO opt-outs.

jeff
> 


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] arm: Fix up arm_override_options_after_change_1
  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
  1 sibling, 1 reply; 29+ messages in thread
From: Jakub Jelinek @ 2020-09-10 15:01 UTC (permalink / raw)
  To: Kyrylo Tkachov; +Cc: Richard Earnshaw, gcc-patches

On Thu, Sep 10, 2020 at 02:11:25PM +0000, Kyrylo Tkachov wrote:
> > > incorrect, rather than testing
> > > !opts->x_str_align_functions
> > > it should be really testing
> > > !opts_set->x_str_align_functions
> > > and get &global_options_set or similar passed to it as additional opts_set
> > > argument.  That is because otherwise the decision will be sticky, while it
> > > should be done whenever use provided -falign-functions but didn't provide
> > > -falign-functions= (either on the command line, or through optimize
> > > attribute or pragma).
> > 
> > Here is a fix for that (incremental change on top of the previous patch).
> > Bootstrapped/regtested on armv7hl-linux-gnueabi, ok for trunk?
> 
> This looks ok to me.
> Please commit to master so we can get some wider testing before backporting.

Note, this patch is just an incremental patch to the previous one which
hasn't been reviewed yet, is that one ok for master too?
https://gcc.gnu.org/pipermail/gcc-patches/2020-September/553400.html

> > 2020-09-10  Jakub Jelinek  <jakub@redhat.com>
> > 
> > 	* config/arm/arm.c (arm_override_options_after_change_1): Add
> > opts_set
> > 	argument, test opts_set->x_str_align_functions rather than
> > 	opts->x_str_align_functions.
> > 	(arm_override_options_after_change, arm_option_override_internal,
> > 	arm_set_current_function): Adjust callers.

	Jakub


^ permalink raw reply	[flat|nested] 29+ messages in thread

* RE: [PATCH] arm: Fix up arm_override_options_after_change_1
  2020-09-10 15:01     ` Jakub Jelinek
@ 2020-09-10 15:04       ` Kyrylo Tkachov
  0 siblings, 0 replies; 29+ messages in thread
From: Kyrylo Tkachov @ 2020-09-10 15:04 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Richard Earnshaw, gcc-patches



> -----Original Message-----
> From: Jakub Jelinek <jakub@redhat.com>
> Sent: 10 September 2020 16:02
> To: Kyrylo Tkachov <Kyrylo.Tkachov@arm.com>
> Cc: Richard Earnshaw <Richard.Earnshaw@foss.arm.com>; gcc-
> patches@gcc.gnu.org
> Subject: Re: [PATCH] arm: Fix up arm_override_options_after_change_1
> 
> On Thu, Sep 10, 2020 at 02:11:25PM +0000, Kyrylo Tkachov wrote:
> > > > incorrect, rather than testing
> > > > !opts->x_str_align_functions
> > > > it should be really testing
> > > > !opts_set->x_str_align_functions
> > > > and get &global_options_set or similar passed to it as additional
> opts_set
> > > > argument.  That is because otherwise the decision will be sticky, while it
> > > > should be done whenever use provided -falign-functions but didn't
> provide
> > > > -falign-functions= (either on the command line, or through optimize
> > > > attribute or pragma).
> > >
> > > Here is a fix for that (incremental change on top of the previous patch).
> > > Bootstrapped/regtested on armv7hl-linux-gnueabi, ok for trunk?
> >
> > This looks ok to me.
> > Please commit to master so we can get some wider testing before
> backporting.
> 
> Note, this patch is just an incremental patch to the previous one which
> hasn't been reviewed yet, is that one ok for master too?
> https://gcc.gnu.org/pipermail/gcc-patches/2020-September/553400.html

Yes, I had looked at that as well.
Sorry for not being explicit.

Thanks,
Kyrill

> 
> > > 2020-09-10  Jakub Jelinek  <jakub@redhat.com>
> > >
> > > 	* config/arm/arm.c (arm_override_options_after_change_1): Add
> > > opts_set
> > > 	argument, test opts_set->x_str_align_functions rather than
> > > 	opts->x_str_align_functions.
> > > 	(arm_override_options_after_change, arm_option_override_internal,
> > > 	arm_set_current_function): Adjust callers.
> 
> 	Jakub


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] arm: Fix up arm_override_options_after_change [PR96939]
  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-11  7:46 ` Christophe Lyon
  2020-09-11  9:29   ` Jakub Jelinek
  2 siblings, 1 reply; 29+ messages in thread
From: Christophe Lyon @ 2020-09-11  7:46 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Richard Earnshaw, Kyrylo Tkachov, gcc Patches

On Tue, 8 Sep 2020 at 10:45, Jakub Jelinek via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> Hi!
>
> As mentioned in the PR, the testcase fails to link, because when set_cfun is
> being called on the crc function, arm_override_options_after_change is
> called from set_cfun -> invoke_set_current_function_hook:
>       /* Change optimization options if needed.  */
>       if (optimization_current_node != opts)
>         {
>           optimization_current_node = opts;
>           cl_optimization_restore (&global_options, TREE_OPTIMIZATION (opts));
>         }
> and at that point target_option_default_node actually matches even the
> current state of options, so this means armv7 (or whatever) arch is set as
> arm_active_target, then
>       targetm.set_current_function (fndecl);
> is called later in that function, which because the crc function's
> DECL_FUNCTION_SPECIFIC_TARGET is different from the current one will do:
>   cl_target_option_restore (&global_options, TREE_TARGET_OPTION (new_tree));
> which calls arm_option_restore and sets arm_active_target to armv8-a+crc
> (so far so good).
> Later arm_set_current_function calls:
>   save_restore_target_globals (new_tree);
> which in this case calls:
>       /* Call target_reinit and save the state for TARGET_GLOBALS.  */
>       TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts ();
> which because optimization_current_node != optimization_default_node
> (the testcase is LTO, so all functions have their
> DECL_FUNCTION_SPECIFIC_TARGET and TREE_OPTIMIZATION nodes) will call:
>       cl_optimization_restore
>         (&global_options,
>          TREE_OPTIMIZATION (optimization_default_node));
> and
>       cl_optimization_restore (&global_options,
>                                TREE_OPTIMIZATION (opts));
> The problem is that these call arm_override_options_after_change again,
> and that one uses the target_option_default_node as what to set the
> arm_active_target to (i.e. back to armv7 or whatever, but not to the
> armv8-a+crc that should be the active target for the crc function).
> That means we then error on the builtin call in that function.
>
> Now, the targetm.override_options_after_change hook is called always at the
> end of cl_optimization_restore, i.e. when we change the Optimization marked
> generic options.  So it seems unnecessary to call arm_configure_build_target
> at that point (nothing it depends on changed), and additionally incorrect
> (because it uses the target_option_default_node, rather than the current
> set of options; we'd need to revert
> https://gcc.gnu.org/legacy-ml/gcc-patches/2016-12/msg01390.html
> otherwise so that it works again with global_options otherwise).
> The options that arm_configure_build_target cares about will change only
> during option parsing (which is where it is called already), or during
> arm_set_current_function, where it is done during the
> cl_target_option_restore.
> Now, arm_override_options_after_change_1 wants to adjust the
> str_align_functions, which depends on the current Optimization options (e.g.
> optimize_size and flag_align_options and str_align_functions) as well as
> the target options target_flags, so IMHO needs to be called both
> when the Optimization options (possibly) change, i.e. from
> the targetm.override_options_after_change hook, and from when the target
> options change (set_current_function hook).
>
> Bootstrapped/regtested on armv7hl-linux-gnueabi, ok for trunk?
>
> Looking further at arm_override_options_after_change_1, it also seems to be
> incorrect, rather than testing
> !opts->x_str_align_functions
> it should be really testing
> !opts_set->x_str_align_functions
> and get &global_options_set or similar passed to it as additional opts_set
> argument.  That is because otherwise the decision will be sticky, while it
> should be done whenever use provided -falign-functions but didn't provide
> -falign-functions= (either on the command line, or through optimize
> attribute or pragma).
>
> 2020-09-08  Jakub Jelinek  <jakub@redhat.com>
>
>         PR target/96939
>         * config/arm/arm.c (arm_override_options_after_change): Don't call
>         arm_configure_build_target here.
>         (arm_set_current_function): Call arm_override_options_after_change_1
>         at the end.
>
>         * gcc.target/arm/lto/pr96939_0.c: New test.
>         * gcc.target/arm/lto/pr96939_1.c: New file.
>

Hi Jakub,

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
In function 'crc':
lto1: internal compiler error: Segmentation fault
0xba720f crash_signal
        /gcc/toplev.c:327
0x172beb9 strchr
        /usr/include/string.h:227
0x172beb9 arm_parse_cpu_option_name(cpu_option const*, char const*,
char const*, bool)
        /gcc/common/config/arm/arm-common.c:349
0xfa9372 arm_configure_build_target(arm_build_target*,
cl_target_option*, gcc_options*, bool)
        /gcc/config/arm/arm.c:3209
0xfbf8e1 arm_set_current_function
        /gcc/config/arm/arm.c:32334
0x86b68b invoke_set_current_function_hook
        /gcc/function.c:4670
0x870d77 invoke_set_current_function_hook
        /gcc/function.c:4836
0x870d77 allocate_struct_function(tree_node*, bool)
        /gcc/function.c:4793
0xa25943 input_function
        /gcc/lto-streamer-in.c:1385
0xa25943 lto_read_body_or_constructor
        /gcc/lto-streamer-in.c:1624
0x6f37ff cgraph_node::get_untransformed_body()
        /gcc/cgraph.c:3932
0x703f42 cgraph_node::expand()
        /gcc/cgraphunit.c:2274
0x70567c expand_all_functions
        /gcc/cgraphunit.c:2476
0x70567c symbol_table::compile()
        /gcc/cgraphunit.c:2839
0x63970b lto_main()
        /gcc/lto/lto.c:653

This is with a cross-compiler.

Christophe

-
> --- gcc/config/arm/arm.c.jj     2020-07-30 15:04:38.136293101 +0200
> +++ gcc/config/arm/arm.c        2020-09-07 10:43:54.809561852 +0200
> @@ -3037,10 +3037,6 @@ arm_override_options_after_change_1 (str
>  static void
>  arm_override_options_after_change (void)
>  {
> -  arm_configure_build_target (&arm_active_target,
> -                             TREE_TARGET_OPTION (target_option_default_node),
> -                             &global_options_set, false);
> -
>    arm_override_options_after_change_1 (&global_options);
>  }
>
> @@ -32338,6 +32334,8 @@ arm_set_current_function (tree fndecl)
>    cl_target_option_restore (&global_options, TREE_TARGET_OPTION (new_tree));
>
>    save_restore_target_globals (new_tree);
> +
> +  arm_override_options_after_change_1 (&global_options);
>  }
>
>  /* Implement TARGET_OPTION_PRINT.  */
> --- gcc/testsuite/gcc.target/arm/lto/pr96939_0.c.jj     2020-09-07 11:26:45.909937609 +0200
> +++ gcc/testsuite/gcc.target/arm/lto/pr96939_0.c        2020-09-07 11:29:18.722706535 +0200
> @@ -0,0 +1,15 @@
> +/* PR target/96939 */
> +/* { dg-lto-do link } */
> +/* { dg-require-effective-target arm_arch_v8a_ok } */
> +/* { dg-lto-options { { -flto -O2 } } } */
> +
> +extern unsigned crc (unsigned, const void *);
> +typedef unsigned (*fnptr) (unsigned, const void *);
> +volatile fnptr fn;
> +
> +int
> +main ()
> +{
> +  fn = crc;
> +  return 0;
> +}
> --- gcc/testsuite/gcc.target/arm/lto/pr96939_1.c.jj     2020-09-07 11:26:49.365887153 +0200
> +++ gcc/testsuite/gcc.target/arm/lto/pr96939_1.c        2020-09-07 11:25:13.885281180 +0200
> @@ -0,0 +1,10 @@
> +/* PR target/96939 */
> +/* { dg-options "-march=armv8-a+crc" } */
> +
> +#include <arm_acle.h>
> +
> +unsigned
> +crc (unsigned x, const void *y)
> +{
> +  return __crc32cw (x, *(unsigned *) y);
> +}
>
>         Jakub
>

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] arm: Fix up arm_override_options_after_change [PR96939]
  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
  0 siblings, 1 reply; 29+ messages in thread
From: Jakub Jelinek @ 2020-09-11  9:29 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: gcc Patches, Richard Earnshaw

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.

> In function 'crc':
> lto1: internal compiler error: Segmentation fault
> 0xba720f crash_signal
>         /gcc/toplev.c:327
> 0x172beb9 strchr
>         /usr/include/string.h:227
> 0x172beb9 arm_parse_cpu_option_name(cpu_option const*, char const*,
> char const*, bool)
>         /gcc/common/config/arm/arm-common.c:349
> 0xfa9372 arm_configure_build_target(arm_build_target*,
> cl_target_option*, gcc_options*, bool)
>         /gcc/config/arm/arm.c:3209
> 0xfbf8e1 arm_set_current_function
>         /gcc/config/arm/arm.c:32334
> 0x86b68b invoke_set_current_function_hook
>         /gcc/function.c:4670
> 0x870d77 invoke_set_current_function_hook
>         /gcc/function.c:4836
> 0x870d77 allocate_struct_function(tree_node*, bool)
>         /gcc/function.c:4793
> 0xa25943 input_function
>         /gcc/lto-streamer-in.c:1385
> 0xa25943 lto_read_body_or_constructor
>         /gcc/lto-streamer-in.c:1624
> 0x6f37ff cgraph_node::get_untransformed_body()
>         /gcc/cgraph.c:3932
> 0x703f42 cgraph_node::expand()
>         /gcc/cgraphunit.c:2274
> 0x70567c expand_all_functions
>         /gcc/cgraphunit.c:2476
> 0x70567c symbol_table::compile()
>         /gcc/cgraphunit.c:2839
> 0x63970b lto_main()
>         /gcc/lto/lto.c:653
> 
> This is with a cross-compiler.

	Jakub


^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH] options: Save and restore opts_set for Optimization and Target options
  2020-09-11  9:29   ` Jakub Jelinek
@ 2020-09-13  8:29     ` Jakub Jelinek
  2020-09-14  6:32       ` Richard Biener
  2020-09-28 19:50       ` Stefan Schulze Frielinghaus
  0 siblings, 2 replies; 29+ messages in thread
From: Jakub Jelinek @ 2020-09-13  8:29 UTC (permalink / raw)
  To: Richard Biener, Joseph S. Myers, Richard Earnshaw; +Cc: gcc-patches

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?

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);
 }
 
 \f
@@ -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


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] options: Save and restore opts_set for Optimization and Target options
  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
  2020-09-28 19:50       ` Stefan Schulze Frielinghaus
  1 sibling, 1 reply; 29+ messages in thread
From: Richard Biener @ 2020-09-14  6:32 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Joseph S. Myers, Richard Earnshaw, gcc-patches

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?

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);
>  }
>  
>  \f
> @@ -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)

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] options: Save and restore opts_set for Optimization and Target options
  2020-09-14  6:32       ` Richard Biener
@ 2020-09-14  8:06         ` Christophe Lyon
  0 siblings, 0 replies; 29+ messages in thread
From: Christophe Lyon @ 2020-09-14  8:06 UTC (permalink / raw)
  To: Richard Biener
  Cc: Jakub Jelinek, gcc Patches, Richard Earnshaw, Joseph S. Myers

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)

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] options: Save and restore opts_set for Optimization and Target options
  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-28 19:50       ` Stefan Schulze Frielinghaus
  2020-09-28 19:58         ` Jakub Jelinek
  2020-09-30  9:32         ` Jakub Jelinek
  1 sibling, 2 replies; 29+ messages in thread
From: Stefan Schulze Frielinghaus @ 2020-09-28 19:50 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Richard Biener, Joseph S. Myers, Richard Earnshaw, gcc-patches

On Sun, Sep 13, 2020 at 10:29:22AM +0200, Jakub Jelinek via Gcc-patches 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?

This patch breaks quite a view test cases (target-attribute/tattr-*) on
IBM Z.  Having a look at function cl_target_option_restore reveals that
some members of opts_set are reduced to 1 or 0 depending on whether a
member was set before or not, e.g. for target_flags we have

opts_set->x_target_flags = (mask & 1) != 0;

whereas previously those members where not touched by
cl_target_option_restore.

My intuition of this whole option evaluation is still pretty vague.
Basically opts_set is a set of options enabled via command line and/or
via pragmas/attributes whereas opts is the set of options which are
implied by opts_set.

What puzzles me right now is that in cl_target_option_save we save in
ptr only options from opts but not from opts_set whereas in
cl_target_option_restore we override some members of opts_set.  Thus it
is unclear to me how a backend should restore opts_set then.
I'm probably missing something.  Any hints on how to restore opts_set
and especially target_flags?

Cheers,
Stefan

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] options: Save and restore opts_set for Optimization and Target options
  2020-09-28 19:50       ` Stefan Schulze Frielinghaus
@ 2020-09-28 19:58         ` Jakub Jelinek
  2020-09-30  9:32         ` Jakub Jelinek
  1 sibling, 0 replies; 29+ messages in thread
From: Jakub Jelinek @ 2020-09-28 19:58 UTC (permalink / raw)
  To: Stefan Schulze Frielinghaus
  Cc: Richard Biener, Joseph S. Myers, Richard Earnshaw, gcc-patches

On Mon, Sep 28, 2020 at 09:50:00PM +0200, Stefan Schulze Frielinghaus wrote:
> This patch breaks quite a view test cases (target-attribute/tattr-*) on
> IBM Z.  Having a look at function cl_target_option_restore reveals that
> some members of opts_set are reduced to 1 or 0 depending on whether a
> member was set before or not, e.g. for target_flags we have
> 
> opts_set->x_target_flags = (mask & 1) != 0;
> 
> whereas previously those members where not touched by
> cl_target_option_restore.

opts_set is always used as a booleans, cleaner would be to have a 
struct global_option_set that would contain just bool fields (or even
bitfields) with the same names as in struct global_option, but unfortunately
we didn't do that years ago and changing it now would be quite a lot of
work.
Anyway, opts_set records a boolean for each flag, whether it was set
explicitly or not, for non-pointer vars that means values 0 and 1,
for pointer vars NULL and "".
I vaguely remember the s390 opts_set handling differed quite a lot from all
the other targets.

> What puzzles me right now is that in cl_target_option_save we save in
> ptr only options from opts but not from opts_set whereas in
> cl_target_option_restore we override some members of opts_set.  Thus it
> is unclear to me how a backend should restore opts_set then.

I've handled in the generic code handling of the opts_set only for whatever
is handled there for opts too.
Whether the vars that are handled in the save/restore options hooks need
handling of opts_set at all or not depends on whether the backend ever cares
about those or not (e.g. whether it every queries
global_options_set.x_whatever).  If yes, it can be handled e.g. by having an
extra target variable that will store whether it was explicit or not and
restore from there.  If it is never used, then it doesn't need to be
handled.

	Jakub


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] options: Save and restore opts_set for Optimization and Target options
  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
  1 sibling, 1 reply; 29+ messages in thread
From: Jakub Jelinek @ 2020-09-30  9:32 UTC (permalink / raw)
  To: Stefan Schulze Frielinghaus
  Cc: gcc-patches, Richard Biener, Richard Earnshaw, Joseph S. Myers

On Mon, Sep 28, 2020 at 09:50:00PM +0200, Stefan Schulze Frielinghaus via Gcc-patches wrote:
> This patch breaks quite a view test cases (target-attribute/tattr-*) on
> IBM Z.  Having a look at function cl_target_option_restore reveals that
> some members of opts_set are reduced to 1 or 0 depending on whether a
> member was set before or not, e.g. for target_flags we have

I've tried to reproduce the tattr FAILs reported in
https://gcc.gnu.org/pipermail/gcc-testresults/2020-September/608760.html
in a cross-compiler (with
#define HAVE_AS_MACHINE_MACHINEMODE 1
), but couldn't, neither the ICEs nor the scan-assembler failures.
Anyway, could you do a side-by-side debugging of one of those failures
before/after my change and see what behaves differently?

	Jakub


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] options: Save and restore opts_set for Optimization and Target options
  2020-09-30  9:32         ` Jakub Jelinek
@ 2020-09-30 11:21           ` Stefan Schulze Frielinghaus
  2020-09-30 11:39             ` Jakub Jelinek
  0 siblings, 1 reply; 29+ messages in thread
From: Stefan Schulze Frielinghaus @ 2020-09-30 11:21 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: gcc-patches, Richard Biener, Richard Earnshaw, Joseph S. Myers

On Wed, Sep 30, 2020 at 11:32:55AM +0200, Jakub Jelinek wrote:
> On Mon, Sep 28, 2020 at 09:50:00PM +0200, Stefan Schulze Frielinghaus via Gcc-patches wrote:
> > This patch breaks quite a view test cases (target-attribute/tattr-*) on
> > IBM Z.  Having a look at function cl_target_option_restore reveals that
> > some members of opts_set are reduced to 1 or 0 depending on whether a
> > member was set before or not, e.g. for target_flags we have
> 
> I've tried to reproduce the tattr FAILs reported in
> https://gcc.gnu.org/pipermail/gcc-testresults/2020-September/608760.html
> in a cross-compiler (with
> #define HAVE_AS_MACHINE_MACHINEMODE 1
> ), but couldn't, neither the ICEs nor the scan-assembler failures.
> Anyway, could you do a side-by-side debugging of one of those failures
> before/after my change and see what behaves differently?

I think the problem boils down that on S/390 we distinguish between four
states of a flag: explicitely set to yes/no and implicitely set to
yes/no.  If set explicitely, the option wins.  For example, the options
`-march=z10 -mhtm` should enable the hardware transactional memory
option although z10 does not have one.  In the past if a flag was set or
not explicitely was encoded into opts_set->x_target_flags ... for each
flag individually, e.g. TARGET_OPT_HTM_P (opts_set->x_target_flags) was
used.  This has changed with the mentioned patch in the sense that
opts_set encodes whether any flag of x_target_flags was set or not but
not which individual one after a call to the generated function
cl_target_option_restore where we have:
opts_set->x_target_flags = (mask & 1) != 0;

Compiling the following program

#pragma GCC target ("arch=z10")
void fn_pragma_0 (void) { }

with options `-march=z13 -mzarch -mhtm -mdebug` produces different flags
for 4ac7b669580 (commit prior your patch) and ba948b37768 (your patch).

This is my current understanding of the option handling.  I will try to
come up with a trace where these things become hopefully more clear.

Cheers,
Stefan

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] options: Save and restore opts_set for Optimization and Target options
  2020-09-30 11:21           ` Stefan Schulze Frielinghaus
@ 2020-09-30 11:39             ` Jakub Jelinek
  2020-09-30 13:24               ` Stefan Schulze Frielinghaus
  0 siblings, 1 reply; 29+ messages in thread
From: Jakub Jelinek @ 2020-09-30 11:39 UTC (permalink / raw)
  To: Stefan Schulze Frielinghaus
  Cc: gcc-patches, Richard Biener, Richard Earnshaw, Joseph S. Myers

On Wed, Sep 30, 2020 at 01:21:44PM +0200, Stefan Schulze Frielinghaus wrote:
> I think the problem boils down that on S/390 we distinguish between four
> states of a flag: explicitely set to yes/no and implicitely set to
> yes/no.  If set explicitely, the option wins.  For example, the options
> `-march=z10 -mhtm` should enable the hardware transactional memory
> option although z10 does not have one.  In the past if a flag was set or
> not explicitely was encoded into opts_set->x_target_flags ... for each
> flag individually, e.g. TARGET_OPT_HTM_P (opts_set->x_target_flags) was

Oops, seems I've missed that set_option has special treatment for
CLVC_BIT_CLEAR/CLVC_BIT_SET.
Which means I'll need to change the generic handling, so that for
global_options_set elements mentioned in CLVC_BIT_* options are treated
differently, instead of using the accumulated bitmasks they'll need to use
their specific bitmask variables during the option saving/restoring.
Is it ok if I defer it for tomorrow? Need to prepare for OpenMP meeting now.

	Jakub


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] options: Save and restore opts_set for Optimization and Target options
  2020-09-30 11:39             ` Jakub Jelinek
@ 2020-09-30 13:24               ` Stefan Schulze Frielinghaus
  2020-10-02  8:46                 ` Jakub Jelinek
  0 siblings, 1 reply; 29+ messages in thread
From: Stefan Schulze Frielinghaus @ 2020-09-30 13:24 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: gcc-patches, Richard Biener, Richard Earnshaw, Joseph S. Myers

On Wed, Sep 30, 2020 at 01:39:11PM +0200, Jakub Jelinek wrote:
> On Wed, Sep 30, 2020 at 01:21:44PM +0200, Stefan Schulze Frielinghaus wrote:
> > I think the problem boils down that on S/390 we distinguish between four
> > states of a flag: explicitely set to yes/no and implicitely set to
> > yes/no.  If set explicitely, the option wins.  For example, the options
> > `-march=z10 -mhtm` should enable the hardware transactional memory
> > option although z10 does not have one.  In the past if a flag was set or
> > not explicitely was encoded into opts_set->x_target_flags ... for each
> > flag individually, e.g. TARGET_OPT_HTM_P (opts_set->x_target_flags) was
> 
> Oops, seems I've missed that set_option has special treatment for
> CLVC_BIT_CLEAR/CLVC_BIT_SET.
> Which means I'll need to change the generic handling, so that for
> global_options_set elements mentioned in CLVC_BIT_* options are treated
> differently, instead of using the accumulated bitmasks they'll need to use
> their specific bitmask variables during the option saving/restoring.
> Is it ok if I defer it for tomorrow? Need to prepare for OpenMP meeting now.

Sure, no problem at all.  In that case I stop to investigate further and
wait for you.

Cheers,
Stefan

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] options: Save and restore opts_set for Optimization and Target options
  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-04  7:13                   ` Andreas Schwab
  0 siblings, 2 replies; 29+ messages in thread
From: Jakub Jelinek @ 2020-10-02  8:46 UTC (permalink / raw)
  To: Stefan Schulze Frielinghaus
  Cc: Richard Biener, gcc-patches, Richard Earnshaw, Joseph S. Myers

On Wed, Sep 30, 2020 at 03:24:08PM +0200, Stefan Schulze Frielinghaus via Gcc-patches wrote:
> On Wed, Sep 30, 2020 at 01:39:11PM +0200, Jakub Jelinek wrote:
> > On Wed, Sep 30, 2020 at 01:21:44PM +0200, Stefan Schulze Frielinghaus wrote:
> > > I think the problem boils down that on S/390 we distinguish between four
> > > states of a flag: explicitely set to yes/no and implicitely set to
> > > yes/no.  If set explicitely, the option wins.  For example, the options
> > > `-march=z10 -mhtm` should enable the hardware transactional memory
> > > option although z10 does not have one.  In the past if a flag was set or
> > > not explicitely was encoded into opts_set->x_target_flags ... for each
> > > flag individually, e.g. TARGET_OPT_HTM_P (opts_set->x_target_flags) was
> > 
> > Oops, seems I've missed that set_option has special treatment for
> > CLVC_BIT_CLEAR/CLVC_BIT_SET.
> > Which means I'll need to change the generic handling, so that for
> > global_options_set elements mentioned in CLVC_BIT_* options are treated
> > differently, instead of using the accumulated bitmasks they'll need to use
> > their specific bitmask variables during the option saving/restoring.
> > Is it ok if I defer it for tomorrow? Need to prepare for OpenMP meeting now.
> 
> Sure, no problem at all.  In that case I stop to investigate further and
> wait for you.

Here is a patch that implements that.

Can you please check if it fixes the s390x regressions that I couldn't
reproduce in a cross?

Bootstrapped/regtested on x86_64-linux and i686-linux so far.
I don't have a convenient way to test it on the trunk on other
architectures ATM, so I've just started testing a backport of the patchset to 10
on {x86_64,i686,powerpc64le,s390x,armv7hl,aarch64}-linux (though, don't
intend to actually commit the backport).

2020-10-02  Jakub Jelinek  <jakub@redhat.com>

	* opth-gen.awk: For variables referenced in Mask and InverseMask,
	don't use the explicit_mask bitmask array, but add separate
	explicit_mask_* members with the same types as the variables.
	* optc-save-gen.awk: Save, restore, compare and hash the separate
	explicit_mask_* members.

--- gcc/opth-gen.awk.jj	2020-09-14 09:04:35.866854351 +0200
+++ gcc/opth-gen.awk	2020-10-01 21:52:30.855122749 +0200
@@ -209,6 +209,7 @@ n_target_int = 0;
 n_target_enum = 0;
 n_target_other = 0;
 n_target_explicit = n_extra_target_vars;
+n_target_explicit_mask = 0;
 
 for (i = 0; i < n_target_save; i++) {
 	if (target_save_decl[i] ~ "^((un)?signed +)?int +[_" alnum "]+$")
@@ -240,6 +241,12 @@ if (have_save) {
 			var_save_seen[name]++;
 			n_target_explicit++;
 			otype = var_type_struct(flags[i])
+
+			if (opt_args("Mask", flags[i]) != "" \
+			    || opt_args("InverseMask", flags[i]))
+				var_target_explicit_mask[n_target_explicit_mask++] \
+				    = otype "explicit_mask_" name;
+
 			if (otype ~ "^((un)?signed +)?int *$")
 				var_target_int[n_target_int++] = otype "x_" name;
 
@@ -259,6 +266,8 @@ if (have_save) {
 } else {
 	var_target_int[n_target_int++] = "int x_target_flags";
 	n_target_explicit++;
+	var_target_explicit_mask[n_target_explicit_mask++] \
+	    = "int explicit_mask_target_flags";
 }
 
 for (i = 0; i < n_target_other; i++) {
@@ -281,8 +290,12 @@ 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 "  /* " n_target_explicit - n_target_explicit_mask " members */";
+print "  unsigned HOST_WIDE_INT explicit_mask[" int ((n_target_explicit - n_target_explicit_mask + 63) / 64) "];";
+
+for (i = 0; i < n_target_explicit_mask; i++) {
+	print "  " var_target_explicit_mask[i] ";";
+}
 
 print "};";
 print "";
--- gcc/optc-save-gen.awk.jj	2020-09-16 10:06:23.018093486 +0200
+++ gcc/optc-save-gen.awk	2020-10-01 21:48:10.933868862 +0200
@@ -516,6 +516,10 @@ if (have_save) {
 
 			var_save_seen[name]++;
 			otype = var_type_struct(flags[i])
+			if (opt_args("Mask", flags[i]) != "" \
+			    || opt_args("InverseMask", flags[i]))
+				var_target_explicit_mask[name] = 1;
+
 			if (otype ~ "^((un)?signed +)?int *$")
 				var_target_int[n_target_int++] = name;
 
@@ -545,6 +549,7 @@ if (have_save) {
 	}
 } else {
 	var_target_int[n_target_int++] = "target_flags";
+	var_target_explicit_mask["target_flags"] = 1;
 }
 
 have_assert = 0;
@@ -608,6 +613,10 @@ for (i = 0; i < n_extra_target_vars; i++
 }
 
 for (i = 0; i < n_target_other; i++) {
+	if (var_target_other[i] in var_target_explicit_mask) {
+		print "  ptr->explicit_mask_" var_target_other[i] " = opts_set->x_" var_target_other[i] ";";
+		continue;
+	}
 	print "  if (opts_set->x_" var_target_other[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
 	j++;
 	if (j == 64) {
@@ -630,6 +639,10 @@ for (i = 0; i < n_target_enum; i++) {
 }
 
 for (i = 0; i < n_target_int; i++) {
+	if (var_target_int[i] in var_target_explicit_mask) {
+		print "  ptr->explicit_mask_" var_target_int[i] " = opts_set->x_" var_target_int[i] ";";
+		continue;
+	}
 	print "  if (opts_set->x_" var_target_int[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
 	j++;
 	if (j == 64) {
@@ -739,6 +752,10 @@ for (i = 0; i < n_extra_target_vars; i++
 }
 
 for (i = 0; i < n_target_other; i++) {
+	if (var_target_other[i] in var_target_explicit_mask) {
+		print "  opts_set->x_" var_target_other[i] " = ptr->explicit_mask_" var_target_other[i] ";";
+		continue;
+	}
 	if (j == 64) {
 		print "  mask = ptr->explicit_mask[" k "];";
 		k++;
@@ -761,6 +778,10 @@ for (i = 0; i < n_target_enum; i++) {
 }
 
 for (i = 0; i < n_target_int; i++) {
+	if (var_target_int[i] in var_target_explicit_mask) {
+		print "  opts_set->x_" var_target_int[i] " = ptr->explicit_mask_" var_target_int[i] ";";
+		continue;
+	}
 	if (j == 64) {
 		print "  mask = ptr->explicit_mask[" k "];";
 		k++;
@@ -1058,6 +1079,20 @@ print "  for (size_t i = 0; i < sizeof (
 print "    if (ptr1->explicit_mask[i] != ptr2->explicit_mask[i])";
 print "      return false;"
 
+for (i = 0; i < n_target_other; i++) {
+	if (var_target_other[i] in var_target_explicit_mask) {
+		print "  if (ptr1->explicit_mask_" var_target_other[i] " != ptr2->explicit_mask_" var_target_other[i] ")";
+		print "    return false;";
+	}
+}
+
+for (i = 0; i < n_target_int; i++) {
+	if (var_target_int[i] in var_target_explicit_mask) {
+		print "  if (ptr1->explicit_mask_" var_target_int[i] " != ptr2->explicit_mask_" var_target_int[i] ")";
+		print "    return false;";
+	}
+}
+
 print "  return true;";
 
 print "}";
@@ -1088,6 +1123,17 @@ for (i = 0; i < n_target_val; i++) {
 }
 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]);";
+
+for (i = 0; i < n_target_other; i++) {
+	if (var_target_other[i] in var_target_explicit_mask)
+		print "  hstate.add_hwi (ptr->explicit_mask_" var_target_other[i] ");";
+}
+
+for (i = 0; i < n_target_int; i++) {
+	if (var_target_int[i] in var_target_explicit_mask)
+		print "  hstate.add_hwi (ptr->explicit_mask_" var_target_int[i] ");";
+}
+
 print "  return hstate.end ();";
 print "}";
 


	Jakub


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] options: Save and restore opts_set for Optimization and Target options
  2020-10-02  8:46                 ` Jakub Jelinek
@ 2020-10-02 14:21                   ` Stefan Schulze Frielinghaus
  2020-10-03  8:41                     ` Jakub Jelinek
  2020-10-04  7:13                   ` Andreas Schwab
  1 sibling, 1 reply; 29+ messages in thread
From: Stefan Schulze Frielinghaus @ 2020-10-02 14:21 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Richard Biener, gcc-patches, Richard Earnshaw, Joseph S. Myers

On Fri, Oct 02, 2020 at 10:46:33AM +0200, Jakub Jelinek wrote:
> On Wed, Sep 30, 2020 at 03:24:08PM +0200, Stefan Schulze Frielinghaus via Gcc-patches wrote:
> > On Wed, Sep 30, 2020 at 01:39:11PM +0200, Jakub Jelinek wrote:
> > > On Wed, Sep 30, 2020 at 01:21:44PM +0200, Stefan Schulze Frielinghaus wrote:
> > > > I think the problem boils down that on S/390 we distinguish between four
> > > > states of a flag: explicitely set to yes/no and implicitely set to
> > > > yes/no.  If set explicitely, the option wins.  For example, the options
> > > > `-march=z10 -mhtm` should enable the hardware transactional memory
> > > > option although z10 does not have one.  In the past if a flag was set or
> > > > not explicitely was encoded into opts_set->x_target_flags ... for each
> > > > flag individually, e.g. TARGET_OPT_HTM_P (opts_set->x_target_flags) was
> > > 
> > > Oops, seems I've missed that set_option has special treatment for
> > > CLVC_BIT_CLEAR/CLVC_BIT_SET.
> > > Which means I'll need to change the generic handling, so that for
> > > global_options_set elements mentioned in CLVC_BIT_* options are treated
> > > differently, instead of using the accumulated bitmasks they'll need to use
> > > their specific bitmask variables during the option saving/restoring.
> > > Is it ok if I defer it for tomorrow? Need to prepare for OpenMP meeting now.
> > 
> > Sure, no problem at all.  In that case I stop to investigate further and
> > wait for you.
> 
> Here is a patch that implements that.
> 
> Can you please check if it fixes the s390x regressions that I couldn't
> reproduce in a cross?

Bootstrapped and regtested on S/390. Now all tattr-*.c test cases run
successfully with the patch. All other tests remain the same.

Thanks for the quick follow up!

Cheers,
Stefan

> 
> Bootstrapped/regtested on x86_64-linux and i686-linux so far.
> I don't have a convenient way to test it on the trunk on other
> architectures ATM, so I've just started testing a backport of the patchset to 10
> on {x86_64,i686,powerpc64le,s390x,armv7hl,aarch64}-linux (though, don't
> intend to actually commit the backport).
> 
> 2020-10-02  Jakub Jelinek  <jakub@redhat.com>
> 
> 	* opth-gen.awk: For variables referenced in Mask and InverseMask,
> 	don't use the explicit_mask bitmask array, but add separate
> 	explicit_mask_* members with the same types as the variables.
> 	* optc-save-gen.awk: Save, restore, compare and hash the separate
> 	explicit_mask_* members.
> 
> --- gcc/opth-gen.awk.jj	2020-09-14 09:04:35.866854351 +0200
> +++ gcc/opth-gen.awk	2020-10-01 21:52:30.855122749 +0200
> @@ -209,6 +209,7 @@ n_target_int = 0;
>  n_target_enum = 0;
>  n_target_other = 0;
>  n_target_explicit = n_extra_target_vars;
> +n_target_explicit_mask = 0;
>  
>  for (i = 0; i < n_target_save; i++) {
>  	if (target_save_decl[i] ~ "^((un)?signed +)?int +[_" alnum "]+$")
> @@ -240,6 +241,12 @@ if (have_save) {
>  			var_save_seen[name]++;
>  			n_target_explicit++;
>  			otype = var_type_struct(flags[i])
> +
> +			if (opt_args("Mask", flags[i]) != "" \
> +			    || opt_args("InverseMask", flags[i]))
> +				var_target_explicit_mask[n_target_explicit_mask++] \
> +				    = otype "explicit_mask_" name;
> +
>  			if (otype ~ "^((un)?signed +)?int *$")
>  				var_target_int[n_target_int++] = otype "x_" name;
>  
> @@ -259,6 +266,8 @@ if (have_save) {
>  } else {
>  	var_target_int[n_target_int++] = "int x_target_flags";
>  	n_target_explicit++;
> +	var_target_explicit_mask[n_target_explicit_mask++] \
> +	    = "int explicit_mask_target_flags";
>  }
>  
>  for (i = 0; i < n_target_other; i++) {
> @@ -281,8 +290,12 @@ 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 "  /* " n_target_explicit - n_target_explicit_mask " members */";
> +print "  unsigned HOST_WIDE_INT explicit_mask[" int ((n_target_explicit - n_target_explicit_mask + 63) / 64) "];";
> +
> +for (i = 0; i < n_target_explicit_mask; i++) {
> +	print "  " var_target_explicit_mask[i] ";";
> +}
>  
>  print "};";
>  print "";
> --- gcc/optc-save-gen.awk.jj	2020-09-16 10:06:23.018093486 +0200
> +++ gcc/optc-save-gen.awk	2020-10-01 21:48:10.933868862 +0200
> @@ -516,6 +516,10 @@ if (have_save) {
>  
>  			var_save_seen[name]++;
>  			otype = var_type_struct(flags[i])
> +			if (opt_args("Mask", flags[i]) != "" \
> +			    || opt_args("InverseMask", flags[i]))
> +				var_target_explicit_mask[name] = 1;
> +
>  			if (otype ~ "^((un)?signed +)?int *$")
>  				var_target_int[n_target_int++] = name;
>  
> @@ -545,6 +549,7 @@ if (have_save) {
>  	}
>  } else {
>  	var_target_int[n_target_int++] = "target_flags";
> +	var_target_explicit_mask["target_flags"] = 1;
>  }
>  
>  have_assert = 0;
> @@ -608,6 +613,10 @@ for (i = 0; i < n_extra_target_vars; i++
>  }
>  
>  for (i = 0; i < n_target_other; i++) {
> +	if (var_target_other[i] in var_target_explicit_mask) {
> +		print "  ptr->explicit_mask_" var_target_other[i] " = opts_set->x_" var_target_other[i] ";";
> +		continue;
> +	}
>  	print "  if (opts_set->x_" var_target_other[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
>  	j++;
>  	if (j == 64) {
> @@ -630,6 +639,10 @@ for (i = 0; i < n_target_enum; i++) {
>  }
>  
>  for (i = 0; i < n_target_int; i++) {
> +	if (var_target_int[i] in var_target_explicit_mask) {
> +		print "  ptr->explicit_mask_" var_target_int[i] " = opts_set->x_" var_target_int[i] ";";
> +		continue;
> +	}
>  	print "  if (opts_set->x_" var_target_int[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
>  	j++;
>  	if (j == 64) {
> @@ -739,6 +752,10 @@ for (i = 0; i < n_extra_target_vars; i++
>  }
>  
>  for (i = 0; i < n_target_other; i++) {
> +	if (var_target_other[i] in var_target_explicit_mask) {
> +		print "  opts_set->x_" var_target_other[i] " = ptr->explicit_mask_" var_target_other[i] ";";
> +		continue;
> +	}
>  	if (j == 64) {
>  		print "  mask = ptr->explicit_mask[" k "];";
>  		k++;
> @@ -761,6 +778,10 @@ for (i = 0; i < n_target_enum; i++) {
>  }
>  
>  for (i = 0; i < n_target_int; i++) {
> +	if (var_target_int[i] in var_target_explicit_mask) {
> +		print "  opts_set->x_" var_target_int[i] " = ptr->explicit_mask_" var_target_int[i] ";";
> +		continue;
> +	}
>  	if (j == 64) {
>  		print "  mask = ptr->explicit_mask[" k "];";
>  		k++;
> @@ -1058,6 +1079,20 @@ print "  for (size_t i = 0; i < sizeof (
>  print "    if (ptr1->explicit_mask[i] != ptr2->explicit_mask[i])";
>  print "      return false;"
>  
> +for (i = 0; i < n_target_other; i++) {
> +	if (var_target_other[i] in var_target_explicit_mask) {
> +		print "  if (ptr1->explicit_mask_" var_target_other[i] " != ptr2->explicit_mask_" var_target_other[i] ")";
> +		print "    return false;";
> +	}
> +}
> +
> +for (i = 0; i < n_target_int; i++) {
> +	if (var_target_int[i] in var_target_explicit_mask) {
> +		print "  if (ptr1->explicit_mask_" var_target_int[i] " != ptr2->explicit_mask_" var_target_int[i] ")";
> +		print "    return false;";
> +	}
> +}
> +
>  print "  return true;";
>  
>  print "}";
> @@ -1088,6 +1123,17 @@ for (i = 0; i < n_target_val; i++) {
>  }
>  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]);";
> +
> +for (i = 0; i < n_target_other; i++) {
> +	if (var_target_other[i] in var_target_explicit_mask)
> +		print "  hstate.add_hwi (ptr->explicit_mask_" var_target_other[i] ");";
> +}
> +
> +for (i = 0; i < n_target_int; i++) {
> +	if (var_target_int[i] in var_target_explicit_mask)
> +		print "  hstate.add_hwi (ptr->explicit_mask_" var_target_int[i] ");";
> +}
> +
>  print "  return hstate.end ();";
>  print "}";
>  
> 
> 
> 	Jakub
> 

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] options: Save and restore opts_set for Optimization and Target options
  2020-10-02 14:21                   ` Stefan Schulze Frielinghaus
@ 2020-10-03  8:41                     ` Jakub Jelinek
  2020-10-03 18:02                       ` Richard Biener
  0 siblings, 1 reply; 29+ messages in thread
From: Jakub Jelinek @ 2020-10-03  8:41 UTC (permalink / raw)
  To: Richard Biener, Stefan Schulze Frielinghaus
  Cc: gcc-patches, Richard Earnshaw, Joseph S. Myers

On Fri, Oct 02, 2020 at 04:21:12PM +0200, Stefan Schulze Frielinghaus via Gcc-patches wrote:
> > > Sure, no problem at all.  In that case I stop to investigate further and
> > > wait for you.
> > 
> > Here is a patch that implements that.
> > 
> > Can you please check if it fixes the s390x regressions that I couldn't
> > reproduce in a cross?
> 
> Bootstrapped and regtested on S/390. Now all tattr-*.c test cases run
> successfully with the patch. All other tests remain the same.

I've now also successfully tested it on
{x86_64,i686,armv7hl,aarch64,powerpc64le,s390x.  Ok for trunk?

> > 2020-10-02  Jakub Jelinek  <jakub@redhat.com>
> > 
> > 	* opth-gen.awk: For variables referenced in Mask and InverseMask,
> > 	don't use the explicit_mask bitmask array, but add separate
> > 	explicit_mask_* members with the same types as the variables.
> > 	* optc-save-gen.awk: Save, restore, compare and hash the separate
> > 	explicit_mask_* members.
> > 
> > --- gcc/opth-gen.awk.jj	2020-09-14 09:04:35.866854351 +0200
> > +++ gcc/opth-gen.awk	2020-10-01 21:52:30.855122749 +0200
> > @@ -209,6 +209,7 @@ n_target_int = 0;
> >  n_target_enum = 0;
> >  n_target_other = 0;
> >  n_target_explicit = n_extra_target_vars;
> > +n_target_explicit_mask = 0;
> >  
> >  for (i = 0; i < n_target_save; i++) {
> >  	if (target_save_decl[i] ~ "^((un)?signed +)?int +[_" alnum "]+$")
> > @@ -240,6 +241,12 @@ if (have_save) {
> >  			var_save_seen[name]++;
> >  			n_target_explicit++;
> >  			otype = var_type_struct(flags[i])
> > +
> > +			if (opt_args("Mask", flags[i]) != "" \
> > +			    || opt_args("InverseMask", flags[i]))
> > +				var_target_explicit_mask[n_target_explicit_mask++] \
> > +				    = otype "explicit_mask_" name;
> > +
> >  			if (otype ~ "^((un)?signed +)?int *$")
> >  				var_target_int[n_target_int++] = otype "x_" name;
> >  
> > @@ -259,6 +266,8 @@ if (have_save) {
> >  } else {
> >  	var_target_int[n_target_int++] = "int x_target_flags";
> >  	n_target_explicit++;
> > +	var_target_explicit_mask[n_target_explicit_mask++] \
> > +	    = "int explicit_mask_target_flags";
> >  }
> >  
> >  for (i = 0; i < n_target_other; i++) {
> > @@ -281,8 +290,12 @@ 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 "  /* " n_target_explicit - n_target_explicit_mask " members */";
> > +print "  unsigned HOST_WIDE_INT explicit_mask[" int ((n_target_explicit - n_target_explicit_mask + 63) / 64) "];";
> > +
> > +for (i = 0; i < n_target_explicit_mask; i++) {
> > +	print "  " var_target_explicit_mask[i] ";";
> > +}
> >  
> >  print "};";
> >  print "";
> > --- gcc/optc-save-gen.awk.jj	2020-09-16 10:06:23.018093486 +0200
> > +++ gcc/optc-save-gen.awk	2020-10-01 21:48:10.933868862 +0200
> > @@ -516,6 +516,10 @@ if (have_save) {
> >  
> >  			var_save_seen[name]++;
> >  			otype = var_type_struct(flags[i])
> > +			if (opt_args("Mask", flags[i]) != "" \
> > +			    || opt_args("InverseMask", flags[i]))
> > +				var_target_explicit_mask[name] = 1;
> > +
> >  			if (otype ~ "^((un)?signed +)?int *$")
> >  				var_target_int[n_target_int++] = name;
> >  
> > @@ -545,6 +549,7 @@ if (have_save) {
> >  	}
> >  } else {
> >  	var_target_int[n_target_int++] = "target_flags";
> > +	var_target_explicit_mask["target_flags"] = 1;
> >  }
> >  
> >  have_assert = 0;
> > @@ -608,6 +613,10 @@ for (i = 0; i < n_extra_target_vars; i++
> >  }
> >  
> >  for (i = 0; i < n_target_other; i++) {
> > +	if (var_target_other[i] in var_target_explicit_mask) {
> > +		print "  ptr->explicit_mask_" var_target_other[i] " = opts_set->x_" var_target_other[i] ";";
> > +		continue;
> > +	}
> >  	print "  if (opts_set->x_" var_target_other[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
> >  	j++;
> >  	if (j == 64) {
> > @@ -630,6 +639,10 @@ for (i = 0; i < n_target_enum; i++) {
> >  }
> >  
> >  for (i = 0; i < n_target_int; i++) {
> > +	if (var_target_int[i] in var_target_explicit_mask) {
> > +		print "  ptr->explicit_mask_" var_target_int[i] " = opts_set->x_" var_target_int[i] ";";
> > +		continue;
> > +	}
> >  	print "  if (opts_set->x_" var_target_int[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
> >  	j++;
> >  	if (j == 64) {
> > @@ -739,6 +752,10 @@ for (i = 0; i < n_extra_target_vars; i++
> >  }
> >  
> >  for (i = 0; i < n_target_other; i++) {
> > +	if (var_target_other[i] in var_target_explicit_mask) {
> > +		print "  opts_set->x_" var_target_other[i] " = ptr->explicit_mask_" var_target_other[i] ";";
> > +		continue;
> > +	}
> >  	if (j == 64) {
> >  		print "  mask = ptr->explicit_mask[" k "];";
> >  		k++;
> > @@ -761,6 +778,10 @@ for (i = 0; i < n_target_enum; i++) {
> >  }
> >  
> >  for (i = 0; i < n_target_int; i++) {
> > +	if (var_target_int[i] in var_target_explicit_mask) {
> > +		print "  opts_set->x_" var_target_int[i] " = ptr->explicit_mask_" var_target_int[i] ";";
> > +		continue;
> > +	}
> >  	if (j == 64) {
> >  		print "  mask = ptr->explicit_mask[" k "];";
> >  		k++;
> > @@ -1058,6 +1079,20 @@ print "  for (size_t i = 0; i < sizeof (
> >  print "    if (ptr1->explicit_mask[i] != ptr2->explicit_mask[i])";
> >  print "      return false;"
> >  
> > +for (i = 0; i < n_target_other; i++) {
> > +	if (var_target_other[i] in var_target_explicit_mask) {
> > +		print "  if (ptr1->explicit_mask_" var_target_other[i] " != ptr2->explicit_mask_" var_target_other[i] ")";
> > +		print "    return false;";
> > +	}
> > +}
> > +
> > +for (i = 0; i < n_target_int; i++) {
> > +	if (var_target_int[i] in var_target_explicit_mask) {
> > +		print "  if (ptr1->explicit_mask_" var_target_int[i] " != ptr2->explicit_mask_" var_target_int[i] ")";
> > +		print "    return false;";
> > +	}
> > +}
> > +
> >  print "  return true;";
> >  
> >  print "}";
> > @@ -1088,6 +1123,17 @@ for (i = 0; i < n_target_val; i++) {
> >  }
> >  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]);";
> > +
> > +for (i = 0; i < n_target_other; i++) {
> > +	if (var_target_other[i] in var_target_explicit_mask)
> > +		print "  hstate.add_hwi (ptr->explicit_mask_" var_target_other[i] ");";
> > +}
> > +
> > +for (i = 0; i < n_target_int; i++) {
> > +	if (var_target_int[i] in var_target_explicit_mask)
> > +		print "  hstate.add_hwi (ptr->explicit_mask_" var_target_int[i] ");";
> > +}
> > +
> >  print "  return hstate.end ();";
> >  print "}";
> >  
> > 

	Jakub


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] options: Save and restore opts_set for Optimization and Target options
  2020-10-03  8:41                     ` Jakub Jelinek
@ 2020-10-03 18:02                       ` Richard Biener
  0 siblings, 0 replies; 29+ messages in thread
From: Richard Biener @ 2020-10-03 18:02 UTC (permalink / raw)
  To: Jakub Jelinek, Stefan Schulze Frielinghaus
  Cc: gcc-patches, Richard Earnshaw, Joseph S. Myers

On October 3, 2020 10:41:26 AM GMT+02:00, Jakub Jelinek <jakub@redhat.com> wrote:
>On Fri, Oct 02, 2020 at 04:21:12PM +0200, Stefan Schulze Frielinghaus
>via Gcc-patches wrote:
>> > > Sure, no problem at all.  In that case I stop to investigate
>further and
>> > > wait for you.
>> > 
>> > Here is a patch that implements that.
>> > 
>> > Can you please check if it fixes the s390x regressions that I
>couldn't
>> > reproduce in a cross?
>> 
>> Bootstrapped and regtested on S/390. Now all tattr-*.c test cases run
>> successfully with the patch. All other tests remain the same.
>
>I've now also successfully tested it on
>{x86_64,i686,armv7hl,aarch64,powerpc64le,s390x.  Ok for trunk?

OK. 

Richard. 

>> > 2020-10-02  Jakub Jelinek  <jakub@redhat.com>
>> > 
>> > 	* opth-gen.awk: For variables referenced in Mask and InverseMask,
>> > 	don't use the explicit_mask bitmask array, but add separate
>> > 	explicit_mask_* members with the same types as the variables.
>> > 	* optc-save-gen.awk: Save, restore, compare and hash the separate
>> > 	explicit_mask_* members.
>> > 
>> > --- gcc/opth-gen.awk.jj	2020-09-14 09:04:35.866854351 +0200
>> > +++ gcc/opth-gen.awk	2020-10-01 21:52:30.855122749 +0200
>> > @@ -209,6 +209,7 @@ n_target_int = 0;
>> >  n_target_enum = 0;
>> >  n_target_other = 0;
>> >  n_target_explicit = n_extra_target_vars;
>> > +n_target_explicit_mask = 0;
>> >  
>> >  for (i = 0; i < n_target_save; i++) {
>> >  	if (target_save_decl[i] ~ "^((un)?signed +)?int +[_" alnum "]+$")
>> > @@ -240,6 +241,12 @@ if (have_save) {
>> >  			var_save_seen[name]++;
>> >  			n_target_explicit++;
>> >  			otype = var_type_struct(flags[i])
>> > +
>> > +			if (opt_args("Mask", flags[i]) != "" \
>> > +			    || opt_args("InverseMask", flags[i]))
>> > +				var_target_explicit_mask[n_target_explicit_mask++] \
>> > +				    = otype "explicit_mask_" name;
>> > +
>> >  			if (otype ~ "^((un)?signed +)?int *$")
>> >  				var_target_int[n_target_int++] = otype "x_" name;
>> >  
>> > @@ -259,6 +266,8 @@ if (have_save) {
>> >  } else {
>> >  	var_target_int[n_target_int++] = "int x_target_flags";
>> >  	n_target_explicit++;
>> > +	var_target_explicit_mask[n_target_explicit_mask++] \
>> > +	    = "int explicit_mask_target_flags";
>> >  }
>> >  
>> >  for (i = 0; i < n_target_other; i++) {
>> > @@ -281,8 +290,12 @@ 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 "  /* " n_target_explicit - n_target_explicit_mask " members
>*/";
>> > +print "  unsigned HOST_WIDE_INT explicit_mask[" int
>((n_target_explicit - n_target_explicit_mask + 63) / 64) "];";
>> > +
>> > +for (i = 0; i < n_target_explicit_mask; i++) {
>> > +	print "  " var_target_explicit_mask[i] ";";
>> > +}
>> >  
>> >  print "};";
>> >  print "";
>> > --- gcc/optc-save-gen.awk.jj	2020-09-16 10:06:23.018093486 +0200
>> > +++ gcc/optc-save-gen.awk	2020-10-01 21:48:10.933868862 +0200
>> > @@ -516,6 +516,10 @@ if (have_save) {
>> >  
>> >  			var_save_seen[name]++;
>> >  			otype = var_type_struct(flags[i])
>> > +			if (opt_args("Mask", flags[i]) != "" \
>> > +			    || opt_args("InverseMask", flags[i]))
>> > +				var_target_explicit_mask[name] = 1;
>> > +
>> >  			if (otype ~ "^((un)?signed +)?int *$")
>> >  				var_target_int[n_target_int++] = name;
>> >  
>> > @@ -545,6 +549,7 @@ if (have_save) {
>> >  	}
>> >  } else {
>> >  	var_target_int[n_target_int++] = "target_flags";
>> > +	var_target_explicit_mask["target_flags"] = 1;
>> >  }
>> >  
>> >  have_assert = 0;
>> > @@ -608,6 +613,10 @@ for (i = 0; i < n_extra_target_vars; i++
>> >  }
>> >  
>> >  for (i = 0; i < n_target_other; i++) {
>> > +	if (var_target_other[i] in var_target_explicit_mask) {
>> > +		print "  ptr->explicit_mask_" var_target_other[i] " =
>opts_set->x_" var_target_other[i] ";";
>> > +		continue;
>> > +	}
>> >  	print "  if (opts_set->x_" var_target_other[i] ") mask |=
>HOST_WIDE_INT_1U << " j ";";
>> >  	j++;
>> >  	if (j == 64) {
>> > @@ -630,6 +639,10 @@ for (i = 0; i < n_target_enum; i++) {
>> >  }
>> >  
>> >  for (i = 0; i < n_target_int; i++) {
>> > +	if (var_target_int[i] in var_target_explicit_mask) {
>> > +		print "  ptr->explicit_mask_" var_target_int[i] " =
>opts_set->x_" var_target_int[i] ";";
>> > +		continue;
>> > +	}
>> >  	print "  if (opts_set->x_" var_target_int[i] ") mask |=
>HOST_WIDE_INT_1U << " j ";";
>> >  	j++;
>> >  	if (j == 64) {
>> > @@ -739,6 +752,10 @@ for (i = 0; i < n_extra_target_vars; i++
>> >  }
>> >  
>> >  for (i = 0; i < n_target_other; i++) {
>> > +	if (var_target_other[i] in var_target_explicit_mask) {
>> > +		print "  opts_set->x_" var_target_other[i] " =
>ptr->explicit_mask_" var_target_other[i] ";";
>> > +		continue;
>> > +	}
>> >  	if (j == 64) {
>> >  		print "  mask = ptr->explicit_mask[" k "];";
>> >  		k++;
>> > @@ -761,6 +778,10 @@ for (i = 0; i < n_target_enum; i++) {
>> >  }
>> >  
>> >  for (i = 0; i < n_target_int; i++) {
>> > +	if (var_target_int[i] in var_target_explicit_mask) {
>> > +		print "  opts_set->x_" var_target_int[i] " =
>ptr->explicit_mask_" var_target_int[i] ";";
>> > +		continue;
>> > +	}
>> >  	if (j == 64) {
>> >  		print "  mask = ptr->explicit_mask[" k "];";
>> >  		k++;
>> > @@ -1058,6 +1079,20 @@ print "  for (size_t i = 0; i < sizeof (
>> >  print "    if (ptr1->explicit_mask[i] != ptr2->explicit_mask[i])";
>> >  print "      return false;"
>> >  
>> > +for (i = 0; i < n_target_other; i++) {
>> > +	if (var_target_other[i] in var_target_explicit_mask) {
>> > +		print "  if (ptr1->explicit_mask_" var_target_other[i] " !=
>ptr2->explicit_mask_" var_target_other[i] ")";
>> > +		print "    return false;";
>> > +	}
>> > +}
>> > +
>> > +for (i = 0; i < n_target_int; i++) {
>> > +	if (var_target_int[i] in var_target_explicit_mask) {
>> > +		print "  if (ptr1->explicit_mask_" var_target_int[i] " !=
>ptr2->explicit_mask_" var_target_int[i] ")";
>> > +		print "    return false;";
>> > +	}
>> > +}
>> > +
>> >  print "  return true;";
>> >  
>> >  print "}";
>> > @@ -1088,6 +1123,17 @@ for (i = 0; i < n_target_val; i++) {
>> >  }
>> >  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]);";
>> > +
>> > +for (i = 0; i < n_target_other; i++) {
>> > +	if (var_target_other[i] in var_target_explicit_mask)
>> > +		print "  hstate.add_hwi (ptr->explicit_mask_"
>var_target_other[i] ");";
>> > +}
>> > +
>> > +for (i = 0; i < n_target_int; i++) {
>> > +	if (var_target_int[i] in var_target_explicit_mask)
>> > +		print "  hstate.add_hwi (ptr->explicit_mask_" var_target_int[i]
>");";
>> > +}
>> > +
>> >  print "  return hstate.end ();";
>> >  print "}";
>> >  
>> > 
>
>	Jakub


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] options: Save and restore opts_set for Optimization and Target options
  2020-10-02  8:46                 ` Jakub Jelinek
  2020-10-02 14:21                   ` Stefan Schulze Frielinghaus
@ 2020-10-04  7:13                   ` Andreas Schwab
  2020-10-04 19:16                     ` Jakub Jelinek
  1 sibling, 1 reply; 29+ messages in thread
From: Andreas Schwab @ 2020-10-04  7:13 UTC (permalink / raw)
  To: Jakub Jelinek via Gcc-patches
  Cc: Stefan Schulze Frielinghaus, Jakub Jelinek, Richard Biener,
	Richard Earnshaw, Joseph S. Myers

This breaks ia64:

In file included from ./tm.h:23,
                 from ../../gcc/gencheck.c:23:
./options.h:7816:40: error: ISO C++ forbids zero-size array 'explicit_mask' [-Werror=pedantic]
 7816 |   unsigned HOST_WIDE_INT explicit_mask[0];
      |                                        ^
./options.h:7816:26: error: zero-size array member 'cl_target_option::explicit_mask' not at end of 'struct cl_target_option' [-Werror=pedantic]
 7816 |   unsigned HOST_WIDE_INT explicit_mask[0];
      |                          ^~~~~~~~~~~~~
./options.h:7812:16: note: in the definition of 'struct cl_target_option'
 7812 | struct GTY(()) cl_target_option
      |                ^~~~~~~~~~~~~~~~

$ diff -u gcc-2020100[34]/Build/gcc/options.h
--- gcc-20201003/Build/gcc/options.h    2020-10-03 04:50:58.000000000 +0200
+++ gcc-20201004/Build/gcc/options.h    2020-10-04 04:25:18.000000000 +0200
@@ -7812,8 +7812,9 @@
 struct GTY(()) cl_target_option
 {
   int x_target_flags;
-  /* 1 members */
-  unsigned HOST_WIDE_INT explicit_mask[1];
+  /* 0 members */
+  unsigned HOST_WIDE_INT explicit_mask[0];
+  int explicit_mask_target_flags;
 };
 
 

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] options: Save and restore opts_set for Optimization and Target options
  2020-10-04  7:13                   ` Andreas Schwab
@ 2020-10-04 19:16                     ` Jakub Jelinek
  2020-10-05  7:08                       ` Jakub Jelinek
  2020-10-06  9:28                       ` Andreas Schwab
  0 siblings, 2 replies; 29+ messages in thread
From: Jakub Jelinek @ 2020-10-04 19:16 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: Jakub Jelinek via Gcc-patches, Richard Biener, Richard Earnshaw,
	Joseph S. Myers

On Sun, Oct 04, 2020 at 09:13:29AM +0200, Andreas Schwab wrote:
> This breaks ia64:
> 
> In file included from ./tm.h:23,
>                  from ../../gcc/gencheck.c:23:
> ./options.h:7816:40: error: ISO C++ forbids zero-size array 'explicit_mask' [-Werror=pedantic]
>  7816 |   unsigned HOST_WIDE_INT explicit_mask[0];
>       |                                        ^
> ./options.h:7816:26: error: zero-size array member 'cl_target_option::explicit_mask' not at end of 'struct cl_target_option' [-Werror=pedantic]
>  7816 |   unsigned HOST_WIDE_INT explicit_mask[0];
>       |                          ^~~~~~~~~~~~~
> ./options.h:7812:16: note: in the definition of 'struct cl_target_option'
>  7812 | struct GTY(()) cl_target_option
>       |                ^~~~~~~~~~~~~~~~

Oops, sorry.

The following patch should fix that and should also fix streaming of the
new explicit_mask_* members.
I'll bootstrap/regtest on x86_64-linux and i686-linux tonight, but have no
way to test it on ia64-linux (well, tested that x86_64-linux -> ia64-linux
cross builds cc1 with it).

2020-10-04  Jakub Jelinek  <jakub@redhat.com>

	* opth-gen.awk: Don't emit explicit_mask array if n_target_explicit
	is equal to n_target_explicit_mask.
	* optc-save-gen.awk: Compute has_target_explicit_mask and if false,
	don't emit code iterating over explicit_mask array elements.  Stream
	also explicit_mask_* target members.

--- gcc/opth-gen.awk.jj	2020-10-03 21:21:59.727862692 +0200
+++ gcc/opth-gen.awk	2020-10-04 11:12:51.851906413 +0200
@@ -291,7 +291,10 @@ for (i = 0; i < n_target_char; i++) {
 }
 
 print "  /* " n_target_explicit - n_target_explicit_mask " members */";
-print "  unsigned HOST_WIDE_INT explicit_mask[" int ((n_target_explicit - n_target_explicit_mask + 63) / 64) "];";
+if (n_target_explicit > n_target_explicit_mask) {
+	print "  unsigned HOST_WIDE_INT explicit_mask[" \
+	  int ((n_target_explicit - n_target_explicit_mask + 63) / 64) "];";
+}
 
 for (i = 0; i < n_target_explicit_mask; i++) {
 	print "  " var_target_explicit_mask[i] ";";
--- gcc/optc-save-gen.awk.jj	2020-10-03 21:21:59.728862678 +0200
+++ gcc/optc-save-gen.awk	2020-10-04 21:03:31.619462434 +0200
@@ -689,6 +689,10 @@ for (i = 0; i < n_target_string; i++) {
 if (j != 0) {
 	print "  ptr->explicit_mask[" k "] = mask;";
 }
+has_target_explicit_mask = 0;
+if (j != 0 || k != 0) {
+	has_target_explicit_mask = 1;
+}
 
 print "}";
 
@@ -1075,9 +1079,11 @@ 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;"
+if (has_target_explicit_mask) {
+	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;"
+}
 
 for (i = 0; i < n_target_other; i++) {
 	if (var_target_other[i] in var_target_explicit_mask) {
@@ -1121,8 +1127,10 @@ 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]);";
+if (has_target_explicit_mask) {
+	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]);";
+}
 
 for (i = 0; i < n_target_other; i++) {
 	if (var_target_other[i] in var_target_explicit_mask)
@@ -1159,8 +1167,22 @@ for (i = 0; i < n_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);";
+if (has_target_explicit_mask) {
+	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);";
+}
+
+for (i = 0; i < n_target_other; i++) {
+	if (var_target_other[i] in var_target_explicit_mask) {
+		print "  bp_pack_value (bp, ptr->explicit_mask_" var_target_other[i] ", 64);";
+	}
+}
+
+for (i = 0; i < n_target_int; i++) {
+	if (var_target_int[i] in var_target_explicit_mask) {
+		print "  bp_pack_value (bp, ptr->explicit_mask_" var_target_int[i] ", 64);";
+	}
+}
 
 print "}";
 
@@ -1188,8 +1210,22 @@ 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);";
+if (has_target_explicit_mask) {
+	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);";
+}
+
+for (i = 0; i < n_target_other; i++) {
+	if (var_target_other[i] in var_target_explicit_mask) {
+		print "  ptr->explicit_mask_" var_target_other[i] " = bp_unpack_value (bp, 64);";
+	}
+}
+
+for (i = 0; i < n_target_int; i++) {
+	if (var_target_int[i] in var_target_explicit_mask) {
+		print "  ptr->explicit_mask_" var_target_int[i] " = bp_unpack_value (bp, 64);";
+	}
+}
 
 print "}";
 


	Jakub


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] options: Save and restore opts_set for Optimization and Target options
  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
  1 sibling, 1 reply; 29+ messages in thread
From: Jakub Jelinek @ 2020-10-05  7:08 UTC (permalink / raw)
  To: Richard Biener; +Cc: gcc-patches

On Sun, Oct 04, 2020 at 09:16:00PM +0200, Jakub Jelinek via Gcc-patches wrote:
> On Sun, Oct 04, 2020 at 09:13:29AM +0200, Andreas Schwab wrote:
> > This breaks ia64:
> > 
> > In file included from ./tm.h:23,
> >                  from ../../gcc/gencheck.c:23:
> > ./options.h:7816:40: error: ISO C++ forbids zero-size array 'explicit_mask' [-Werror=pedantic]
> >  7816 |   unsigned HOST_WIDE_INT explicit_mask[0];
> >       |                                        ^
> > ./options.h:7816:26: error: zero-size array member 'cl_target_option::explicit_mask' not at end of 'struct cl_target_option' [-Werror=pedantic]
> >  7816 |   unsigned HOST_WIDE_INT explicit_mask[0];
> >       |                          ^~~~~~~~~~~~~
> > ./options.h:7812:16: note: in the definition of 'struct cl_target_option'
> >  7812 | struct GTY(()) cl_target_option
> >       |                ^~~~~~~~~~~~~~~~
> 
> Oops, sorry.
> 
> The following patch should fix that and should also fix streaming of the
> new explicit_mask_* members.
> I'll bootstrap/regtest on x86_64-linux and i686-linux tonight, but have no
> way to test it on ia64-linux (well, tested that x86_64-linux -> ia64-linux
> cross builds cc1 with it).

Successfully bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk?

> 2020-10-04  Jakub Jelinek  <jakub@redhat.com>
> 
> 	* opth-gen.awk: Don't emit explicit_mask array if n_target_explicit
> 	is equal to n_target_explicit_mask.
> 	* optc-save-gen.awk: Compute has_target_explicit_mask and if false,
> 	don't emit code iterating over explicit_mask array elements.  Stream
> 	also explicit_mask_* target members.
> 
> --- gcc/opth-gen.awk.jj	2020-10-03 21:21:59.727862692 +0200
> +++ gcc/opth-gen.awk	2020-10-04 11:12:51.851906413 +0200
> @@ -291,7 +291,10 @@ for (i = 0; i < n_target_char; i++) {
>  }
>  
>  print "  /* " n_target_explicit - n_target_explicit_mask " members */";
> -print "  unsigned HOST_WIDE_INT explicit_mask[" int ((n_target_explicit - n_target_explicit_mask + 63) / 64) "];";
> +if (n_target_explicit > n_target_explicit_mask) {
> +	print "  unsigned HOST_WIDE_INT explicit_mask[" \
> +	  int ((n_target_explicit - n_target_explicit_mask + 63) / 64) "];";
> +}
>  
>  for (i = 0; i < n_target_explicit_mask; i++) {
>  	print "  " var_target_explicit_mask[i] ";";
> --- gcc/optc-save-gen.awk.jj	2020-10-03 21:21:59.728862678 +0200
> +++ gcc/optc-save-gen.awk	2020-10-04 21:03:31.619462434 +0200
> @@ -689,6 +689,10 @@ for (i = 0; i < n_target_string; i++) {
>  if (j != 0) {
>  	print "  ptr->explicit_mask[" k "] = mask;";
>  }
> +has_target_explicit_mask = 0;
> +if (j != 0 || k != 0) {
> +	has_target_explicit_mask = 1;
> +}
>  
>  print "}";
>  
> @@ -1075,9 +1079,11 @@ 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;"
> +if (has_target_explicit_mask) {
> +	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;"
> +}
>  
>  for (i = 0; i < n_target_other; i++) {
>  	if (var_target_other[i] in var_target_explicit_mask) {
> @@ -1121,8 +1127,10 @@ 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]);";
> +if (has_target_explicit_mask) {
> +	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]);";
> +}
>  
>  for (i = 0; i < n_target_other; i++) {
>  	if (var_target_other[i] in var_target_explicit_mask)
> @@ -1159,8 +1167,22 @@ for (i = 0; i < n_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);";
> +if (has_target_explicit_mask) {
> +	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);";
> +}
> +
> +for (i = 0; i < n_target_other; i++) {
> +	if (var_target_other[i] in var_target_explicit_mask) {
> +		print "  bp_pack_value (bp, ptr->explicit_mask_" var_target_other[i] ", 64);";
> +	}
> +}
> +
> +for (i = 0; i < n_target_int; i++) {
> +	if (var_target_int[i] in var_target_explicit_mask) {
> +		print "  bp_pack_value (bp, ptr->explicit_mask_" var_target_int[i] ", 64);";
> +	}
> +}
>  
>  print "}";
>  
> @@ -1188,8 +1210,22 @@ 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);";
> +if (has_target_explicit_mask) {
> +	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);";
> +}
> +
> +for (i = 0; i < n_target_other; i++) {
> +	if (var_target_other[i] in var_target_explicit_mask) {
> +		print "  ptr->explicit_mask_" var_target_other[i] " = bp_unpack_value (bp, 64);";
> +	}
> +}
> +
> +for (i = 0; i < n_target_int; i++) {
> +	if (var_target_int[i] in var_target_explicit_mask) {
> +		print "  ptr->explicit_mask_" var_target_int[i] " = bp_unpack_value (bp, 64);";
> +	}
> +}
>  
>  print "}";
>  

	Jakub


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] options: Save and restore opts_set for Optimization and Target options
  2020-10-05  7:08                       ` Jakub Jelinek
@ 2020-10-05  7:10                         ` Richard Biener
  0 siblings, 0 replies; 29+ messages in thread
From: Richard Biener @ 2020-10-05  7:10 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches

On October 5, 2020 9:08:41 AM GMT+02:00, Jakub Jelinek <jakub@redhat.com> wrote:
>On Sun, Oct 04, 2020 at 09:16:00PM +0200, Jakub Jelinek via Gcc-patches
>wrote:
>> On Sun, Oct 04, 2020 at 09:13:29AM +0200, Andreas Schwab wrote:
>> > This breaks ia64:
>> > 
>> > In file included from ./tm.h:23,
>> >                  from ../../gcc/gencheck.c:23:
>> > ./options.h:7816:40: error: ISO C++ forbids zero-size array
>'explicit_mask' [-Werror=pedantic]
>> >  7816 |   unsigned HOST_WIDE_INT explicit_mask[0];
>> >       |                                        ^
>> > ./options.h:7816:26: error: zero-size array member
>'cl_target_option::explicit_mask' not at end of 'struct
>cl_target_option' [-Werror=pedantic]
>> >  7816 |   unsigned HOST_WIDE_INT explicit_mask[0];
>> >       |                          ^~~~~~~~~~~~~
>> > ./options.h:7812:16: note: in the definition of 'struct
>cl_target_option'
>> >  7812 | struct GTY(()) cl_target_option
>> >       |                ^~~~~~~~~~~~~~~~
>> 
>> Oops, sorry.
>> 
>> The following patch should fix that and should also fix streaming of
>the
>> new explicit_mask_* members.
>> I'll bootstrap/regtest on x86_64-linux and i686-linux tonight, but
>have no
>> way to test it on ia64-linux (well, tested that x86_64-linux ->
>ia64-linux
>> cross builds cc1 with it).
>
>Successfully bootstrapped/regtested on x86_64-linux and i686-linux, ok
>for
>trunk?

OK. 

Richard. 

>> 2020-10-04  Jakub Jelinek  <jakub@redhat.com>
>> 
>> 	* opth-gen.awk: Don't emit explicit_mask array if n_target_explicit
>> 	is equal to n_target_explicit_mask.
>> 	* optc-save-gen.awk: Compute has_target_explicit_mask and if false,
>> 	don't emit code iterating over explicit_mask array elements.  Stream
>> 	also explicit_mask_* target members.
>> 
>> --- gcc/opth-gen.awk.jj	2020-10-03 21:21:59.727862692 +0200
>> +++ gcc/opth-gen.awk	2020-10-04 11:12:51.851906413 +0200
>> @@ -291,7 +291,10 @@ for (i = 0; i < n_target_char; i++) {
>>  }
>>  
>>  print "  /* " n_target_explicit - n_target_explicit_mask " members
>*/";
>> -print "  unsigned HOST_WIDE_INT explicit_mask[" int
>((n_target_explicit - n_target_explicit_mask + 63) / 64) "];";
>> +if (n_target_explicit > n_target_explicit_mask) {
>> +	print "  unsigned HOST_WIDE_INT explicit_mask[" \
>> +	  int ((n_target_explicit - n_target_explicit_mask + 63) / 64)
>"];";
>> +}
>>  
>>  for (i = 0; i < n_target_explicit_mask; i++) {
>>  	print "  " var_target_explicit_mask[i] ";";
>> --- gcc/optc-save-gen.awk.jj	2020-10-03 21:21:59.728862678 +0200
>> +++ gcc/optc-save-gen.awk	2020-10-04 21:03:31.619462434 +0200
>> @@ -689,6 +689,10 @@ for (i = 0; i < n_target_string; i++) {
>>  if (j != 0) {
>>  	print "  ptr->explicit_mask[" k "] = mask;";
>>  }
>> +has_target_explicit_mask = 0;
>> +if (j != 0 || k != 0) {
>> +	has_target_explicit_mask = 1;
>> +}
>>  
>>  print "}";
>>  
>> @@ -1075,9 +1079,11 @@ 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;"
>> +if (has_target_explicit_mask) {
>> +	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;"
>> +}
>>  
>>  for (i = 0; i < n_target_other; i++) {
>>  	if (var_target_other[i] in var_target_explicit_mask) {
>> @@ -1121,8 +1127,10 @@ 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]);";
>> +if (has_target_explicit_mask) {
>> +	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]);";
>> +}
>>  
>>  for (i = 0; i < n_target_other; i++) {
>>  	if (var_target_other[i] in var_target_explicit_mask)
>> @@ -1159,8 +1167,22 @@ for (i = 0; i < n_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);";
>> +if (has_target_explicit_mask) {
>> +	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);";
>> +}
>> +
>> +for (i = 0; i < n_target_other; i++) {
>> +	if (var_target_other[i] in var_target_explicit_mask) {
>> +		print "  bp_pack_value (bp, ptr->explicit_mask_"
>var_target_other[i] ", 64);";
>> +	}
>> +}
>> +
>> +for (i = 0; i < n_target_int; i++) {
>> +	if (var_target_int[i] in var_target_explicit_mask) {
>> +		print "  bp_pack_value (bp, ptr->explicit_mask_" var_target_int[i]
>", 64);";
>> +	}
>> +}
>>  
>>  print "}";
>>  
>> @@ -1188,8 +1210,22 @@ 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);";
>> +if (has_target_explicit_mask) {
>> +	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);";
>> +}
>> +
>> +for (i = 0; i < n_target_other; i++) {
>> +	if (var_target_other[i] in var_target_explicit_mask) {
>> +		print "  ptr->explicit_mask_" var_target_other[i] " =
>bp_unpack_value (bp, 64);";
>> +	}
>> +}
>> +
>> +for (i = 0; i < n_target_int; i++) {
>> +	if (var_target_int[i] in var_target_explicit_mask) {
>> +		print "  ptr->explicit_mask_" var_target_int[i] " =
>bp_unpack_value (bp, 64);";
>> +	}
>> +}
>>  
>>  print "}";
>>  
>
>	Jakub


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] options: Save and restore opts_set for Optimization and Target options
  2020-10-04 19:16                     ` Jakub Jelinek
  2020-10-05  7:08                       ` Jakub Jelinek
@ 2020-10-06  9:28                       ` Andreas Schwab
  2020-10-06 13:20                         ` [PATCH] options: Avoid unused variable mask warning [PR97305] Jakub Jelinek
  1 sibling, 1 reply; 29+ messages in thread
From: Andreas Schwab @ 2020-10-06  9:28 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Jakub Jelinek via Gcc-patches, Richard Biener, Richard Earnshaw,
	Joseph S. Myers

options-save.c: In function 'void cl_target_option_save(cl_target_option*, gcc_options*, gcc_options*)':
options-save.c:8526:26: error: unused variable 'mask' [-Werror=unused-variable]
 8526 |   unsigned HOST_WIDE_INT mask = 0;
      |                          ^~~~
options-save.c: In function 'void cl_target_option_restore(gcc_options*, gcc_options*, cl_target_option*)':
options-save.c:8537:26: error: unused variable 'mask' [-Werror=unused-variable]
 8537 |   unsigned HOST_WIDE_INT mask;
      |                          ^~~~

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH] options: Avoid unused variable mask warning [PR97305]
  2020-10-06  9:28                       ` Andreas Schwab
@ 2020-10-06 13:20                         ` Jakub Jelinek
  2020-10-06 13:32                           ` Richard Biener
  0 siblings, 1 reply; 29+ messages in thread
From: Jakub Jelinek @ 2020-10-06 13:20 UTC (permalink / raw)
  To: Richard Biener, Andreas Schwab; +Cc: gcc-patches

Hi!

On Tue, Oct 06, 2020 at 11:28:22AM +0200, Andreas Schwab wrote:
> options-save.c: In function 'void cl_target_option_save(cl_target_option*, gcc_options*, gcc_options*)':
> options-save.c:8526:26: error: unused variable 'mask' [-Werror=unused-variable]
>  8526 |   unsigned HOST_WIDE_INT mask = 0;
>       |                          ^~~~
> options-save.c: In function 'void cl_target_option_restore(gcc_options*, gcc_options*, cl_target_option*)':
> options-save.c:8537:26: error: unused variable 'mask' [-Werror=unused-variable]
>  8537 |   unsigned HOST_WIDE_INT mask;
>       |                          ^~~~

Oops, missed that, sorry.

The following patch should fix that, tested on x86_64-linux make
options-save.c (same file as before) and -> ia64-linux cross make
options-save.o (no warning anymore, just the unwanted declarations gone).

Ok for trunk if it passes bootstrap/regtest?

2020-10-06  Jakub Jelinek  <jakub@redhat.com>

	PR bootstrap/97305
	* optc-save-gen.awk: Don't declare mask variable if explicit_mask
	array is not present.

--- gcc/optc-save-gen.awk.jj	2020-10-05 09:34:26.561874335 +0200
+++ gcc/optc-save-gen.awk	2020-10-06 14:44:04.679556591 +0200
@@ -597,11 +597,13 @@ for (i = 0; i < n_target_string; i++) {
 }
 
 print "";
-print "  unsigned HOST_WIDE_INT mask = 0;";
 
 j = 0;
 k = 0;
 for (i = 0; i < n_extra_target_vars; i++) {
+	if (j == 0 && k == 0) {
+		print "  unsigned HOST_WIDE_INT mask = 0;";
+	}
 	print "  if (opts_set->x_" extra_target_vars[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
 	j++;
 	if (j == 64) {
@@ -617,6 +619,9 @@ for (i = 0; i < n_target_other; i++) {
 		print "  ptr->explicit_mask_" var_target_other[i] " = opts_set->x_" var_target_other[i] ";";
 		continue;
 	}
+	if (j == 0 && k == 0) {
+		print "  unsigned HOST_WIDE_INT mask = 0;";
+	}
 	print "  if (opts_set->x_" var_target_other[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
 	j++;
 	if (j == 64) {
@@ -628,6 +633,9 @@ for (i = 0; i < n_target_other; i++) {
 }
 
 for (i = 0; i < n_target_enum; i++) {
+	if (j == 0 && k == 0) {
+		print "  unsigned HOST_WIDE_INT mask = 0;";
+	}
 	print "  if (opts_set->x_" var_target_enum[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
 	j++;
 	if (j == 64) {
@@ -643,6 +651,9 @@ for (i = 0; i < n_target_int; i++) {
 		print "  ptr->explicit_mask_" var_target_int[i] " = opts_set->x_" var_target_int[i] ";";
 		continue;
 	}
+	if (j == 0 && k == 0) {
+		print "  unsigned HOST_WIDE_INT mask = 0;";
+	}
 	print "  if (opts_set->x_" var_target_int[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
 	j++;
 	if (j == 64) {
@@ -654,6 +665,9 @@ for (i = 0; i < n_target_int; i++) {
 }
 
 for (i = 0; i < n_target_short; i++) {
+	if (j == 0 && k == 0) {
+		print "  unsigned HOST_WIDE_INT mask = 0;";
+	}
 	print "  if (opts_set->x_" var_target_short[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
 	j++;
 	if (j == 64) {
@@ -665,6 +679,9 @@ for (i = 0; i < n_target_short; i++) {
 }
 
 for (i = 0; i < n_target_char; i++) {
+	if (j == 0 && k == 0) {
+		print "  unsigned HOST_WIDE_INT mask = 0;";
+	}
 	print "  if (opts_set->x_" var_target_char[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
 	j++;
 	if (j == 64) {
@@ -676,6 +693,9 @@ for (i = 0; i < n_target_char; i++) {
 }
 
 for (i = 0; i < n_target_string; i++) {
+	if (j == 0 && k == 0) {
+		print "  unsigned HOST_WIDE_INT mask = 0;";
+	}
 	print "  if (opts_set->x_" var_target_string[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
 	j++;
 	if (j == 64) {
@@ -732,7 +752,9 @@ for (i = 0; i < n_target_string; i++) {
 }
 
 print "";
-print "  unsigned HOST_WIDE_INT mask;";
+if (has_target_explicit_mask) {
+	print "  unsigned HOST_WIDE_INT mask;";
+}
 
 j = 64;
 k = 0;


	Jakub


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] options: Avoid unused variable mask warning [PR97305]
  2020-10-06 13:20                         ` [PATCH] options: Avoid unused variable mask warning [PR97305] Jakub Jelinek
@ 2020-10-06 13:32                           ` Richard Biener
  0 siblings, 0 replies; 29+ messages in thread
From: Richard Biener @ 2020-10-06 13:32 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Andreas Schwab, gcc-patches

On Tue, 6 Oct 2020, Jakub Jelinek wrote:

> Hi!
> 
> On Tue, Oct 06, 2020 at 11:28:22AM +0200, Andreas Schwab wrote:
> > options-save.c: In function 'void cl_target_option_save(cl_target_option*, gcc_options*, gcc_options*)':
> > options-save.c:8526:26: error: unused variable 'mask' [-Werror=unused-variable]
> >  8526 |   unsigned HOST_WIDE_INT mask = 0;
> >       |                          ^~~~
> > options-save.c: In function 'void cl_target_option_restore(gcc_options*, gcc_options*, cl_target_option*)':
> > options-save.c:8537:26: error: unused variable 'mask' [-Werror=unused-variable]
> >  8537 |   unsigned HOST_WIDE_INT mask;
> >       |                          ^~~~
> 
> Oops, missed that, sorry.
> 
> The following patch should fix that, tested on x86_64-linux make
> options-save.c (same file as before) and -> ia64-linux cross make
> options-save.o (no warning anymore, just the unwanted declarations gone).
> 
> Ok for trunk if it passes bootstrap/regtest?

OK.

Richard.

> 2020-10-06  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR bootstrap/97305
> 	* optc-save-gen.awk: Don't declare mask variable if explicit_mask
> 	array is not present.
> 
> --- gcc/optc-save-gen.awk.jj	2020-10-05 09:34:26.561874335 +0200
> +++ gcc/optc-save-gen.awk	2020-10-06 14:44:04.679556591 +0200
> @@ -597,11 +597,13 @@ for (i = 0; i < n_target_string; i++) {
>  }
>  
>  print "";
> -print "  unsigned HOST_WIDE_INT mask = 0;";
>  
>  j = 0;
>  k = 0;
>  for (i = 0; i < n_extra_target_vars; i++) {
> +	if (j == 0 && k == 0) {
> +		print "  unsigned HOST_WIDE_INT mask = 0;";
> +	}
>  	print "  if (opts_set->x_" extra_target_vars[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
>  	j++;
>  	if (j == 64) {
> @@ -617,6 +619,9 @@ for (i = 0; i < n_target_other; i++) {
>  		print "  ptr->explicit_mask_" var_target_other[i] " = opts_set->x_" var_target_other[i] ";";
>  		continue;
>  	}
> +	if (j == 0 && k == 0) {
> +		print "  unsigned HOST_WIDE_INT mask = 0;";
> +	}
>  	print "  if (opts_set->x_" var_target_other[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
>  	j++;
>  	if (j == 64) {
> @@ -628,6 +633,9 @@ for (i = 0; i < n_target_other; i++) {
>  }
>  
>  for (i = 0; i < n_target_enum; i++) {
> +	if (j == 0 && k == 0) {
> +		print "  unsigned HOST_WIDE_INT mask = 0;";
> +	}
>  	print "  if (opts_set->x_" var_target_enum[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
>  	j++;
>  	if (j == 64) {
> @@ -643,6 +651,9 @@ for (i = 0; i < n_target_int; i++) {
>  		print "  ptr->explicit_mask_" var_target_int[i] " = opts_set->x_" var_target_int[i] ";";
>  		continue;
>  	}
> +	if (j == 0 && k == 0) {
> +		print "  unsigned HOST_WIDE_INT mask = 0;";
> +	}
>  	print "  if (opts_set->x_" var_target_int[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
>  	j++;
>  	if (j == 64) {
> @@ -654,6 +665,9 @@ for (i = 0; i < n_target_int; i++) {
>  }
>  
>  for (i = 0; i < n_target_short; i++) {
> +	if (j == 0 && k == 0) {
> +		print "  unsigned HOST_WIDE_INT mask = 0;";
> +	}
>  	print "  if (opts_set->x_" var_target_short[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
>  	j++;
>  	if (j == 64) {
> @@ -665,6 +679,9 @@ for (i = 0; i < n_target_short; i++) {
>  }
>  
>  for (i = 0; i < n_target_char; i++) {
> +	if (j == 0 && k == 0) {
> +		print "  unsigned HOST_WIDE_INT mask = 0;";
> +	}
>  	print "  if (opts_set->x_" var_target_char[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
>  	j++;
>  	if (j == 64) {
> @@ -676,6 +693,9 @@ for (i = 0; i < n_target_char; i++) {
>  }
>  
>  for (i = 0; i < n_target_string; i++) {
> +	if (j == 0 && k == 0) {
> +		print "  unsigned HOST_WIDE_INT mask = 0;";
> +	}
>  	print "  if (opts_set->x_" var_target_string[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
>  	j++;
>  	if (j == 64) {
> @@ -732,7 +752,9 @@ for (i = 0; i < n_target_string; i++) {
>  }
>  
>  print "";
> -print "  unsigned HOST_WIDE_INT mask;";
> +if (has_target_explicit_mask) {
> +	print "  unsigned HOST_WIDE_INT mask;";
> +}
>  
>  j = 64;
>  k = 0;
> 
> 
> 	Jakub
> 
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Felix Imend

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2020-10-06 13:32 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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
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

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).