Improve effectivity of ipa_polymorphi_context cache.
authorJan Hubicka <hubicka@ucw.cz>
Sun, 3 Nov 2019 22:32:56 +0000 (23:32 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sun, 3 Nov 2019 22:32:56 +0000 (22:32 +0000)
        * ipa-fnsummary.c (set_cond_stmt_execution_predicate,
set_switch_stmt_execution_predicate, compute_bb_predicates,
will_be_nonconstant_expr_predicate,
phi_result_unknown_predicate,
analyze_function_body): Pass arround params summary.
(ipa_call_context::duplicate_from): New comment;
only duplicate useful values.
(ipa_call_context::equal_to): Only compare useful values.
(remap_edge_summaries): Pass params_summary.
(remap_hint_predicate): Likewise.
(ipa_merge_fn_summary_after_inlining): Likewise.
(inline_read_section): Initialize params summary used flags.
* ipa-predicate.c (predicate::remap_after_inlining): Pass
around param_summary.
(add_condition): Initialized used params summary flags.
* ipa-predicate.h (inline_param_summary::equals_to): Make const.
(inline_param_summary::useless_p): New predicate.
(remap_after_inlining, add_condition): Update prototype
* ipa-prop.c (ipa_populate_param_decls): Watch overflow in
move_cost.
(ipa_note_param_call): Add parameter POLYMORPHIC; update params
summaries.
(ipa_analyze_indirect_call_uses): Update use of ipa_note_param_call.
(ipa_analyze_virtual_call_uses): Likewise.
(update_indirect_edges_after_inlining): Update param summaries.
(ipa_print_node_params): Print used flags.
(ipa_read_indirect_edge_info): Update param summareis.
* ipa-prop.h (ipa_param_descriptor): Add
used_by_ipa_predicates, used_by_indirect_call
and used_by_polymorphic_call.
(ipa_set_param_used_by_ipa_predicates,
ipa_set_param_used_by_indirect_call,
ipa_set_param_used_by_polymorphic_call,
ipa_is_param_used_by_ipa_predicates,
ipa_is_param_used_by_indirect_call,
ipa_is_param_used_by_polymorphic_call): New inline functions.

From-SVN: r277759

gcc/ChangeLog
gcc/ipa-fnsummary.c
gcc/ipa-predicate.c
gcc/ipa-predicate.h
gcc/ipa-prop.c
gcc/ipa-prop.h

index fdac1b2ca09ef575ad40599ec8f0e19a2057730b..c108ac2108d311aa427e669147f20b6fd7c458cd 100644 (file)
@@ -1,3 +1,42 @@
+2019-11-02  Jan Hubicka  <hubicka@ucw.cz>
+
+       * ipa-fnsummary.c (set_cond_stmt_execution_predicate,
+       set_switch_stmt_execution_predicate, compute_bb_predicates,
+       will_be_nonconstant_expr_predicate,
+       phi_result_unknown_predicate,
+       analyze_function_body): Pass arround params summary.
+       (ipa_call_context::duplicate_from): New comment;
+       only duplicate useful values.
+       (ipa_call_context::equal_to): Only compare useful values.
+       (remap_edge_summaries): Pass params_summary.
+       (remap_hint_predicate): Likewise.
+       (ipa_merge_fn_summary_after_inlining): Likewise.
+       (inline_read_section): Initialize params summary used flags.
+       * ipa-predicate.c (predicate::remap_after_inlining): Pass
+       around param_summary.
+       (add_condition): Initialized used params summary flags.
+       * ipa-predicate.h (inline_param_summary::equals_to): Make const.
+       (inline_param_summary::useless_p): New predicate.
+       (remap_after_inlining, add_condition): Update prototype
+       * ipa-prop.c (ipa_populate_param_decls): Watch overflow in
+       move_cost.
+       (ipa_note_param_call): Add parameter POLYMORPHIC; update params
+       summaries.
+       (ipa_analyze_indirect_call_uses): Update use of ipa_note_param_call.
+       (ipa_analyze_virtual_call_uses): Likewise.
+       (update_indirect_edges_after_inlining): Update param summaries.
+       (ipa_print_node_params): Print used flags.
+       (ipa_read_indirect_edge_info): Update param summareis.
+       * ipa-prop.h (ipa_param_descriptor): Add
+       used_by_ipa_predicates, used_by_indirect_call
+       and used_by_polymorphic_call.
+       (ipa_set_param_used_by_ipa_predicates,
+       ipa_set_param_used_by_indirect_call,
+       ipa_set_param_used_by_polymorphic_call,
+       ipa_is_param_used_by_ipa_predicates,
+       ipa_is_param_used_by_indirect_call,
+       ipa_is_param_used_by_polymorphic_call): New inline functions.
+
 2019-11-02  Jan Hubicka  <hubicka@ucw.cz>
 
        * ipa-fnsummary.c (ipa_call_context::duplicate_from): New
index eaf904cd4017462ab45d041a672c899d90b4359a..4a3cb760a265ba0b5b13eb785a84736b11b17db6 100644 (file)
@@ -1312,6 +1312,7 @@ fail:
 static void
 set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi,
                                   class ipa_fn_summary *summary,
+                                  class ipa_node_params *params_summary,
                                   basic_block bb)
 {
   gimple *last;
@@ -1354,7 +1355,8 @@ set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi,
              && !dominated_by_p (CDI_POST_DOMINATORS, bb, e->dest))
            {
              predicate p
-               = add_condition (summary, index, param_type, &aggpos,
+               = add_condition (summary, params_summary, index,
+                                param_type, &aggpos,
                                 this_code, gimple_cond_rhs (last), param_ops);
              e->aux = edge_predicate_pool.allocate ();
              *(predicate *) e->aux = p;
@@ -1387,7 +1389,8 @@ set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi,
     return;
   FOR_EACH_EDGE (e, ei, bb->succs) if (e->flags & EDGE_FALSE_VALUE)
     {
-      predicate p = add_condition (summary, index, param_type, &aggpos,
+      predicate p = add_condition (summary, params_summary, index,
+                                  param_type, &aggpos,
                                   predicate::is_not_constant, NULL_TREE);
       e->aux = edge_predicate_pool.allocate ();
       *(predicate *) e->aux = p;
@@ -1401,6 +1404,7 @@ set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi,
 static void
 set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi,
                                     class ipa_fn_summary *summary,
+                                    class ipa_node_params *params_summary,
                                     basic_block bb)
 {
   gimple *lastg;
@@ -1470,15 +1474,15 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi,
       if (dominated_by_p (CDI_POST_DOMINATORS, bb, e->dest))
        p = true;
       else if (min == max)
-       p = add_condition (summary, index, param_type, &aggpos, EQ_EXPR,
-                          min, param_ops);
+       p = add_condition (summary, params_summary, index, param_type,
+                          &aggpos, EQ_EXPR, min, param_ops);
       else
        {
          predicate p1, p2;
-         p1 = add_condition (summary, index, param_type, &aggpos, GE_EXPR,
-                             min, param_ops);
-         p2 = add_condition (summary, index, param_type, &aggpos, LE_EXPR,
-                             max, param_ops);
+         p1 = add_condition (summary, params_summary, index, param_type,
+                             &aggpos, GE_EXPR, min, param_ops);
+         p2 = add_condition (summary,  params_summary,index, param_type,
+                             &aggpos, LE_EXPR, max, param_ops);
          p = p1 & p2;
        }
       *(class predicate *) e->aux
@@ -1559,7 +1563,8 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi,
       tree max = ranges[i].second;
 
       if (min == max)
-       p_seg &= add_condition (summary, index, param_type, &aggpos, NE_EXPR,
+       p_seg &= add_condition (summary, params_summary, index,
+                               param_type, &aggpos, NE_EXPR,
                                min, param_ops);
       else
        {
@@ -1567,7 +1572,8 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi,
             of switch index.  */
          if (wi::lt_p (vr_wmin, wi::to_wide (min), TYPE_SIGN (type)))
            {
-             p_seg &= add_condition (summary, index, param_type, &aggpos,
+             p_seg &= add_condition (summary, params_summary, index,
+                                     param_type, &aggpos,
                                      LT_EXPR, min, param_ops);
              p_all = p_all.or_with (summary->conds, p_seg);
            }
@@ -1580,7 +1586,8 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi,
              break;
            }
 
-         p_seg = add_condition (summary, index, param_type, &aggpos, GT_EXPR,
+         p_seg = add_condition (summary, params_summary, index,
+                                param_type, &aggpos, GT_EXPR,
                                 max, param_ops);
        }
     }
@@ -1599,7 +1606,8 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi,
 static void
 compute_bb_predicates (struct ipa_func_body_info *fbi,
                       struct cgraph_node *node,
-                      class ipa_fn_summary *summary)
+                      class ipa_fn_summary *summary,
+                      class ipa_node_params *params_summary)
 {
   struct function *my_function = DECL_STRUCT_FUNCTION (node->decl);
   bool done = false;
@@ -1607,8 +1615,8 @@ compute_bb_predicates (struct ipa_func_body_info *fbi,
 
   FOR_EACH_BB_FN (bb, my_function)
     {
-      set_cond_stmt_execution_predicate (fbi, summary, bb);
-      set_switch_stmt_execution_predicate (fbi, summary, bb);
+      set_cond_stmt_execution_predicate (fbi, summary, params_summary, bb);
+      set_switch_stmt_execution_predicate (fbi, summary, params_summary, bb);
     }
 
   /* Entry block is always executable.  */
@@ -1701,6 +1709,7 @@ compute_bb_predicates (struct ipa_func_body_info *fbi,
 static predicate
 will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi,
                                    class ipa_fn_summary *summary,
+                                   class ipa_node_params *params_summary,
                                    tree expr,
                                    vec<predicate> nonconstant_names)
 {
@@ -1712,7 +1721,7 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi,
 
   parm = unmodified_parm (fbi, NULL, expr, NULL);
   if (parm && (index = ipa_get_param_decl_index (fbi->info, parm)) >= 0)
-    return add_condition (summary, index, TREE_TYPE (parm), NULL,
+    return add_condition (summary, params_summary, index, TREE_TYPE (parm), NULL,
                          predicate::changed, NULL_TREE);
   if (is_gimple_min_invariant (expr))
     return false;
@@ -1722,6 +1731,7 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi,
     {
       predicate p1
        = will_be_nonconstant_expr_predicate (fbi, summary,
+                                             params_summary,
                                              TREE_OPERAND (expr, 0),
                                              nonconstant_names);
       if (p1 == true)
@@ -1729,6 +1739,7 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi,
 
       predicate p2
        = will_be_nonconstant_expr_predicate (fbi, summary,
+                                             params_summary,
                                              TREE_OPERAND (expr, 1),
                                              nonconstant_names);
       return p1.or_with (summary->conds, p2);
@@ -1737,6 +1748,7 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi,
     {
       predicate p1
        = will_be_nonconstant_expr_predicate (fbi, summary,
+                                             params_summary,
                                              TREE_OPERAND (expr, 0),
                                              nonconstant_names);
       if (p1 == true)
@@ -1744,12 +1756,14 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi,
 
       predicate p2
        = will_be_nonconstant_expr_predicate (fbi, summary,
+                                             params_summary,
                                              TREE_OPERAND (expr, 1),
                                              nonconstant_names);
       if (p2 == true)
        return p2;
       p1 = p1.or_with (summary->conds, p2);
       p2 = will_be_nonconstant_expr_predicate (fbi, summary,
+                                              params_summary,
                                               TREE_OPERAND (expr, 2),
                                               nonconstant_names);
       return p2.or_with (summary->conds, p1);
@@ -1771,6 +1785,7 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi,
 static predicate
 will_be_nonconstant_predicate (struct ipa_func_body_info *fbi,
                               class ipa_fn_summary *summary,
+                              class ipa_node_params *params_summary,
                               gimple *stmt,
                               vec<predicate> nonconstant_names)
 {
@@ -1828,7 +1843,8 @@ will_be_nonconstant_predicate (struct ipa_func_body_info *fbi,
 
   if (is_load)
     op_non_const =
-      add_condition (summary, base_index, param_type, &aggpos,
+      add_condition (summary, params_summary,
+                    base_index, param_type, &aggpos,
                     predicate::changed, NULL_TREE);
   else
     op_non_const = false;
@@ -1840,7 +1856,8 @@ will_be_nonconstant_predicate (struct ipa_func_body_info *fbi,
       if (parm && (index = ipa_get_param_decl_index (fbi->info, parm)) >= 0)
        {
          if (index != base_index)
-           p = add_condition (summary, index, TREE_TYPE (parm), NULL,
+           p = add_condition (summary, params_summary, index,
+                              TREE_TYPE (parm), NULL,
                               predicate::changed, NULL_TREE);
          else
            continue;
@@ -2027,7 +2044,9 @@ param_change_prob (ipa_func_body_info *fbi, gimple *stmt, int i)
 
 static bool
 phi_result_unknown_predicate (ipa_func_body_info *fbi,
-                             ipa_fn_summary *summary, basic_block bb,
+                             ipa_fn_summary *summary,
+                             class ipa_node_params *params_summary,
+                             basic_block bb,
                              predicate *p,
                              vec<predicate> nonconstant_names)
 {
@@ -2071,7 +2090,7 @@ phi_result_unknown_predicate (ipa_func_body_info *fbi,
       || !is_gimple_ip_invariant (gimple_cond_rhs (stmt)))
     return false;
 
-  *p = will_be_nonconstant_expr_predicate (fbi, summary,
+  *p = will_be_nonconstant_expr_predicate (fbi, summary, params_summary,
                                           gimple_cond_lhs (stmt),
                                           nonconstant_names);
   if (*p == true)
@@ -2264,6 +2283,7 @@ analyze_function_body (struct cgraph_node *node, bool early)
   struct function *my_function = DECL_STRUCT_FUNCTION (node->decl);
   sreal freq;
   class ipa_fn_summary *info = ipa_fn_summaries->get_create (node);
+  class ipa_node_params *params_summary = early ? NULL : IPA_NODE_REF (node);
   predicate bb_predicate;
   struct ipa_func_body_info fbi;
   vec<predicate> nonconstant_names = vNULL;
@@ -2329,7 +2349,7 @@ analyze_function_body (struct cgraph_node *node, bool early)
                           bb_predicate);
 
   if (fbi.info)
-    compute_bb_predicates (&fbi, node, info);
+    compute_bb_predicates (&fbi, node, info, params_summary);
   order = XNEWVEC (int, n_basic_blocks_for_fn (cfun));
   nblocks = pre_and_rev_post_order_compute (NULL, order, false);
   for (n = 0; n < nblocks; n++)
@@ -2371,7 +2391,9 @@ analyze_function_body (struct cgraph_node *node, bool early)
               gsi_next (&bsi))
            {
              if (first_phi
-                 && !phi_result_unknown_predicate (&fbi, info, bb,
+                 && !phi_result_unknown_predicate (&fbi, info,
+                                                   params_summary,
+                                                   bb,
                                                    &phi_predicate,
                                                    nonconstant_names))
                break;
@@ -2469,7 +2491,7 @@ analyze_function_body (struct cgraph_node *node, bool early)
             just maximum of the possible paths.  */
          if (fbi.info)
            will_be_nonconstant
-             = will_be_nonconstant_predicate (&fbi, info,
+             = will_be_nonconstant_predicate (&fbi, info, params_summary,
                                               stmt, nonconstant_names);
          else
            will_be_nonconstant = true;
@@ -2536,7 +2558,8 @@ analyze_function_body (struct cgraph_node *node, bool early)
                    predicate p = bb_predicate;
                    if (fbi.info)
                      p = p & will_be_nonconstant_expr_predicate
-                                (&fbi, info, TREE_OPERAND (op, 1),
+                                (&fbi, info, params_summary,
+                                 TREE_OPERAND (op, 1),
                                  nonconstant_names);
                    if (p != false)
                      {
@@ -2581,6 +2604,7 @@ analyze_function_body (struct cgraph_node *node, bool early)
            {
              predicate will_be_nonconstant
                = will_be_nonconstant_expr_predicate (&fbi, info,
+                                                     params_summary,
                                                      niter_desc.niter,
                                                      nonconstant_names);
              if (will_be_nonconstant != true)
@@ -2625,7 +2649,9 @@ analyze_function_body (struct cgraph_node *node, bool early)
                    continue;
 
                  predicate will_be_nonconstant
-                   = will_be_nonconstant_expr_predicate (&fbi, info, iv.step,
+                   = will_be_nonconstant_expr_predicate (&fbi, info,
+                                                         params_summary,
+                                                         iv.step,
                                                          nonconstant_names);
                  if (will_be_nonconstant != true)
                    will_be_nonconstant = bb_predicate & will_be_nonconstant;
@@ -2964,29 +2990,73 @@ ipa_call_context::ipa_call_context (cgraph_node *node,
 {
 }
 
+/* Set THIS to be a duplicate of CTX.  Copy all relevant info.  */
+
 void
 ipa_call_context::duplicate_from (const ipa_call_context &ctx)
 {
   m_node = ctx.m_node;
   m_possible_truths = ctx.m_possible_truths;
   m_nonspec_possible_truths = ctx.m_nonspec_possible_truths;
+  class ipa_node_params *params_summary = IPA_NODE_REF (m_node);
+  unsigned int nargs = ipa_get_param_count (params_summary);
 
+  m_inline_param_summary = vNULL;
+  /* Copy the info only if there is at least one useful entry.  */
   if (ctx.m_inline_param_summary.exists ())
-    m_inline_param_summary = ctx.m_inline_param_summary.copy ();
-  else
-    m_inline_param_summary = vNULL;
+    {
+      unsigned int n = MIN (ctx.m_inline_param_summary.length (), nargs);
+
+      for (unsigned int i = 0; i < n; i++)
+       if (ipa_is_param_used_by_ipa_predicates (params_summary, i)
+           && !ctx.m_inline_param_summary[i].useless_p ())
+         {
+            m_inline_param_summary
+                   = ctx.m_inline_param_summary.copy ();
+           break;
+         }
+    }
+  m_known_vals = vNULL;
   if (ctx.m_known_vals.exists ())
-    m_known_vals = ctx.m_known_vals.copy ();
-  else
-    m_known_vals = vNULL;
+    {
+      unsigned int n = MIN (ctx.m_known_vals.length (), nargs);
+
+      for (unsigned int i = 0; i < n; i++)
+       if (ipa_is_param_used_by_indirect_call (params_summary, i)
+           && ctx.m_known_vals[i])
+         {
+           m_known_vals = ctx.m_known_vals.copy ();
+           break;
+         }
+    }
+
+  m_known_contexts = vNULL;
   if (ctx.m_known_contexts.exists ())
-    m_known_contexts = ctx.m_known_contexts.copy ();
-  else
-    m_known_contexts = vNULL;
+    {
+      unsigned int n = MIN (ctx.m_known_contexts.length (), nargs);
+
+      for (unsigned int i = 0; i < n; i++)
+       if (ipa_is_param_used_by_polymorphic_call (params_summary, i)
+           && !ctx.m_known_contexts[i].useless_p ())
+         {
+           m_known_contexts = ctx.m_known_contexts.copy ();
+           break;
+         }
+    }
+
+  m_known_aggs = vNULL;
   if (ctx.m_known_aggs.exists ())
-    m_known_aggs = ctx.m_known_aggs.copy ();
-  else
-    m_known_aggs = vNULL;
+    {
+      unsigned int n = MIN (ctx.m_known_aggs.length (), nargs);
+
+      for (unsigned int i = 0; i < n; i++)
+       if (ipa_is_param_used_by_indirect_call (params_summary, i)
+           && ctx.m_known_aggs[i])
+         {
+           m_known_aggs = ctx.m_known_aggs.copy ();
+           break;
+         }
+    }
 }
 
 /* Release memory used by known_vals/contexts/aggs vectors.
@@ -3016,49 +3086,107 @@ ipa_call_context::equal_to (const ipa_call_context &ctx)
       || m_possible_truths != ctx.m_possible_truths
       || m_nonspec_possible_truths != ctx.m_nonspec_possible_truths)
     return false;
-  if (m_inline_param_summary.exists () != ctx.m_inline_param_summary.exists ()
-      || m_known_vals.exists () != ctx.m_known_vals.exists()
-      || m_known_contexts.exists () != ctx.m_known_contexts.exists ()
-      || m_known_aggs.exists () != ctx.m_known_aggs.exists ())
-    return false;
-  if (m_inline_param_summary.exists ())
+
+  class ipa_node_params *params_summary = IPA_NODE_REF (m_node);
+  unsigned int nargs = ipa_get_param_count (params_summary);
+
+  if (m_inline_param_summary.exists () || ctx.m_inline_param_summary.exists ())
     {
-      if (m_inline_param_summary.length () != ctx.m_inline_param_summary.length ())
-       return false;
-      for (unsigned int i = 0; i < m_inline_param_summary.length (); i++)
-       if (!m_inline_param_summary[i].equal_to (ctx.m_inline_param_summary[i]))
-         return false;
+      for (unsigned int i = 0; i < nargs; i++)
+       {
+         if (!ipa_is_param_used_by_ipa_predicates (params_summary, i))
+           continue;
+         if (i >= m_inline_param_summary.length ()
+             || m_inline_param_summary[i].useless_p ())
+           {
+             if (i < ctx.m_inline_param_summary.length ()
+                 && !ctx.m_inline_param_summary[i].useless_p ())
+               return false;
+             continue;
+           }
+         if (i >= ctx.m_inline_param_summary.length ()
+             || ctx.m_inline_param_summary[i].useless_p ())
+           {
+             if (i < m_inline_param_summary.length ()
+                 && !m_inline_param_summary[i].useless_p ())
+               return false;
+             continue;
+           }
+         if (!m_inline_param_summary[i].equal_to
+                (ctx.m_inline_param_summary[i]))
+           return false;
+       }
     }
-  if (m_known_vals.exists ())
+  if (m_known_vals.exists () || ctx.m_known_vals.exists ())
     {
-      if (m_known_vals.length () != ctx.m_known_vals.length ())
-       return false;
-      for (unsigned int i = 0; i < m_known_vals.length (); i++)
+      for (unsigned int i = 0; i < nargs; i++)
        {
-         tree t1 = m_known_vals[i];
-         tree t2 = ctx.m_known_vals[i];
-
-         if (t1 != t2
-             && (!t1 || !t2 || !operand_equal_p (m_known_vals[i],
-                                                 ctx.m_known_vals[i], 0)))
+         if (!ipa_is_param_used_by_indirect_call (params_summary, i))
+           continue;
+         if (i >= m_known_vals.length () || !m_known_vals[i])
+           {
+             if (i < ctx.m_known_vals.length () && ctx.m_known_vals[i])
+               return false;
+             continue;
+           }
+         if (i >= ctx.m_known_vals.length () || !ctx.m_known_vals[i])
+           {
+             if (i < m_known_vals.length () && m_known_vals[i])
+               return false;
+             continue;
+           }
+         if (m_known_vals[i] != ctx.m_known_vals[i])
            return false;
        }
     }
-  if (m_known_contexts.exists ())
+  if (m_known_contexts.exists () || ctx.m_known_contexts.exists ())
     {
-      if (m_known_contexts.length () != ctx.m_known_contexts.length ())
-       return false;
-      for (unsigned int i = 0; i < m_known_contexts.length (); i++)
-       if (!m_known_contexts[i].equal_to (ctx.m_known_contexts[i]))
-         return false;
+      for (unsigned int i = 0; i < nargs; i++)
+       {
+         if (!ipa_is_param_used_by_polymorphic_call (params_summary, i))
+           continue;
+         if (i >= m_known_contexts.length ()
+             || m_known_contexts[i].useless_p ())
+           {
+             if (i < ctx.m_known_contexts.length ()
+                 && !ctx.m_known_contexts[i].useless_p ())
+               return false;
+             continue;
+           }
+         if (i >= ctx.m_known_contexts.length ()
+             || ctx.m_known_contexts[i].useless_p ())
+           {
+             if (i < m_known_contexts.length ()
+                 && !m_known_contexts[i].useless_p ())
+               return false;
+             continue;
+           }
+         if (!m_known_contexts[i].equal_to
+                (ctx.m_known_contexts[i]))
+           return false;
+       }
     }
-  if (m_known_aggs.exists ())
+  if (m_known_aggs.exists () || ctx.m_known_aggs.exists ())
     {
-      if (m_known_aggs.length () != ctx.m_known_aggs.length ())
-       return false;
-      for (unsigned int i = 0; i < m_known_aggs.length (); i++)
-       if (!m_known_aggs[i]->equal_to (*ctx.m_known_aggs[i]))
-         return false;
+      for (unsigned int i = 0; i < nargs; i++)
+       {
+         if (!ipa_is_param_used_by_indirect_call (params_summary, i))
+           continue;
+         if (i >= m_known_aggs.length () || !m_known_aggs[i])
+           {
+             if (i < ctx.m_known_aggs.length () && ctx.m_known_aggs[i])
+               return false;
+             continue;
+           }
+         if (i >= ctx.m_known_aggs.length () || !ctx.m_known_aggs[i])
+           {
+             if (i < m_known_aggs.length () && m_known_aggs[i])
+               return false;
+             continue;
+           }
+         if (m_known_aggs[i] != ctx.m_known_aggs[i])
+           return false;
+       }
     }
   return true;
 }
@@ -3319,6 +3447,7 @@ static void
 remap_edge_summaries (struct cgraph_edge *inlined_edge,
                      struct cgraph_node *node,
                      class ipa_fn_summary *info,
+                     class ipa_node_params *params_summary,
                      class ipa_fn_summary *callee_info,
                      vec<int> operand_map,
                      vec<int> offset_map,
@@ -3339,7 +3468,8 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge,
          if (es->predicate)
            {
              p = es->predicate->remap_after_inlining
-                                    (info, callee_info, operand_map,
+                                    (info, params_summary,
+                                     callee_info, operand_map,
                                      offset_map, possible_truths,
                                      *toplev_predicate);
              edge_set_predicate (e, &p);
@@ -3348,7 +3478,8 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge,
            edge_set_predicate (e, toplev_predicate);
        }
       else
-       remap_edge_summaries (inlined_edge, e->callee, info, callee_info,
+       remap_edge_summaries (inlined_edge, e->callee, info,
+                             params_summary, callee_info,
                              operand_map, offset_map, possible_truths,
                              toplev_predicate);
     }
@@ -3362,7 +3493,8 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge,
       if (es->predicate)
        {
          p = es->predicate->remap_after_inlining
-                                (info, callee_info, operand_map, offset_map,
+                                (info, params_summary,
+                                 callee_info, operand_map, offset_map,
                                  possible_truths, *toplev_predicate);
          edge_set_predicate (e, &p);
        }
@@ -3375,6 +3507,7 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge,
 
 static void
 remap_hint_predicate (class ipa_fn_summary *info,
+                     class ipa_node_params *params_summary,
                      class ipa_fn_summary *callee_info,
                      predicate **hint,
                      vec<int> operand_map,
@@ -3387,7 +3520,7 @@ remap_hint_predicate (class ipa_fn_summary *info,
   if (!*hint)
     return;
   p = (*hint)->remap_after_inlining
-                        (info, callee_info,
+                        (info, params_summary, callee_info,
                          operand_map, offset_map,
                          possible_truths, *toplev_predicate);
   if (p != false && p != true)
@@ -3415,6 +3548,8 @@ ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge)
   int i;
   predicate toplev_predicate;
   class ipa_call_summary *es = ipa_call_summaries->get (edge);
+  class ipa_node_params *params_summary = (ipa_node_params_sum
+                                          ? IPA_NODE_REF (to) : NULL);
 
   if (es->predicate)
     toplev_predicate = *es->predicate;
@@ -3461,19 +3596,21 @@ ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge)
                }
            }
          operand_map[i] = map;
-         gcc_assert (map < ipa_get_param_count (IPA_NODE_REF (to)));
+         gcc_assert (map < ipa_get_param_count (params_summary));
        }
     }
   for (i = 0; vec_safe_iterate (callee_info->size_time_table, i, &e); i++)
     {
       predicate p;
       p = e->exec_predicate.remap_after_inlining
-                            (info, callee_info, operand_map,
+                            (info, params_summary,
+                             callee_info, operand_map,
                              offset_map, clause,
                              toplev_predicate);
       predicate nonconstp;
       nonconstp = e->nonconst_predicate.remap_after_inlining
-                                    (info, callee_info, operand_map,
+                                    (info, params_summary,
+                                     callee_info, operand_map,
                                      offset_map, clause,
                                      toplev_predicate);
       if (p != false && nonconstp != false)
@@ -3491,12 +3628,13 @@ ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge)
          info->account_size_time (e->size, add_time, p, nonconstp);
        }
     }
-  remap_edge_summaries (edge, edge->callee, info, callee_info, operand_map,
+  remap_edge_summaries (edge, edge->callee, info, params_summary,
+                       callee_info, operand_map,
                        offset_map, clause, &toplev_predicate);
-  remap_hint_predicate (info, callee_info,
+  remap_hint_predicate (info, params_summary, callee_info,
                        &callee_info->loop_iterations,
                        operand_map, offset_map, clause, &toplev_predicate);
-  remap_hint_predicate (info, callee_info,
+  remap_hint_predicate (info, params_summary, callee_info,
                        &callee_info->loop_stride,
                        operand_map, offset_map, clause, &toplev_predicate);
 
@@ -3687,6 +3825,7 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data,
       unsigned int index;
       struct cgraph_node *node;
       class ipa_fn_summary *info;
+      class ipa_node_params *params_summary;
       class ipa_size_summary *size_info;
       lto_symtab_encoder_t encoder;
       struct bitpack_d bp;
@@ -3698,6 +3837,7 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data,
       node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref (encoder,
                                                                index));
       info = node->prevailing_p () ? ipa_fn_summaries->get_create (node) : NULL;
+      params_summary = node->prevailing_p () ? IPA_NODE_REF (node) : NULL;
       size_info = node->prevailing_p ()
                  ? ipa_size_summaries->get_create (node) : NULL;
 
@@ -3746,6 +3886,9 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data,
          c.param_ops = NULL;
          if (info)
            vec_safe_reserve_exact (c.param_ops, count3);
+         if (params_summary)
+           ipa_set_param_used_by_ipa_predicates
+                   (params_summary, c.operand_num, true);
          for (k = 0; k < count3; k++)
            {
              struct expr_eval_op op;
index b5e3cf44323896849709e738962a93a0c5af9723..721f0957f9f9bfbf062cd0f826ab12fd3c54cfdc 100644 (file)
@@ -505,6 +505,7 @@ predicate::remap_after_duplication (clause_t possible_truths)
 
 predicate
 predicate::remap_after_inlining (class ipa_fn_summary *info,
+                                class ipa_node_params *params_summary,
                                 class ipa_fn_summary *callee_info,
                                 vec<int> operand_map,
                                 vec<int> offset_map,
@@ -566,7 +567,7 @@ predicate::remap_after_inlining (class ipa_fn_summary *info,
                    ap.offset = c->offset + offset_delta;
                    ap.agg_contents = c->agg_contents;
                    ap.by_ref = c->by_ref;
-                   cond_predicate = add_condition (info,
+                   cond_predicate = add_condition (info, params_summary,
                                                    operand_map[c->operand_num],
                                                    c->type, &ap, c->code,
                                                    c->val, c->param_ops);
@@ -629,7 +630,9 @@ predicate::stream_out (struct output_block *ob)
    aggregate.  */
 
 predicate
-add_condition (class ipa_fn_summary *summary, int operand_num,
+add_condition (class ipa_fn_summary *summary,
+              class ipa_node_params *params_summary,
+              int operand_num,
               tree type, struct agg_position_info *aggpos,
               enum tree_code code, tree val, expr_eval_ops param_ops)
 {
@@ -640,6 +643,9 @@ add_condition (class ipa_fn_summary *summary, int operand_num,
   bool agg_contents, by_ref;
   expr_eval_op *op;
 
+  if (params_summary)
+    ipa_set_param_used_by_ipa_predicates (params_summary, operand_num, true);
+
   if (aggpos)
     {
       offset = aggpos->offset;
index 2509b1e516217ac616b989f1343dcbce792a2e7a..25cd5f2797dd4c87e522e44d34ed00cb3295f731 100644 (file)
@@ -77,10 +77,14 @@ struct inline_param_summary
 
      Value 0 is reserved for compile time invariants. */
   int change_prob;
-  bool equal_to (const inline_param_summary &other)
+  bool equal_to (const inline_param_summary &other) const
   {
     return change_prob == other.change_prob;
   }
+  bool useless_p (void) const
+  {
+    return change_prob == REG_BR_PROB_BASE;
+  }
 };
 
 typedef vec<condition, va_gc> *conditions;
@@ -233,6 +237,7 @@ public:
 
   /* Return predicate equal to THIS after inlining.  */
   predicate remap_after_inlining (class ipa_fn_summary *,
+                                 class ipa_node_params *params_summary,
                                  class ipa_fn_summary *,
                                  vec<int>, vec<int>, clause_t, const predicate &);
 
@@ -254,7 +259,9 @@ private:
 };
 
 void dump_condition (FILE *f, conditions conditions, int cond);
-predicate add_condition (class ipa_fn_summary *summary, int operand_num,
+predicate add_condition (class ipa_fn_summary *summary,
+                        class ipa_node_params *params_summary,
+                        int operand_num,
                         tree type, struct agg_position_info *aggpos,
                         enum tree_code code, tree val,
                         expr_eval_ops param_ops = NULL);
index 5491aee2fc6090819f86b029b10d1f8b9157112b..83cf4d1c7bacf94778e19b917aef21e83da9f535 100644 (file)
@@ -227,8 +227,10 @@ ipa_populate_param_decls (struct cgraph_node *node,
   for (parm = fnargs; parm; parm = DECL_CHAIN (parm))
     {
       descriptors[param_num].decl_or_type = parm;
-      descriptors[param_num].move_cost = estimate_move_cost (TREE_TYPE (parm),
-                                                            true);
+      unsigned int cost = estimate_move_cost (TREE_TYPE (parm), true);
+      descriptors[param_num].move_cost = cost;
+      /* Watch overflow, move_cost is a bitfield.  */
+      gcc_checking_assert (cost == descriptors[param_num].move_cost);
       param_num++;
     }
 }
@@ -2116,11 +2118,12 @@ ipa_is_ssa_with_stmt_def (tree t)
 
 /* Find the indirect call graph edge corresponding to STMT and mark it as a
    call to a parameter number PARAM_INDEX.  NODE is the caller.  Return the
-   indirect call graph edge.  */
+   indirect call graph edge.
+   If POLYMORPHIC is true record is as a destination of polymorphic call.  */
 
 static struct cgraph_edge *
 ipa_note_param_call (struct cgraph_node *node, int param_index,
-                    gcall *stmt)
+                    gcall *stmt, bool polymorphic)
 {
   struct cgraph_edge *cs;
 
@@ -2129,6 +2132,11 @@ ipa_note_param_call (struct cgraph_node *node, int param_index,
   cs->indirect_info->agg_contents = 0;
   cs->indirect_info->member_ptr = 0;
   cs->indirect_info->guaranteed_unmodified = 0;
+  ipa_set_param_used_by_indirect_call (IPA_NODE_REF (node),
+                                         param_index, true);
+  if (cs->indirect_info->polymorphic || polymorphic)
+    ipa_set_param_used_by_polymorphic_call
+           (IPA_NODE_REF (node), param_index, true);
   return cs;
 }
 
@@ -2204,7 +2212,7 @@ ipa_analyze_indirect_call_uses (struct ipa_func_body_info *fbi, gcall *call,
       tree var = SSA_NAME_VAR (target);
       int index = ipa_get_param_decl_index (info, var);
       if (index >= 0)
-       ipa_note_param_call (fbi->node, index, call);
+       ipa_note_param_call (fbi->node, index, call, false);
       return;
     }
 
@@ -2216,7 +2224,8 @@ ipa_analyze_indirect_call_uses (struct ipa_func_body_info *fbi, gcall *call,
                                 gimple_assign_rhs1 (def), &index, &offset,
                                 NULL, &by_ref, &guaranteed_unmodified))
     {
-      struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index, call);
+      struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index,
+                                                   call, false);
       cs->indirect_info->offset = offset;
       cs->indirect_info->agg_contents = 1;
       cs->indirect_info->by_ref = by_ref;
@@ -2317,7 +2326,8 @@ ipa_analyze_indirect_call_uses (struct ipa_func_body_info *fbi, gcall *call,
   if (index >= 0
       && parm_preserved_before_stmt_p (fbi, index, call, rec))
     {
-      struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index, call);
+      struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index,
+                                                   call, false);
       cs->indirect_info->offset = offset;
       cs->indirect_info->agg_contents = 1;
       cs->indirect_info->member_ptr = 1;
@@ -2377,7 +2387,8 @@ ipa_analyze_virtual_call_uses (struct ipa_func_body_info *fbi,
        return;
     }
 
-  struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index, call);
+  struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index,
+                                               call, true);
   class cgraph_indirect_call_info *ii = cs->indirect_info;
   ii->offset = anc_offset;
   ii->otr_token = tree_to_uhwi (OBJ_TYPE_REF_TOKEN (target));
@@ -3510,6 +3521,11 @@ update_indirect_edges_after_inlining (struct cgraph_edge *cs,
              if (ici->polymorphic
                  && !ipa_get_jf_pass_through_type_preserved (jfunc))
                ici->vptr_changed = true;
+             ipa_set_param_used_by_indirect_call (new_root_info,
+                                                  ici->param_index, true);
+             if (ici->polymorphic)
+               ipa_set_param_used_by_polymorphic_call (new_root_info,
+                                                       ici->param_index, true);
            }
        }
       else if (jfunc->type == IPA_JF_ANCESTOR)
@@ -4055,6 +4071,12 @@ ipa_print_node_params (FILE *f, struct cgraph_node *node)
       ipa_dump_param (f, info, i);
       if (ipa_is_param_used (info, i))
        fprintf (f, " used");
+      if (ipa_is_param_used_by_ipa_predicates (info, i))
+       fprintf (f, " used_by_ipa_predicates");
+      if (ipa_is_param_used_by_indirect_call (info, i))
+       fprintf (f, " used_by_indirect_call");
+      if (ipa_is_param_used_by_polymorphic_call (info, i))
+       fprintf (f, " used_by_polymorphic_call");
       c = ipa_get_controlled_uses (info, i);
       if (c == IPA_UNDESCRIBED_USE)
        fprintf (f, " undescribed_use");
@@ -4331,7 +4353,8 @@ ipa_write_indirect_edge_info (struct output_block *ob,
 static void
 ipa_read_indirect_edge_info (class lto_input_block *ib,
                             class data_in *data_in,
-                            struct cgraph_edge *cs)
+                            struct cgraph_edge *cs,
+                            class ipa_node_params *info)
 {
   class cgraph_indirect_call_info *ii = cs->indirect_info;
   struct bitpack_d bp;
@@ -4354,6 +4377,14 @@ ipa_read_indirect_edge_info (class lto_input_block *ib,
       ii->otr_type = stream_read_tree (ib, data_in);
       ii->context.stream_in (ib, data_in);
     }
+  if (info && ii->param_index >= 0)
+    {
+      if (ii->polymorphic)
+       ipa_set_param_used_by_polymorphic_call (info,
+                                               ii->param_index , true);
+      ipa_set_param_used_by_indirect_call (info,
+                                          ii->param_index, true);
+    }
 }
 
 /* Stream out NODE info to OB.  */
@@ -4523,7 +4554,7 @@ ipa_read_node_info (class lto_input_block *ib, struct cgraph_node *node,
   for (e = node->indirect_calls; e; e = e->next_callee)
     {
       ipa_read_edge_info (ib, data_in, e, prevails);
-      ipa_read_indirect_edge_info (ib, data_in, e);
+      ipa_read_indirect_edge_info (ib, data_in, e, info);
     }
 }
 
index 121d0f647b11a16f9b91442bb894edada26bb65c..9f2479e7fdc51b1a90c142dd617c94b5103de3f9 100644 (file)
@@ -333,9 +333,12 @@ struct GTY(()) ipa_param_descriptor
      says how many there are.  If any use could not be described by means of
      ipa-prop structures, this is IPA_UNDESCRIBED_USE.  */
   int controlled_uses;
-  unsigned int move_cost : 31;
+  unsigned int move_cost : 28;
   /* The parameter is used.  */
   unsigned used : 1;
+  unsigned used_by_ipa_predicates : 1;
+  unsigned used_by_indirect_call : 1;
+  unsigned used_by_polymorphic_call : 1;
 };
 
 /* ipa_node_params stores information related to formal parameters of functions
@@ -519,6 +522,36 @@ ipa_set_param_used (class ipa_node_params *info, int i, bool val)
   (*info->descriptors)[i].used = val;
 }
 
+/* Set the used_by_ipa_predicates flag corresponding to the Ith formal
+   parameter of the function associated with INFO to VAL.  */
+
+static inline void
+ipa_set_param_used_by_ipa_predicates (class ipa_node_params *info, int i, bool val)
+{
+  gcc_checking_assert (info->descriptors);
+  (*info->descriptors)[i].used_by_ipa_predicates = val;
+}
+
+/* Set the used_by_indirect_call flag corresponding to the Ith formal
+   parameter of the function associated with INFO to VAL.  */
+
+static inline void
+ipa_set_param_used_by_indirect_call (class ipa_node_params *info, int i, bool val)
+{
+  gcc_checking_assert (info->descriptors);
+  (*info->descriptors)[i].used_by_indirect_call = val;
+}
+
+/* Set the .used_by_polymorphic_call flag corresponding to the Ith formal
+   parameter of the function associated with INFO to VAL.  */
+
+static inline void
+ipa_set_param_used_by_polymorphic_call (class ipa_node_params *info, int i, bool val)
+{
+  gcc_checking_assert (info->descriptors);
+  (*info->descriptors)[i].used_by_polymorphic_call = val;
+}
+
 /* Return how many uses described by ipa-prop a parameter has or
    IPA_UNDESCRIBED_USE if there is a use that is not described by these
    structures.  */
@@ -550,6 +583,36 @@ ipa_is_param_used (class ipa_node_params *info, int i)
   return (*info->descriptors)[i].used;
 }
 
+/* Return the used_by_ipa_predicates flag corresponding to the Ith formal
+   parameter of the function associated with INFO.  */
+
+static inline bool
+ipa_is_param_used_by_ipa_predicates (class ipa_node_params *info, int i)
+{
+  gcc_checking_assert (info->descriptors);
+  return (*info->descriptors)[i].used_by_ipa_predicates;
+}
+
+/* Return the used_by_indirect_call flag corresponding to the Ith formal
+   parameter of the function associated with INFO.  */
+
+static inline bool
+ipa_is_param_used_by_indirect_call (class ipa_node_params *info, int i)
+{
+  gcc_checking_assert (info->descriptors);
+  return (*info->descriptors)[i].used_by_indirect_call;
+}
+
+/* Return the used_by_polymorphic_call flag corresponding to the Ith formal
+   parameter of the function associated with INFO.  */
+
+static inline bool
+ipa_is_param_used_by_polymorphic_call (class ipa_node_params *info, int i)
+{
+  gcc_checking_assert (info->descriptors);
+  return (*info->descriptors)[i].used_by_polymorphic_call;
+}
+
 /* Information about replacements done in aggregates for a given node (each
    node has its linked list).  */
 struct GTY(()) ipa_agg_replacement_value