On Wed, Jan 8, 2014 at 1:45 PM, Jakub Jelinek <ja...@redhat.com> wrote:
> On Wed, Jan 08, 2014 at 12:32:59PM +0100, Richard Biener wrote:
>> > 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.
>
> Even if the pointer was out of GCC land and GTY((skip)), we'd need to clear
> it somewhere during PCH saving, as the containing structure is GC allocated.
>
> I've already implemented in the mean time the variant with the
> htab_traverse, all still reachable TARGET_OPTION_NODE trees should be in that
> hash table.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux (in both cases with
> --enable-checking=yes,rtl and --enable-checking=release, for the
> i686-linux/release checking I had to fix an unrelated compare debug issue
> I'll post when I manage to reduce testcase).
>
> I'd like to get rid of all the XCNEW calls in target-globals.c as a
> follow-up.
>
> As for performance, for --enable-checking=release from very rough check
> on make -j48 bootstrap and make -j48 check times the patch is compile time
> neutral, on e.g. declare-simd-1.C testcase g++ is twice as fast with the
> patch though (~ 0.8 sec without the patch, ~ 0.3 sec with the patch, both
> for x86_64 and i686).
>
> Ok for trunk?

Works for me.  Wait a bit for others to comment though.

Thanks,
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.
>         (prepare_target_option_nodes_for_pch): New prototype.
>         * target-globals.h (struct target_globals): Define even if
>         !SWITCHABLE_TARGET.
>         * tree.c (prepare_target_option_node_for_pch,
>         prepare_target_option_nodes_for_pch): New functions.
>         * 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.
> c-family/
>         * c-pch.c (c_common_write_pch): Call
>         prepare_target_option_nodes_for_pch.
>
> --- 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 21:28:15.038061120 +0100
> @@ -2695,9 +2695,14 @@ 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);
>
> +extern void prepare_target_option_nodes_for_pch (void);
> +
>  #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
>
>  inline tree
> --- 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/tree.c.jj       2014-01-03 11:40:33.000000000 +0100
> +++ gcc/tree.c  2014-01-07 21:27:35.590268195 +0100
> @@ -11527,6 +11527,28 @@ build_target_option_node (struct gcc_opt
>    return t;
>  }
>
> +/* Reset TREE_TARGET_GLOBALS cache for TARGET_OPTION_NODE.
> +   Called through htab_traverse.  */
> +
> +static int
> +prepare_target_option_node_for_pch (void **slot, void *)
> +{
> +  tree node = (tree) *slot;
> +  if (TREE_CODE (node) == TARGET_OPTION_NODE)
> +    TREE_TARGET_GLOBALS (node) = NULL;
> +  return 1;
> +}
> +
> +/* Clear TREE_TARGET_GLOBALS of all TARGET_OPTION_NODE trees,
> +   so that they aren't saved during PCH writing.  */
> +
> +void
> +prepare_target_option_nodes_for_pch (void)
> +{
> +  htab_traverse (cl_option_hash_table, prepare_target_option_node_for_pch,
> +                NULL);
> +}
> +
>  /* Determine the "ultimate origin" of a block.  The block may be an inlined
>     instance of an inlined instance of a block which is local to an inline
>     function, so we have to trace all of the way back through the origin chain
> --- gcc/c-family/c-pch.c.jj     2014-01-03 11:40:29.000000000 +0100
> +++ gcc/c-family/c-pch.c        2014-01-07 21:29:42.985600418 +0100
> @@ -180,6 +180,8 @@ c_common_write_pch (void)
>
>    (*debug_hooks->handle_pch) (1);
>
> +  prepare_target_option_nodes_for_pch ();
> +
>    cpp_write_pch_deps (parse_in, pch_outfile);
>
>    gt_pch_save (pch_outfile);
> --- gcc/config/i386/i386.h.jj   2014-01-06 22:37:19.000000000 +0100
> +++ gcc/config/i386/i386.h      2014-01-07 17:21:09.049106675 +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 17:21:09.049106675 +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

Reply via email to