On 07/09/2015 10:47 PM, Martin Liška wrote: > On 07/09/2015 07:44 PM, Jeff Law wrote: >> On 07/09/2015 03:13 AM, mliska wrote: >>> gcc/ChangeLog: >>> >>> 2015-07-03 Martin Liska <mli...@suse.cz> >>> >>> * ipa-pure-const.c (struct funct_state_d): New. >>> (funct_state_d::default_p): Likewise. >>> (has_function_state): Remove. >>> (get_function_state): Likewise. >>> (set_function_state): Likewise. >>> (add_new_function): Rename and port to ::insert. >>> (duplicate_node_data): Rename and port to ::duplicate. >>> (funct_state_summary_t::duplicate): New function. >>> (register_hooks): Remove hook registration. >>> (pure_const_generate_summary): Use new data structure. >>> (pure_const_write_summary): Likewise. >>> (pure_const_read_summary): Likewise. >>> (propagate_pure_const): Likewise. >>> (propagate_nothrow): Likewise. >>> (execute): Remove hook usage. >>> (pass_ipa_pure_const::pass_ipa_pure_const): Likewise. >>> --- >>> @@ -84,6 +85,18 @@ const char *pure_const_names[3] = {"const", "pure", >>> "neither"}; >>> decl. */ >>> struct funct_state_d >>> { >>> + funct_state_d (): pure_const_state (IPA_NEITHER), >>> + state_previously_known (IPA_NEITHER), looping_previously_known (true), >>> + looping (true), can_throw (true), can_free (true) {} >>> + >>> + funct_state_d (const funct_state_d &s): pure_const_state >>> (s.pure_const_state), >>> + state_previously_known (s.state_previously_known), >>> + looping_previously_known (s.looping_previously_known), >>> + looping (s.looping), can_throw (s.can_throw), can_free (s.can_free) {} >>> + >>> + /* Return true if the value is default. */ >>> + bool default_p (); >>> + >>> /* See above. */ >>> enum pure_const_state_e pure_const_state; >>> /* What user set here; we can be always sure about this. */ >> Doesn't this need to be a "class" rather then a "struct"? >> >> >> OK with that change. >> >> jeff > > Yeah. > > 'class' will be more appropriate. As I'm going to be AFK for Friday and > upcoming weekend, > I will install these patches on Monday. > > Thanks, > Martin
Hello. v2 of the patch. Thanks, Martin
>From a17b6f69d944894ffda2f8db93577014dde070b9 Mon Sep 17 00:00:00 2001 From: mliska <mli...@suse.cz> Date: Thu, 9 Jul 2015 11:13:55 +0200 Subject: [PATCH 4/4] Port ipa-pure-const to function_summary. gcc/ChangeLog: 2015-07-03 Martin Liska <mli...@suse.cz> * ipa-pure-const.c (struct funct_state_d): New. (funct_state_d::default_p): Likewise. (has_function_state): Remove. (get_function_state): Likewise. (set_function_state): Likewise. (add_new_function): Rename and port to ::insert. (duplicate_node_data): Rename and port to ::duplicate. (funct_state_summary_t::duplicate): New function. (register_hooks): Remove hook registration. (pure_const_generate_summary): Use new data structure. (pure_const_write_summary): Likewise. (pure_const_read_summary): Likewise. (propagate_pure_const): Likewise. (propagate_nothrow): Likewise. (execute): Remove hook usage. (pass_ipa_pure_const::pass_ipa_pure_const): Likewise. --- gcc/ipa-pure-const.c | 168 +++++++++++++++++---------------------------------- 1 file changed, 55 insertions(+), 113 deletions(-) diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c index f0373e6..90f1c9f 100644 --- a/gcc/ipa-pure-const.c +++ b/gcc/ipa-pure-const.c @@ -67,6 +67,7 @@ along with GCC; see the file COPYING3. If not see #include "intl.h" #include "opts.h" #include "varasm.h" +#include "symbol-summary.h" /* Lattice values for const and pure functions. Everything starts out being const, then may drop to pure and then neither depending on @@ -82,8 +83,18 @@ const char *pure_const_names[3] = {"const", "pure", "neither"}; /* Holder for the const_state. There is one of these per function decl. */ -struct funct_state_d +class funct_state_d { +public: + funct_state_d (): pure_const_state (IPA_NEITHER), + state_previously_known (IPA_NEITHER), looping_previously_known (true), + looping (true), can_throw (true), can_free (true) {} + + funct_state_d (const funct_state_d &s): pure_const_state (s.pure_const_state), + state_previously_known (s.state_previously_known), + looping_previously_known (s.looping_previously_known), + looping (s.looping), can_throw (s.can_throw), can_free (s.can_free) {} + /* See above. */ enum pure_const_state_e pure_const_state; /* What user set here; we can be always sure about this. */ @@ -105,20 +116,25 @@ struct funct_state_d bool can_free; }; -/* State used when we know nothing about function. */ -static struct funct_state_d varying_state - = { IPA_NEITHER, IPA_NEITHER, true, true, true, true }; - - typedef struct funct_state_d * funct_state; /* The storage of the funct_state is abstracted because there is the possibility that it may be desirable to move this to the cgraph local info. */ -/* Array, indexed by cgraph node uid, of function states. */ +class funct_state_summary_t: public function_summary <funct_state_d *> +{ +public: + funct_state_summary_t (symbol_table *symtab): + function_summary <funct_state_d *> (symtab) {} + + virtual void insert (cgraph_node *, funct_state_d *state); + virtual void duplicate (cgraph_node *src_node, cgraph_node *dst_node, + funct_state_d *src_data, + funct_state_d *dst_data); +}; -static vec<funct_state> funct_state_vec; +static funct_state_summary_t *funct_state_summaries = NULL; static bool gate_pure_const (void); @@ -150,12 +166,6 @@ public: private: bool init_p; - - /* Holders of ipa cgraph hooks: */ - struct cgraph_node_hook_list *function_insertion_hook_holder; - struct cgraph_2node_hook_list *node_duplication_hook_holder; - struct cgraph_node_hook_list *node_removal_hook_holder; - }; // class pass_ipa_pure_const } // anon namespace @@ -237,41 +247,6 @@ warn_function_noreturn (tree decl) true, warned_about, "noreturn"); } -/* Return true if we have a function state for NODE. */ - -static inline bool -has_function_state (struct cgraph_node *node) -{ - if (!funct_state_vec.exists () - || funct_state_vec.length () <= (unsigned int)node->uid) - return false; - return funct_state_vec[node->uid] != NULL; -} - -/* Return the function state from NODE. */ - -static inline funct_state -get_function_state (struct cgraph_node *node) -{ - if (!funct_state_vec.exists () - || funct_state_vec.length () <= (unsigned int)node->uid - || !funct_state_vec[node->uid]) - /* We might want to put correct previously_known state into varying. */ - return &varying_state; - return funct_state_vec[node->uid]; -} - -/* Set the function state S for NODE. */ - -static inline void -set_function_state (struct cgraph_node *node, funct_state s) -{ - if (!funct_state_vec.exists () - || funct_state_vec.length () <= (unsigned int)node->uid) - funct_state_vec.safe_grow_cleared (node->uid + 1); - funct_state_vec[node->uid] = s; -} - /* Check to see if the use (or definition when CHECKING_WRITE is true) variable T is legal in a function that is either pure or const. */ @@ -903,9 +878,8 @@ end: return l; } -/* Called when new function is inserted to callgraph late. */ -static void -add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) +void +funct_state_summary_t::insert (cgraph_node *node, funct_state_d *state) { if (node->get_availability () < AVAIL_INTERPOSABLE) return; @@ -915,36 +889,21 @@ add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) operations. */ if (node->get_availability () > AVAIL_INTERPOSABLE && opt_for_fn (node->decl, flag_ipa_pure_const)) - set_function_state (node, analyze_function (node, true)); -} - -/* Called when new clone is inserted to callgraph late. */ - -static void -duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst, - void *data ATTRIBUTE_UNUSED) -{ - if (has_function_state (src)) { - funct_state l = XNEW (struct funct_state_d); - gcc_assert (!has_function_state (dst)); - memcpy (l, get_function_state (src), sizeof (*l)); - set_function_state (dst, l); + funct_state_d *a = analyze_function (node, true); + new (state) funct_state_d (*a); + free (a); } } /* Called when new clone is inserted to callgraph late. */ -static void -remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) +void +funct_state_summary_t::duplicate (cgraph_node *, cgraph_node *, + funct_state_d *src_data, + funct_state_d *dst_data) { - if (has_function_state (node)) - { - funct_state l = get_function_state (node); - if (l != &varying_state) - free (l); - set_function_state (node, NULL); - } + new (dst_data) funct_state_d (*src_data); } @@ -957,12 +916,7 @@ register_hooks (void) init_p = true; - node_removal_hook_holder = - symtab->add_cgraph_removal_hook (&remove_node_data, NULL); - node_duplication_hook_holder = - symtab->add_cgraph_duplication_hook (&duplicate_node_data, NULL); - function_insertion_hook_holder = - symtab->add_cgraph_insertion_hook (&add_new_function, NULL); + funct_state_summaries = new funct_state_summary_t (symtab); } @@ -986,7 +940,11 @@ pure_const_generate_summary (void) FOR_EACH_DEFINED_FUNCTION (node) if (node->get_availability () >= AVAIL_INTERPOSABLE && opt_for_fn (node->decl, flag_ipa_pure_const)) - set_function_state (node, analyze_function (node, true)); + { + funct_state_d *a = analyze_function (node, true); + new (funct_state_summaries->get_or_insert (node)) funct_state_d (*a); + free (a); + } } @@ -1008,7 +966,8 @@ pure_const_write_summary (void) lsei_next_function_in_partition (&lsei)) { node = lsei_cgraph_node (lsei); - if (node->definition && has_function_state (node)) + if (node->definition + && funct_state_summaries->get_or_insert (node) != NULL) count++; } @@ -1019,15 +978,13 @@ pure_const_write_summary (void) lsei_next_function_in_partition (&lsei)) { node = lsei_cgraph_node (lsei); - if (node->definition && has_function_state (node)) + funct_state_d *fs = funct_state_summaries->get_or_insert (node); + if (node->definition && fs != NULL) { struct bitpack_d bp; - funct_state fs; int node_ref; lto_symtab_encoder_t encoder; - fs = get_function_state (node); - encoder = ob->decl_state->symtab_node_encoder; node_ref = lto_symtab_encoder_encode (encoder, node); streamer_write_uhwi_stream (ob->main_stream, node_ref); @@ -1082,13 +1039,12 @@ pure_const_read_summary (void) funct_state fs; lto_symtab_encoder_t encoder; - fs = XCNEW (struct funct_state_d); index = streamer_read_uhwi (ib); encoder = file_data->symtab_node_encoder; node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref (encoder, index)); - set_function_state (node, fs); + fs = funct_state_summaries->get_or_insert (node); /* Note that the flags must be read in the opposite order in which they were written (the bitflags were pushed into FLAGS). */ @@ -1216,7 +1172,7 @@ propagate_pure_const (void) int i; struct ipa_ref *ref = NULL; - funct_state w_l = get_function_state (w); + funct_state w_l = funct_state_summaries->get_or_insert (w); if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, " Visiting %s/%i state:%s looping %i\n", w->name (), @@ -1272,7 +1228,7 @@ propagate_pure_const (void) } if (avail > AVAIL_INTERPOSABLE) { - funct_state y_l = get_function_state (y); + funct_state_d *y_l = funct_state_summaries->get_or_insert (y); if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, @@ -1389,7 +1345,7 @@ propagate_pure_const (void) while (w && !can_free) { struct cgraph_edge *e; - funct_state w_l = get_function_state (w); + funct_state_d *w_l = funct_state_summaries->get_or_insert (w); if (w_l->can_free || w->get_availability () == AVAIL_INTERPOSABLE @@ -1403,7 +1359,7 @@ propagate_pure_const (void) function_or_virtual_thunk_symbol (&avail); if (avail > AVAIL_INTERPOSABLE) - can_free = get_function_state (y)->can_free; + can_free = funct_state_summaries->get_or_insert (y)->can_free; else can_free = true; } @@ -1416,7 +1372,7 @@ propagate_pure_const (void) w = node; while (w) { - funct_state w_l = get_function_state (w); + funct_state_d *w_l = funct_state_summaries->get_or_insert (w); enum pure_const_state_e this_state = pure_const_state; bool this_looping = looping; @@ -1526,7 +1482,7 @@ propagate_nothrow (void) while (w && !can_throw) { struct cgraph_edge *e, *ie; - funct_state w_l = get_function_state (w); + funct_state_d *w_l = funct_state_summaries->get_or_insert (w); if (w_l->can_throw || w->get_availability () == AVAIL_INTERPOSABLE) @@ -1540,7 +1496,7 @@ propagate_nothrow (void) if (avail > AVAIL_INTERPOSABLE) { - funct_state y_l = get_function_state (y); + funct_state_d *y_l = funct_state_summaries->get_or_insert (y); if (y_l->can_throw && !TREE_NOTHROW (w->decl) && e->can_throw_external) @@ -1561,7 +1517,7 @@ propagate_nothrow (void) w = node; while (w) { - funct_state w_l = get_function_state (w); + funct_state_d *w_l = funct_state_summaries->get_or_insert (w); if (!can_throw && !TREE_NOTHROW (w->decl)) { /* Inline clones share declaration with their offline copies; @@ -1594,23 +1550,14 @@ unsigned int pass_ipa_pure_const:: execute (function *) { - struct cgraph_node *node; bool remove_p; - symtab->remove_cgraph_insertion_hook (function_insertion_hook_holder); - symtab->remove_cgraph_duplication_hook (node_duplication_hook_holder); - symtab->remove_cgraph_removal_hook (node_removal_hook_holder); - /* Nothrow makes more function to not lead to return and improve later analysis. */ propagate_nothrow (); remove_p = propagate_pure_const (); - /* Cleanup. */ - FOR_EACH_FUNCTION (node) - if (has_function_state (node)) - free (get_function_state (node)); - funct_state_vec.release (); + delete funct_state_summaries; return remove_p ? TODO_remove_functions : 0; } @@ -1631,12 +1578,7 @@ pass_ipa_pure_const::pass_ipa_pure_const(gcc::context *ctxt) 0, /* function_transform_todo_flags_start */ NULL, /* function_transform */ NULL), /* variable_transform */ - init_p(false), - function_insertion_hook_holder(NULL), - node_duplication_hook_holder(NULL), - node_removal_hook_holder(NULL) -{ -} + init_p (false) {} ipa_opt_pass_d * make_pass_ipa_pure_const (gcc::context *ctxt) -- 2.4.5