Make default duplicate and insert methods of summaries abort; fix fallout
authorJan Hubicka <jh@suse.cz>
Mon, 26 Oct 2020 10:24:33 +0000 (11:24 +0100)
committerJan Hubicka <jh@suse.cz>
Mon, 26 Oct 2020 10:24:33 +0000 (11:24 +0100)
the default duplicate and insert methods of sumaries produce empty
summary that is not useful for anything and makes it easy to introduce
bugs.

This patch makes the default hooks to abort and summaries that do not
need dupicaito/insertion disable the corresponding hooks. I also
implemented missing insertion hook for ipa-sra which forced me to move
analysis out of anonymous namespace.

2020-10-23  Jan Hubicka  <hubicka@ucw.cz>

* cgraph.h (struct cgraph_node): Make ipa_transforms_to_apply vl_ptr.
* ipa-inline-analysis.c (initialize_growth_caches): Disable insertion
and duplication hooks.
* ipa-inline-transform.c (clone_inlined_nodes): Clear
ipa_transforms_to_apply.
(save_inline_function_body): Disable insertion hoook for
ipa_saved_clone_sources.
* ipa-prop.c (ipcp_transformation_initialize): Disable insertion hook.
* ipa-prop.h (ipa_node_params_t): Disable insertion hook.
* ipa-reference.c (propagate): Disable insertion hoook.
* ipa-sra.c (ipa_sra_summarize_function): Move out of anonymous
namespace.
(ipa_sra_function_summaries::insert): New virtual function.
* passes.c (execute_one_pass): Do not add transforms to inline clones.
* symbol-summary.h (function_summary_base): Make insert and duplicate
hooks fail instead of silently producing empty summaries; add way to
disable duplication hooks
(call_summary_base): Likewise.
* tree-nested.c (nested_function_info::get_create): Disable insertion
hooks
(maybe_record_nested_function): Likewise.

gcc/cgraph.h
gcc/ipa-inline-analysis.c
gcc/ipa-inline-transform.c
gcc/ipa-prop.c
gcc/ipa-prop.h
gcc/ipa-reference.c
gcc/ipa-sra.c
gcc/passes.c
gcc/symbol-summary.h
gcc/tree-nested.c

index 9eb48d5..65e4646 100644 (file)
@@ -1402,7 +1402,7 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node
   /* Interprocedural passes scheduled to have their transform functions
      applied next time we execute local pass on them.  We maintain it
      per-function in order to allow IPA passes to introduce new functions.  */
-  vec<ipa_opt_pass> GTY((skip)) ipa_transforms_to_apply;
+  vec<ipa_opt_pass, va_heap, vl_ptr> GTY((skip)) ipa_transforms_to_apply;
 
   /* For inline clones this points to the function they will be
      inlined into.  */
index acbf82e..bd0e322 100644 (file)
@@ -127,6 +127,9 @@ initialize_growth_caches ()
     = new fast_call_summary<edge_growth_cache_entry *, va_heap> (symtab);
   node_context_cache
     = new fast_function_summary<node_context_summary *, va_heap> (symtab);
+  edge_growth_cache->disable_duplication_hook ();
+  node_context_cache->disable_insertion_hook ();
+  node_context_cache->disable_duplication_hook ();
 }
 
 /* Free growth caches.  */
index 3782cce..279ba2f 100644 (file)
@@ -231,6 +231,11 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
     e->callee->remove_from_same_comdat_group ();
 
   e->callee->inlined_to = inlining_into;
+  if (e->callee->ipa_transforms_to_apply.length ())
+    {
+      e->callee->ipa_transforms_to_apply.release ();
+      e->callee->ipa_transforms_to_apply = vNULL;
+    }
 
   /* Recursively clone all bodies.  */
   for (e = e->callee->callees; e; e = next)
@@ -606,7 +611,10 @@ save_inline_function_body (struct cgraph_node *node)
 
   tree prev_body_holder = node->decl;
   if (!ipa_saved_clone_sources)
-    ipa_saved_clone_sources = new function_summary <tree *> (symtab);
+    {
+      ipa_saved_clone_sources = new function_summary <tree *> (symtab);
+      ipa_saved_clone_sources->disable_insertion_hook ();
+    }
   else
     {
       tree *p = ipa_saved_clone_sources->get (node);
index a848f1d..6014766 100644 (file)
@@ -4211,7 +4211,10 @@ ipcp_transformation_initialize (void)
   if (!ipa_vr_hash_table)
     ipa_vr_hash_table = hash_table<ipa_vr_ggc_hash_traits>::create_ggc (37);
   if (ipcp_transformation_sum == NULL)
-    ipcp_transformation_sum = ipcp_transformation_t::create_ggc (symtab);
+    {
+      ipcp_transformation_sum = ipcp_transformation_t::create_ggc (symtab);
+      ipcp_transformation_sum->disable_insertion_hook ();
+    }
 }
 
 /* Release the IPA CP transformation summary.  */
