On Tue, Jan 7, 2014 at 8:39 PM, Jakub Jelinek <ja...@redhat.com> wrote: > On Mon, Jan 06, 2014 at 10:27:06AM +0000, Richard Sandiford wrote: >> Of course, IMO, the cleanest fix would be to use switchable targets >> for i386... > > The following patch does that, bootstrapped/regtested on x86_64-linux and > i686-linux. The only problem with the patch is PCH, > +FAIL: 17_intro/headers/c++200x/stdc++.cc (test for excess errors) > +FAIL: 17_intro/headers/c++200x/stdc++_multiple_inclusion.cc (test for excess > errors) > (both 32-bit and 64-bit regtests), where it ICEs. I guess the problem is > that the target globals are allocated partly in GC, partly in heap and > even if they were allocated completely in GC and GTY(()) marked fully all > the individual pointed structures, we IMNSHO still don't want it to be > saved during PCH and restored later, what we have is basically just a cache > of the target globals. > > Dunno what is the best way to handle that though. > Either before writing PCH c-common.c could call some tree.c routine that > would traverse the cl_option_hash_table hash table and for every > TARGET_OPTION_NODE in the hash table clear TREE_TARGET_GLOBALS. > Or perhaps some gengtype extension to run some routine before PCH saving > on the tree_target_option structs and clear the globals field in there. > Or use GTY((user)) on tree_target_option, but then dunno how we'd handle the > marking of the embedded opts field (and common). > Any ideas?
Well, a GTY((skip_pch)) would probably work. Or move the thing out-of GC land (thus make cl_option_hash_table persistant) and simply GTY((skip)) the pointer completely. Not sure if we ever collect from it. Richard. > 2014-01-07 Jakub Jelinek <ja...@redhat.com> > > PR target/58115 > * tree-core.h (struct target_globals): New forward declaration. > (struct tree_target_option): Add globals field. > * tree.h (TREE_TARGET_GLOBALS): Define. > * target-globals.h (struct target_globals): Define even if > !SWITCHABLE_TARGET. > * config/i386/i386.h (SWITCHABLE_TARGET): Define. > * config/i386/i386.c: Include target-globals.h. > (ix86_set_current_function): Instead of doing target_reinit > unconditionally, use save_target_globals_default_opts and > restore_target_globals. > > --- gcc/tree-core.h.jj 2014-01-07 08:47:24.000000000 +0100 > +++ gcc/tree-core.h 2014-01-07 16:44:35.591358235 +0100 > @@ -1557,11 +1557,18 @@ struct GTY(()) tree_optimization_option > struct target_optabs *GTY ((skip)) base_optabs; > }; > > +/* Forward declaration, defined in target-globals.h. */ > + > +struct GTY(()) target_globals; > + > /* Target options used by a function. */ > > struct GTY(()) tree_target_option { > struct tree_common common; > > + /* Target globals for the corresponding target option. */ > + struct target_globals *globals; > + > /* The optimization options used by the user. */ > struct cl_target_option opts; > }; > --- gcc/tree.h.jj 2014-01-03 11:40:33.000000000 +0100 > +++ gcc/tree.h 2014-01-07 12:55:39.137295100 +0100 > @@ -2695,6 +2695,9 @@ extern tree build_optimization_node (str > #define TREE_TARGET_OPTION(NODE) \ > (&TARGET_OPTION_NODE_CHECK (NODE)->target_option.opts) > > +#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); > > --- gcc/target-globals.h.jj 2014-01-03 11:40:46.000000000 +0100 > +++ gcc/target-globals.h 2014-01-07 17:08:51.113880947 +0100 > @@ -37,6 +37,7 @@ extern struct target_builtins *this_targ > extern struct target_gcse *this_target_gcse; > extern struct target_bb_reorder *this_target_bb_reorder; > extern struct target_lower_subreg *this_target_lower_subreg; > +#endif > > struct GTY(()) target_globals { > struct target_flag_state *GTY((skip)) flag_state; > @@ -57,6 +58,7 @@ struct GTY(()) target_globals { > struct target_lower_subreg *GTY((skip)) lower_subreg; > }; > > +#if SWITCHABLE_TARGET > extern struct target_globals default_target_globals; > > extern struct target_globals *save_target_globals (void); > --- gcc/config/i386/i386.h.jj 2014-01-06 22:37:19.000000000 +0100 > +++ gcc/config/i386/i386.h 2014-01-07 12:13:06.480486755 +0100 > @@ -2510,6 +2510,9 @@ extern void debug_dispatch_window (int); > #define IX86_HLE_ACQUIRE (1 << 16) > #define IX86_HLE_RELEASE (1 << 17) > > +/* For switching between functions with different target attributes. */ > +#define SWITCHABLE_TARGET 1 > + > /* > Local variables: > version-control: t > --- gcc/config/i386/i386.c.jj 2014-01-06 22:37:19.000000000 +0100 > +++ gcc/config/i386/i386.c 2014-01-07 16:52:32.597904760 +0100 > @@ -80,6 +80,7 @@ along with GCC; see the file COPYING3. > #include "tree-pass.h" > #include "context.h" > #include "pass_manager.h" > +#include "target-globals.h" > > static rtx legitimize_dllimport_symbol (rtx, bool); > static rtx legitimize_pe_coff_extern_decl (rtx, bool); > @@ -4868,16 +4869,25 @@ ix86_set_current_function (tree fndecl) > { > cl_target_option_restore (&global_options, > TREE_TARGET_OPTION (new_tree)); > - target_reinit (); > + if (TREE_TARGET_GLOBALS (new_tree)) > + restore_target_globals (TREE_TARGET_GLOBALS (new_tree)); > + else > + TREE_TARGET_GLOBALS (new_tree) > + = save_target_globals_default_opts (); > } > > else if (old_tree) > { > - struct cl_target_option *def > - = TREE_TARGET_OPTION (target_option_current_node); > - > - cl_target_option_restore (&global_options, def); > - target_reinit (); > + new_tree = target_option_current_node; > + cl_target_option_restore (&global_options, > + 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) > + restore_target_globals (&default_target_globals); > + else > + TREE_TARGET_GLOBALS (new_tree) > + = save_target_globals_default_opts (); > } > } > } > > > Jakub