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 | 177 +++++++++++++++++++--------------------------------
 1 file changed, 66 insertions(+), 111 deletions(-)

diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index f0373e6..565083c 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
@@ -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.  */
@@ -105,10 +118,16 @@ 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 };
-
+bool
+funct_state_d::default_p ()
+{
+  return pure_const_state == IPA_NEITHER
+    && state_previously_known == IPA_NEITHER
+    && looping_previously_known
+    && looping
+    && can_throw
+    && can_free;
+}
 
 typedef struct funct_state_d * funct_state;
 
@@ -116,9 +135,19 @@ typedef struct funct_state_d * funct_state;
    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) {}
 
-static vec<funct_state> funct_state_vec;
+  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 funct_state_summary_t *funct_state_summaries = NULL;
 
 static bool gate_pure_const (void);
 
@@ -150,12 +179,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 +260,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 +891,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 +902,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 +929,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 +953,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 (node)) funct_state_d (*a);
+       free (a);
+      }
 }
 
 
@@ -1008,7 +979,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 (node)->default_p ())
        count++;
     }
 
@@ -1019,15 +991,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 (node);
+      if (node->definition && !fs->default_p ())
        {
          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 +1052,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 (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 +1185,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 (w);
          if (dump_file && (dump_flags & TDF_DETAILS))
            fprintf (dump_file, "  Visiting %s/%i state:%s looping %i\n",
                     w->name (),
@@ -1272,7 +1241,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 (y);
                  if (dump_file && (dump_flags & TDF_DETAILS))
                    {
                      fprintf (dump_file,
@@ -1389,7 +1358,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 (w);
 
          if (w_l->can_free
              || w->get_availability () == AVAIL_INTERPOSABLE
@@ -1403,7 +1372,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 (y)->can_free;
              else
                can_free = true;
            }
@@ -1416,7 +1385,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 (w);
          enum pure_const_state_e this_state = pure_const_state;
          bool this_looping = looping;
 
@@ -1526,7 +1495,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 (w);
 
          if (w_l->can_throw
              || w->get_availability () == AVAIL_INTERPOSABLE)
@@ -1540,7 +1509,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 (y);
 
                  if (y_l->can_throw && !TREE_NOTHROW (w->decl)
                      && e->can_throw_external)
@@ -1561,7 +1530,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 (w);
          if (!can_throw && !TREE_NOTHROW (w->decl))
            {
              /* Inline clones share declaration with their offline copies;
@@ -1594,23 +1563,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 +1591,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

Reply via email to