index 0bbbbf9..77e92b0 100644 (file)
@@ -941,7 +941,10 @@ class GTY((user)) ipa_node_params_t: public function_summary <ipa_node_params *>
 {
 public:
   ipa_node_params_t (symbol_table *table, bool ggc):
-    function_summary<ipa_node_params *> (table, ggc) { }
+    function_summary<ipa_node_params *> (table, ggc)
+  {
+    disable_insertion_hook ();
+  }
 
   /* Hook that is called by summary when a node is duplicated.  */
   virtual void duplicate (cgraph_node *node,
index 4a6c011..871c997 100644 (file)
@@ -894,7 +894,10 @@ propagate (void)
     }
 
   if (ipa_ref_opt_sum_summaries == NULL)
-    ipa_ref_opt_sum_summaries = new ipa_ref_opt_summary_t (symtab);
+    {
+      ipa_ref_opt_sum_summaries = new ipa_ref_opt_summary_t (symtab);
+      ipa_ref_opt_sum_summaries->disable_insertion_hook ();
+    }
 
   /* Cleanup. */
   FOR_EACH_DEFINED_FUNCTION (node)
@@ -1130,6 +1133,7 @@ ipa_reference_read_optimization_summary (void)
 
   gcc_checking_assert (ipa_ref_opt_sum_summaries == NULL);
   ipa_ref_opt_sum_summaries = new ipa_ref_opt_summary_t (symtab);
+  ipa_ref_opt_sum_summaries->disable_insertion_hook ();
   ipa_reference_vars_map = new reference_vars_map_t(257);
   varpool_node_hooks
         = symtab->add_varpool_removal_hook (varpool_removal_hook, NULL);
index 8d4f580..07227c0 100644 (file)
@@ -85,6 +85,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-streamer.h"
 #include "internal-fn.h"
 
+static void ipa_sra_summarize_function (cgraph_node *);
+
 /* Bits used to track size of an aggregate in bytes interprocedurally.  */
 #define ISRA_ARG_SIZE_LIMIT_BITS 16
 #define ISRA_ARG_SIZE_LIMIT (1 << ISRA_ARG_SIZE_LIMIT_BITS)
@@ -373,6 +375,7 @@ public:
   virtual void duplicate (cgraph_node *, cgraph_node *,
                          isra_func_summary *old_sum,
                          isra_func_summary *new_sum);
+  virtual void insert (cgraph_node *, isra_func_summary *);
 };
 
 /* Hook that is called by summary when a node is duplicated.  */
@@ -426,6 +429,21 @@ ipa_sra_function_summaries::duplicate (cgraph_node *, cgraph_node *,
 
 static GTY(()) ipa_sra_function_summaries *func_sums;
 
+/* Hook that is called by summary when new node appears.  */
+
+void
+ipa_sra_function_summaries::insert (cgraph_node *node, isra_func_summary *)
+{
+  if (opt_for_fn (node->decl, flag_ipa_sra))
+    {
+      push_cfun (DECL_STRUCT_FUNCTION (node->decl));
+      ipa_sra_summarize_function (node);
+      pop_cfun ();
+    }
+  else
+    func_sums->remove (node);
+}
+
 /* Class to manage call summaries.  */
 
 class ipa_sra_call_summaries: public call_summary <isra_call_summary *>
@@ -2478,79 +2496,6 @@ verify_splitting_accesses (cgraph_node *node, bool certain_must_exist)
     }
 }
 
