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 9eb48d5b62fbf9c392febeddd67f3b4ee61e8f3a..65e4646efcd8778aacda2dc56ccc4ce8b2ab4b86 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 acbf82e84d9576154a66333b68d28475d43c59f1..bd0e322605fa50fefc0567da088541a099a1c522 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 3782cce12e34aa40b4d1a5cb64dc95c8a00b095c..279ba2f7cb0abee6648181887fdc0c5b24bbc29c 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 a848f1db95e61011c91897399c8b37447d0c88c3..6014766b4183dbe1a842320b6c3494beff4d05ff 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 0bbbbf9bd9f407d187f252270f09e23cecf57d3b..77e92b04bbaa9a95c32b3fa12a37c9fc3edaf6b8 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 4a6c011c525eceb1e096618ff169a1b8ed95467d..871c9977841f3138ef500b561a98ec21f338cd80 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 8d4f580e00959e17050144ccfd1d52007ac57286..07227c0bfecfdf8c4b295053e0a90d08aadf58c8 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 1942b7cd1c3d13370c4b0f85e00c2648eb2ce5f2..02a47e2595cfcfd0745660df32f949e85d2053f2 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 a38eb1db7787e62e888be8921af9309d85ba5d4f..af5f4e6da62cb7aba5a37836bbf3b0152416cc52 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 788883faa4c980edbbf6458f32c4f21362df6614..9cb4a08e2d9e713bfd41a5171edda7c4d9b4fa0f 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)
     {