-/* Intraprocedural part of IPA-SRA analysis.  Scan function body of NODE and
-   create a summary structure describing IPA-SRA opportunities and constraints
-   in it.  */
-
-static void
-ipa_sra_summarize_function (cgraph_node *node)
-{
-  if (dump_file)
-    fprintf (dump_file, "Creating summary for %s/%i:\n", node->name (),
-            node->order);
-  if (!ipa_sra_preliminary_function_checks (node))
-    return;
-  gcc_obstack_init (&gensum_obstack);
-  isra_func_summary *ifs = func_sums->get_create (node);
-  ifs->m_candidate = true;
-  tree ret = TREE_TYPE (TREE_TYPE (node->decl));
-  ifs->m_returns_value = (TREE_CODE (ret) != VOID_TYPE);
-
-  decl2desc = new hash_map<tree, gensum_param_desc *>;
-  unsigned count = 0;
-  for (tree parm = DECL_ARGUMENTS (node->decl); parm; parm = DECL_CHAIN (parm))
-    count++;
-
-  if (count > 0)
-    {
-      auto_vec<gensum_param_desc, 16> param_descriptions (count);
-      param_descriptions.reserve_exact (count);
-      param_descriptions.quick_grow_cleared (count);
-
-      bool cfun_pushed = false;
-      struct function *fun = DECL_STRUCT_FUNCTION (node->decl);
-      if (create_parameter_descriptors (node, &param_descriptions))
-       {
-         push_cfun (fun);
-         cfun_pushed = true;
-         final_bbs = BITMAP_ALLOC (NULL);
-         bb_dereferences = XCNEWVEC (HOST_WIDE_INT,
-                                     by_ref_count
-                                     * last_basic_block_for_fn (fun));
-         aa_walking_limit = opt_for_fn (node->decl, param_ipa_max_aa_steps);
-         scan_function (node, fun);
-
-         if (dump_file)
-           {
-             dump_gensum_param_descriptors (dump_file, node->decl,
-                                            &param_descriptions);
-             fprintf (dump_file, "----------------------------------------\n");
-           }
-       }
-      process_scan_results (node, fun, ifs, &param_descriptions);
-
-      if (cfun_pushed)
-       pop_cfun ();
-      if (bb_dereferences)
-       {
-         free (bb_dereferences);
-         bb_dereferences = NULL;
-         BITMAP_FREE (final_bbs);
-         final_bbs = NULL;
-       }
-    }
-  isra_analyze_all_outgoing_calls (node);
-
-  delete decl2desc;
-  decl2desc = NULL;
-  obstack_free (&gensum_obstack, NULL);
-  if (dump_file)
-    fprintf (dump_file, "\n\n");
-  if (flag_checking)
-    verify_splitting_accesses (node, false);
-  return;
-}
-
 /* Intraprocedural part of IPA-SRA analysis.  Scan bodies of all functions in
    this compilation unit and create summary structures describing IPA-SRA
    opportunities and constraints in them.  */
@@ -4102,6 +4047,79 @@ public:
 
 } // anon namespace
 
+/* Intraprocedural part of IPA-SRA analysis.  Scan function body of NODE and
+   create a summary structure describing IPA-SRA opportunities and constraints
+   in it.  */
+
+static void
+ipa_sra_summarize_function (cgraph_node *node)
+{
+  if (dump_file)
+    fprintf (dump_file, "Creating summary for %s/%i:\n", node->name (),
+            node->order);
+  if (!ipa_sra_preliminary_function_checks (node))
+    return;
+  gcc_obstack_init (&gensum_obstack);
+  isra_func_summary *ifs = func_sums->get_create (node);
+  ifs->m_candidate = true;
+  tree ret = TREE_TYPE (TREE_TYPE (node->decl));
+  ifs->m_returns_value = (TREE_CODE (ret) != VOID_TYPE);
+
+  decl2desc = new hash_map<tree, gensum_param_desc *>;
+  unsigned count = 0;
+  for (tree parm = DECL_ARGUMENTS (node->decl); parm; parm = DECL_CHAIN (parm))
+    count++;
+
+  if (count > 0)
+    {
+      auto_vec<gensum_param_desc, 16> param_descriptions (count);
+      param_descriptions.reserve_exact (count);
+      param_descriptions.quick_grow_cleared (count);
+
+      bool cfun_pushed = false;
+      struct function *fun = DECL_STRUCT_FUNCTION (node->decl);
+      if (create_parameter_descriptors (node, &param_descriptions))
+       {
+         push_cfun (fun);
+         cfun_pushed = true;
+         final_bbs = BITMAP_ALLOC (NULL);
+         bb_dereferences = XCNEWVEC (HOST_WIDE_INT,
+                                     by_ref_count
+                                     * last_basic_block_for_fn (fun));
+         aa_walking_limit = opt_for_fn (node->decl, param_ipa_max_aa_steps);
+         scan_function (node, fun);
+
+         if (dump_file)
+           {
+             dump_gensum_param_descriptors (dump_file, node->decl,
+                                            &param_descriptions);
+             fprintf (dump_file, "----------------------------------------\n");
+           }
+       }
+      process_scan_results (node, fun, ifs, &param_descriptions);
+
+      if (cfun_pushed)
+       pop_cfun ();
+      if (bb_dereferences)
+       {
+         free (bb_dereferences);
+         bb_dereferences = NULL;
+         BITMAP_FREE (final_bbs);
+         final_bbs = NULL;
+       }
+    }
+  isra_analyze_all_outgoing_calls (node);
+
+  delete decl2desc;
+  decl2desc = NULL;
+  obstack_free (&gensum_obstack, NULL);
+  if (dump_file)
+    fprintf (dump_file, "\n\n");
+  if (flag_checking)
+    verify_splitting_accesses (node, false);
+  return;
+}
+
 ipa_opt_pass_d *
 make_pass_ipa_sra (gcc::context *ctxt)
 {
index 1942b7c..02a47e2 100644 (file)
@@ -2566,7 +2566,8 @@ execute_one_pass (opt_pass *pass)
     {
       struct cgraph_node *node;
       FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
-       node->ipa_transforms_to_apply.safe_push ((ipa_opt_pass_d *)pass);
+       if (!node->inlined_to)
+         node->ipa_transforms_to_apply.safe_push ((ipa_opt_pass_d *)pass);
     }
   else if (dump_file)
     do_per_function (execute_function_dump, pass);
index a38eb1d..af5f4e6 100644 (file)
@@ -31,17 +31,27 @@ public:
   function_summary_base (symbol_table *symtab CXX_MEM_STAT_INFO):
   m_symtab (symtab),
   m_insertion_enabled (true),
+  m_duplication_enabled (true),
   m_allocator ("function summary" PASS_MEM_STAT)
   {}
 
   /* Basic implementation of insert operation.  */
-  virtual void insert (cgraph_node *, T *) {}
+  virtual void insert (cgraph_node *, T *)
+  {
+    /* In most cases, it makes no sense to create summaries without
+       initializing them.  */
+    gcc_unreachable ();
+  }
 
   /* Basic implementation of removal operation.  */
   virtual void remove (cgraph_node *, T *) {}
 
   /* Basic implementation of duplication operation.  */
-  virtual void duplicate (cgraph_node *, cgraph_node *, T *, T *) {}
+  virtual void duplicate (cgraph_node *, cgraph_node *, T *, T *)
+  {
+    /* It makes no sense to not copy anything during duplication.  */
+    gcc_unreachable ();
+  }
 
   /* Enable insertion hook invocation.  */
   void enable_insertion_hook ()
@@ -55,6 +65,18 @@ public:
     m_insertion_enabled = false;
   }
 
+  /* Enable duplication hook invocation.  */
+  void enable_duplication_hook ()
+  {
+    m_duplication_enabled = true;
+  }
+
+  /* Enable duplication hook invocation.  */
+  void disable_duplication_hook ()
+  {
+    m_duplication_enabled = false;
+  }
+
 protected:
   /* Allocates new data that are stored within map.  */
   T* allocate_new ()
@@ -88,6 +110,8 @@ protected:
 
   /* Indicates if insertion hook is enabled.  */
   bool m_insertion_enabled;
+  /* Indicates if duplication hook is enabled.  */
+  bool m_duplication_enabled;
 
 private:
   /* Return true when the summary uses GGC memory for allocation.  */
@@ -269,10 +293,13 @@ function_summary<T *>::symtab_duplication (cgraph_node *node,
                                           cgraph_node *node2, void *data)
 {
   function_summary *summary = (function_summary <T *> *) (data);
-  T *v = summary->get (node);
+  if (summary->m_duplication_enabled)
+    {
+      T *v = summary->get (node);
 
-  if (v)
-    summary->duplicate (node, node2, v, summary->get_create (node2));
+      if (v)
+       summary->duplicate (node, node2, v, summary->get_create (node2));
+    }
 }
 
 template <typename T>
@@ -468,12 +495,15 @@ fast_function_summary<T *, V>::symtab_duplication (cgraph_node *node,
                                                   void *data)
 {
   fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
-  T *v = summary->get (node);
-
-  if (v)
+  if (summary->m_duplication_enabled)
     {
-      T *duplicate = summary->get_create (node2);
-      summary->duplicate (node, node2, v, duplicate);
+      T *v = summary->get (node);
+
+      if (v)
+       {
+         T *duplicate = summary->get_create (node2);
+         summary->duplicate (node, node2, v, duplicate);
+       }
     }
 }
 
@@ -536,6 +566,7 @@ public:
   call_summary_base (symbol_table *symtab CXX_MEM_STAT_INFO):
   m_symtab (symtab),
   m_initialize_when_cloning (false),
+  m_duplication_enabled (true),
   m_allocator ("call summary" PASS_MEM_STAT)
   {}
 
@@ -543,7 +574,22 @@ public:
   virtual void remove (cgraph_edge *, T *) {}
 
   /* Basic implementation of duplication operation.  */
-  virtual void duplicate (cgraph_edge *, cgraph_edge *, T *, T *) {}
+  virtual void duplicate (cgraph_edge *, cgraph_edge *, T *, T *)
+  {
+    gcc_unreachable ();
+  }
+
+  /* Enable duplication hook invocation.  */
+  void enable_duplication_hook ()
+  {
+    m_duplication_enabled = true;
+  }
+
+  /* Enable duplication hook invocation.  */
+  void disable_duplication_hook ()
+  {
+    m_duplication_enabled = false;
+  }
 
 protected:
   /* Allocates new data that are stored within map.  */
@@ -576,6 +622,8 @@ protected:
   cgraph_2edge_hook_list *m_symtab_duplication_hook;
   /* Initialize summary for an edge that is cloned.  */
   bool m_initialize_when_cloning;
+  /* Indicates if duplication hook is enabled.  */
+  bool m_duplication_enabled;
 
 private:
   /* Return true when the summary uses GGC memory for allocation.  */
@@ -726,16 +774,19 @@ call_summary<T *>::symtab_duplication (cgraph_edge *edge1,
                                       cgraph_edge *edge2, void *data)
 {
   call_summary *summary = (call_summary <T *> *) (data);
-  T *edge1_summary = NULL;
+  if (summary->m_duplication_enabled)
+    {
+      T *edge1_summary = NULL;
 
-  if (summary->m_initialize_when_cloning)
-    edge1_summary = summary->get_create (edge1);
-  else
-    edge1_summary = summary->get (edge1);
+      if (summary->m_initialize_when_cloning)
+       edge1_summary = summary->get_create (edge1);
+      else
+       edge1_summary = summary->get (edge1);
 
-  if (edge1_summary)
-    summary->duplicate (edge1, edge2, edge1_summary,
-                       summary->get_create (edge2));
+      if (edge1_summary)
+       summary->duplicate (edge1, edge2, edge1_summary,
+                           summary->get_create (edge2));
+    }
 }
 
 template <typename T>
@@ -892,17 +943,20 @@ fast_call_summary<T *, V>::symtab_duplication (cgraph_edge *edge1,
                                                 cgraph_edge *edge2, void *data)
 {
   fast_call_summary *summary = (fast_call_summary <T *, V> *) (data);
-  T *edge1_summary = NULL;
-
-  if (summary->m_initialize_when_cloning)
-    edge1_summary = summary->get_create (edge1);
-  else
-    edge1_summary = summary->get (edge1);
-
-  if (edge1_summary)
+  if (summary->m_duplication_enabled)
     {
-      T *duplicate = summary->get_create (edge2);
-      summary->duplicate (edge1, edge2, edge1_summary, duplicate);
+      T *edge1_summary = NULL;
+
+      if (summary->m_initialize_when_cloning)
+       edge1_summary = summary->get_create (edge1);
+      else
+       edge1_summary = summary->get (edge1);
+
+      if (edge1_summary)
+       {
+         T *duplicate = summary->get_create (edge2);
+         summary->duplicate (edge1, edge2, edge1_summary, duplicate);
+       }
     }
 }
 
index 788883f..9cb4a08 100644 (file)
@@ -65,8 +65,11 @@ nested_function_info *
 nested_function_info::get_create (cgraph_node *node)
 {
   if (!nested_function_sum)
-    nested_function_sum = new function_summary <nested_function_info *>
-                                (symtab);
+    {
+      nested_function_sum = new function_summary <nested_function_info *>
+                                  (symtab);
+      nested_function_sum->disable_insertion_hook ();
+    }
   return nested_function_sum->get_create (node);
 }
 
@@ -124,6 +127,9 @@ nested_function_info::release ()
 void
 maybe_record_nested_function (cgraph_node *node)
 {
+  /* All nested functions gets lowered during the construction of symtab.  */
+  if (symtab->state > CONSTRUCTION)
+    return;
   if (DECL_CONTEXT (node->decl)
       && TREE_CODE (DECL_CONTEXT (node->decl)) == FUNCTION_DECL)
     {