qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] PR/66760, ipa-inline-analysis.c compile-time hog


From: Paolo Bonzini
Subject: [Qemu-devel] [PATCH] PR/66760, ipa-inline-analysis.c compile-time hog
Date: Sun, 12 Jul 2015 23:39:55 +0200

From: address@hidden

In this PR, a lot of time is spent doing the same ipa_load_from_parm_agg
query over and over.  Luckily a memoization scheme is already there, it's
just not used by ipa-inline-analysis.c.  The patch moves the cache struct
(struct func_body_info) to ipa-prop.h and modify ipa-inline-analysis.c.
On some testcases from PR26854 the "alias stmt walking" timevar goes
off the profile while it used to be 30-70%.

Bootstrapped (regtest in progress) on x86_64-pc-linux-gnu.

Please commit the patch for me if approved, as I don't have anymore
the key I used to use for gcc.gnu.org.  One of these days I'll send
my new SSH public key to the overseers.

Paolo

* ipa-inline-analysis.c (unmodified_parm_or_parm_agg_item): Accept
struct func_body_info* instead of struct ipa_node_params*, expecting
fbi->info to be filled in.  Replace throughout.  Adjust call to
ipa_load_from_parm_agg.
(set_cond_stmt_execution_predicate): Accept struct func_body_info*
instead of struct ipa_node_params*.  Adjust calls to other functions
so that they pass either fbi or fbi->info.
(set_switch_stmt_execution_predicate): Likewise.
(will_be_nonconstant_predicate): Likewise.
(compute_bb_predicates): Likewise.
(estimate_function_body_sizes): Move asserts earlier.  Fill in
struct func_body_info, replace parms_info with fbi.info.  Adjust
calls to functions that now accept struct func_body_info.
* ipa-prop.c (struct param_aa_status, struct ipa_bb_info,
struct func_body_info).  Move to ipa-prop.h.
(ipa_load_from_parm_agg_1): Rename to ipa_load_from_parm_agg,
remove static.  Adjust callers.
(ipa_load_from_parm_agg): Remove.
* ipa-prop.h (struct param_aa_status, struct ipa_bb_info,
struct func_body_info).  Move from ipa-prop.c.
(ipa_load_from_parm_agg): Adjust prototype.

diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index d5dbfbd..81a6860 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -1574,7 +1574,7 @@ unmodified_parm (gimple stmt, tree op)
    loaded.  */
 
 static bool
-unmodified_parm_or_parm_agg_item (struct ipa_node_params *info,
+unmodified_parm_or_parm_agg_item (struct func_body_info *fbi,
                                  gimple stmt, tree op, int *index_p,
                                  struct agg_position_info *aggpos)
 {
@@ -1583,7 +1583,7 @@ unmodified_parm_or_parm_agg_item (struct ipa_node_params 
*info,
   gcc_checking_assert (aggpos);
   if (res)
     {
-      *index_p = ipa_get_param_decl_index (info, res);
+      *index_p = ipa_get_param_decl_index (fbi->info, res);
       if (*index_p < 0)
        return false;
       aggpos->agg_contents = false;
@@ -1599,13 +1599,14 @@ unmodified_parm_or_parm_agg_item (struct 
ipa_node_params *info,
       stmt = SSA_NAME_DEF_STMT (op);
       op = gimple_assign_rhs1 (stmt);
       if (!REFERENCE_CLASS_P (op))
-       return unmodified_parm_or_parm_agg_item (info, stmt, op, index_p,
+       return unmodified_parm_or_parm_agg_item (fbi, stmt, op, index_p,
                                                 aggpos);
     }
 
   aggpos->agg_contents = true;
-  return ipa_load_from_parm_agg (info, stmt, op, index_p, &aggpos->offset,
-                                &aggpos->by_ref);
+  return ipa_load_from_parm_agg (fbi, fbi->info->descriptors,
+                                stmt, op, index_p, &aggpos->offset,
+                                NULL, &aggpos->by_ref);
 }
 
 /* See if statement might disappear after inlining.
@@ -1744,7 +1745,7 @@ eliminated_by_inlining_prob (gimple stmt)
    predicates to the CFG edges.   */
 
 static void
-set_cond_stmt_execution_predicate (struct ipa_node_params *info,
+set_cond_stmt_execution_predicate (struct func_body_info *fbi,
                                   struct inline_summary *summary,
                                   basic_block bb)
 {
@@ -1767,7 +1768,7 @@ set_cond_stmt_execution_predicate (struct ipa_node_params 
*info,
   /* TODO: handle conditionals like
      var = op0 < 4;
      if (var != 0).  */
-  if (unmodified_parm_or_parm_agg_item (info, last, op, &index, &aggpos))
+  if (unmodified_parm_or_parm_agg_item (fbi, last, op, &index, &aggpos))
     {
       code = gimple_cond_code (last);
       inverted_code = invert_tree_comparison (code, HONOR_NANS (op));
@@ -1810,8 +1811,7 @@ set_cond_stmt_execution_predicate (struct ipa_node_params 
*info,
       || gimple_call_num_args (set_stmt) != 1)
     return;
   op2 = gimple_call_arg (set_stmt, 0);
-  if (!unmodified_parm_or_parm_agg_item
-      (info, set_stmt, op2, &index, &aggpos))
+  if (!unmodified_parm_or_parm_agg_item (fbi, set_stmt, op2, &index, &aggpos))
     return;
   FOR_EACH_EDGE (e, ei, bb->succs) if (e->flags & EDGE_FALSE_VALUE)
     {
@@ -1827,7 +1827,7 @@ set_cond_stmt_execution_predicate (struct ipa_node_params 
*info,
    predicates to the CFG edges.   */
 
 static void
-set_switch_stmt_execution_predicate (struct ipa_node_params *info,
+set_switch_stmt_execution_predicate (struct func_body_info *fbi,
                                     struct inline_summary *summary,
                                     basic_block bb)
 {
@@ -1845,7 +1845,7 @@ set_switch_stmt_execution_predicate (struct 
ipa_node_params *info,
     return;
   gswitch *last = as_a <gswitch *> (lastg);
   op = gimple_switch_index (last);
-  if (!unmodified_parm_or_parm_agg_item (info, last, op, &index, &aggpos))
+  if (!unmodified_parm_or_parm_agg_item (fbi, last, op, &index, &aggpos))
     return;
 
   FOR_EACH_EDGE (e, ei, bb->succs)
@@ -1888,8 +1888,8 @@ set_switch_stmt_execution_predicate (struct 
ipa_node_params *info,
    which it is executable.  */
 
 static void
-compute_bb_predicates (struct cgraph_node *node,
-                      struct ipa_node_params *parms_info,
+compute_bb_predicates (struct func_body_info *fbi,
+                      struct cgraph_node *node,
                       struct inline_summary *summary)
 {
   struct function *my_function = DECL_STRUCT_FUNCTION (node->decl);
@@ -1898,8 +1898,8 @@ compute_bb_predicates (struct cgraph_node *node,
 
   FOR_EACH_BB_FN (bb, my_function)
     {
-      set_cond_stmt_execution_predicate (parms_info, summary, bb);
-      set_switch_stmt_execution_predicate (parms_info, summary, bb);
+      set_cond_stmt_execution_predicate (fbi, summary, bb);
+      set_switch_stmt_execution_predicate (fbi, summary, bb);
     }
 
   /* Entry block is always executable.  */
@@ -2031,7 +2031,7 @@ will_be_nonconstant_expr_predicate (struct 
ipa_node_params *info,
    a compile time constant.  */
 
 static struct predicate
-will_be_nonconstant_predicate (struct ipa_node_params *info,
+will_be_nonconstant_predicate (struct func_body_info *fbi,
                               struct inline_summary *summary,
                               gimple stmt,
                               vec<predicate_t> nonconstant_names)
@@ -2065,7 +2065,7 @@ will_be_nonconstant_predicate (struct ipa_node_params 
*info,
       tree op;
       gcc_assert (gimple_assign_single_p (stmt));
       op = gimple_assign_rhs1 (stmt);
-      if (!unmodified_parm_or_parm_agg_item (info, stmt, op, &base_index,
+      if (!unmodified_parm_or_parm_agg_item (fbi, stmt, op, &base_index,
                                             &aggpos))
        return p;
     }
@@ -2078,7 +2078,7 @@ will_be_nonconstant_predicate (struct ipa_node_params 
*info,
     {
       tree parm = unmodified_parm (stmt, use);
       /* For arguments we can build a condition.  */
-      if (parm && ipa_get_param_decl_index (info, parm) >= 0)
+      if (parm && ipa_get_param_decl_index (fbi->info, parm) >= 0)
        continue;
       if (TREE_CODE (use) != SSA_NAME)
        return p;
@@ -2099,7 +2099,7 @@ will_be_nonconstant_predicate (struct ipa_node_params 
*info,
       tree parm = unmodified_parm (stmt, use);
       int index;
 
-      if (parm && (index = ipa_get_param_decl_index (info, parm)) >= 0)
+      if (parm && (index = ipa_get_param_decl_index (fbi->info, parm)) >= 0)
        {
          if (index != base_index)
            p = add_condition (summary, index, NULL, CHANGED, NULL_TREE);
@@ -2481,13 +2481,17 @@ estimate_function_body_sizes (struct cgraph_node *node, 
bool early)
   int freq;
   struct inline_summary *info = inline_summaries->get (node);
   struct predicate bb_predicate;
-  struct ipa_node_params *parms_info = NULL;
+  struct func_body_info fbi;
   vec<predicate_t> nonconstant_names = vNULL;
   int nblocks, n;
   int *order;
   predicate array_index = true_predicate ();
   gimple fix_builtin_expect_stmt;
 
+  gcc_assert (my_function && my_function->cfg);
+  gcc_assert (cfun == my_function);
+
+  memset(&fbi, 0, sizeof(fbi));
   info->conds = NULL;
   info->entry = NULL;
 
@@ -2510,7 +2514,11 @@ estimate_function_body_sizes (struct cgraph_node *node, 
bool early)
 
       if (ipa_node_params_sum)
        {
-         parms_info = IPA_NODE_REF (node);
+         fbi.node = node;
+         fbi.info = IPA_NODE_REF (node);
+         fbi.bb_infos = vNULL;
+         fbi.bb_infos.safe_grow_cleared (last_basic_block_for_fn (cfun));
+         fbi.param_count = count_formal_params(node->decl);
          nonconstant_names.safe_grow_cleared
            (SSANAMES (my_function)->length ());
        }
@@ -2528,10 +2536,8 @@ estimate_function_body_sizes (struct cgraph_node *node, 
bool early)
   bb_predicate = not_inlined_predicate ();
   account_size_time (info, 2 * INLINE_SIZE_SCALE, 0, &bb_predicate);
 
-  gcc_assert (my_function && my_function->cfg);
-  if (parms_info)
-    compute_bb_predicates (node, parms_info, info);
-  gcc_assert (cfun == my_function);
+  if (fbi.info)
+    compute_bb_predicates (&fbi, node, info);
   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++)
@@ -2548,7 +2554,7 @@ estimate_function_body_sizes (struct cgraph_node *node, 
bool early)
        }
 
       /* TODO: Obviously predicates can be propagated down across CFG.  */
-      if (parms_info)
+      if (fbi.info)
        {
          if (bb->aux)
            bb_predicate = *(struct predicate *) bb->aux;
@@ -2564,7 +2570,7 @@ estimate_function_body_sizes (struct cgraph_node *node, 
bool early)
          dump_predicate (dump_file, info->conds, &bb_predicate);
        }
 
-      if (parms_info && nonconstant_names.exists ())
+      if (fbi.info && nonconstant_names.exists ())
        {
          struct predicate phi_predicate;
          bool first_phi = true;
@@ -2573,7 +2579,7 @@ estimate_function_body_sizes (struct cgraph_node *node, 
bool early)
               gsi_next (&bsi))
            {
              if (first_phi
-                 && !phi_result_unknown_predicate (parms_info, info, bb,
+                 && !phi_result_unknown_predicate (fbi.info, info, bb,
                                                    &phi_predicate,
                                                    nonconstant_names))
                break;
@@ -2682,9 +2688,9 @@ estimate_function_body_sizes (struct cgraph_node *node, 
bool early)
          /* TODO: When conditional jump or swithc is known to be constant, but
             we did not translate it into the predicates, we really can account
             just maximum of the possible paths.  */
-         if (parms_info)
+         if (fbi.info)
            will_be_nonconstant
-             = will_be_nonconstant_predicate (parms_info, info,
+             = will_be_nonconstant_predicate (&fbi, info,
                                               stmt, nonconstant_names);
          if (this_time || this_size)
            {
@@ -2699,7 +2705,7 @@ estimate_function_body_sizes (struct cgraph_node *node, 
bool early)
              if (prob == 2 && dump_file && (dump_flags & TDF_DETAILS))
                fprintf (dump_file, "\t\tWill be eliminated by inlining\n");
 
-             if (parms_info)
+             if (fbi.info)
                p = and_predicates (info->conds, &bb_predicate,
                                    &will_be_nonconstant);
              else
@@ -2767,7 +2773,7 @@ estimate_function_body_sizes (struct cgraph_node *node, 
bool early)
                && !is_gimple_min_invariant (niter_desc.niter))
            {
              predicate will_be_nonconstant
-               = will_be_nonconstant_expr_predicate (parms_info, info,
+               = will_be_nonconstant_expr_predicate (fbi.info, info,
                                                      niter_desc.niter,
                                                      nonconstant_names);
              if (!true_predicate_p (&will_be_nonconstant))
@@ -2805,7 +2811,7 @@ estimate_function_body_sizes (struct cgraph_node *node, 
bool early)
                        || is_gimple_min_invariant (iv.step))
                      continue;
                    will_be_nonconstant
-                     = will_be_nonconstant_expr_predicate (parms_info, info,
+                     = will_be_nonconstant_expr_predicate (fbi.info, info,
                                                            iv.step,
                                                            nonconstant_names);
                    if (!true_predicate_p (&will_be_nonconstant))
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 6074194..2ba45e2 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -70,57 +70,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "domwalk.h"
 #include "builtins.h"
 
-/* Intermediate information that we get from alias analysis about a particular
-   parameter in a particular basic_block.  When a parameter or the memory it
-   references is marked modified, we use that information in all dominatd
-   blocks without cosulting alias analysis oracle.  */
-
-struct param_aa_status
-{
-  /* Set when this structure contains meaningful information.  If not, the
-     structure describing a dominating BB should be used instead.  */
-  bool valid;
-
-  /* Whether we have seen something which might have modified the data in
-     question.  PARM is for the parameter itself, REF is for data it points to
-     but using the alias type of individual accesses and PT is the same thing
-     but for computing aggregate pass-through functions using a very inclusive
-     ao_ref.  */
-  bool parm_modified, ref_modified, pt_modified;
-};
-
-/* Information related to a given BB that used only when looking at function
-   body.  */
-
-struct ipa_bb_info
-{
-  /* Call graph edges going out of this BB.  */
-  vec<cgraph_edge *> cg_edges;
-  /* Alias analysis statuses of each formal parameter at this bb.  */
-  vec<param_aa_status> param_aa_statuses;
-};
-
-/* Structure with global information that is only used when looking at function
-   body. */
-
-struct func_body_info
-{
-  /* The node that is being analyzed.  */
-  cgraph_node *node;
-
-  /* Its info.  */
-  struct ipa_node_params *info;
-
-  /* Information about individual BBs. */
-  vec<ipa_bb_info> bb_infos;
-
-  /* Number of parameters.  */
-  int param_count;
-
-  /* Number of statements already walked by when analyzing this function.  */
-  unsigned int aa_walked;
-};
-
 /* Function summary where the parameter infos are actually stored. */
 ipa_node_params_t *ipa_node_params_sum = NULL;
 /* Vector of IPA-CP transformation data for each clone.  */
@@ -1010,12 +959,12 @@ parm_ref_data_pass_through_p (struct func_body_info 
*fbi, int index,
    within the aggregate and whether it is a load from a value passed by
    reference respectively.  */
 
-static bool
-ipa_load_from_parm_agg_1 (struct func_body_info *fbi,
-                         vec<ipa_param_descriptor> descriptors,
-                         gimple stmt, tree op, int *index_p,
-                         HOST_WIDE_INT *offset_p, HOST_WIDE_INT *size_p,
-                         bool *by_ref_p)
+bool
+ipa_load_from_parm_agg (struct func_body_info *fbi,
+                       vec<ipa_param_descriptor> descriptors,
+                       gimple stmt, tree op, int *index_p,
+                       HOST_WIDE_INT *offset_p, HOST_WIDE_INT *size_p,
+                       bool *by_ref_p)
 {
   int index;
   HOST_WIDE_INT size, max_size;
@@ -1082,18 +1031,6 @@ ipa_load_from_parm_agg_1 (struct func_body_info *fbi,
   return false;
 }
 
-/* Just like the previous function, just without the param_analysis_info
-   pointer, for users outside of this file.  */
-
-bool
-ipa_load_from_parm_agg (struct ipa_node_params *info, gimple stmt,
-                       tree op, int *index_p, HOST_WIDE_INT *offset_p,
-                       bool *by_ref_p)
-{
-  return ipa_load_from_parm_agg_1 (NULL, info->descriptors, stmt, op, index_p,
-                                  offset_p, NULL, by_ref_p);
-}
-
 /* Given that an actual argument is an SSA_NAME (given in NAME) and is a result
    of an assignment statement STMT, try to determine whether we are actually
    handling any of the following cases and construct an appropriate jump
@@ -1977,9 +1914,9 @@ ipa_analyze_indirect_call_uses (struct func_body_info 
*fbi, gcall *call,
   int index;
   gimple def = SSA_NAME_DEF_STMT (target);
   if (gimple_assign_single_p (def)
-      && ipa_load_from_parm_agg_1 (fbi, info->descriptors, def,
-                                  gimple_assign_rhs1 (def), &index, &offset,
-                                  NULL, &by_ref))
+      && ipa_load_from_parm_agg (fbi, info->descriptors, def,
+                                gimple_assign_rhs1 (def), &index, &offset,
+                                NULL, &by_ref))
     {
       struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index, call);
       cs->indirect_info->offset = offset;
@@ -5192,8 +5129,8 @@ ipcp_modif_dom_walker::before_dom_children (basic_block 
bb)
       if (vce)
        continue;
 
-      if (!ipa_load_from_parm_agg_1 (m_fbi, m_descriptors, stmt, rhs, &index,
-                                    &offset, &size, &by_ref))
+      if (!ipa_load_from_parm_agg (m_fbi, m_descriptors, stmt, rhs, &index,
+                                  &offset, &size, &by_ref))
        continue;
       for (v = m_aggval; v; v = v->next)
        if (v->index == index
diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h
index e6725aa..af41ef1 100644
--- a/gcc/ipa-prop.h
+++ b/gcc/ipa-prop.h
@@ -336,6 +336,57 @@ struct ipa_node_params
   unsigned node_calling_single_call : 1;
 };
 
+/* Intermediate information that we get from alias analysis about a particular
+   parameter in a particular basic_block.  When a parameter or the memory it
+   references is marked modified, we use that information in all dominatd
+   blocks without cosulting alias analysis oracle.  */
+
+struct param_aa_status
+{
+  /* Set when this structure contains meaningful information.  If not, the
+     structure describing a dominating BB should be used instead.  */
+  bool valid;
+
+  /* Whether we have seen something which might have modified the data in
+     question.  PARM is for the parameter itself, REF is for data it points to
+     but using the alias type of individual accesses and PT is the same thing
+     but for computing aggregate pass-through functions using a very inclusive
+     ao_ref.  */
+  bool parm_modified, ref_modified, pt_modified;
+};
+
+/* Information related to a given BB that used only when looking at function
+   body.  */
+
+struct ipa_bb_info
+{
+  /* Call graph edges going out of this BB.  */
+  vec<cgraph_edge *> cg_edges;
+  /* Alias analysis statuses of each formal parameter at this bb.  */
+  vec<param_aa_status> param_aa_statuses;
+};
+
+/* Structure with global information that is only used when looking at function
+   body. */
+
+struct func_body_info
+{
+  /* The node that is being analyzed.  */
+  cgraph_node *node;
+
+  /* Its info.  */
+  struct ipa_node_params *info;
+
+  /* Information about individual BBs. */
+  vec<ipa_bb_info> bb_infos;
+
+  /* Number of parameters.  */
+  int param_count;
+
+  /* Number of statements already walked by when analyzing this function.  */
+  unsigned int aa_walked;
+};
+
 /* ipa_node_params access functions.  Please use these to access fields that
    are or will be shared among various passes.  */
 
@@ -585,8 +636,9 @@ void ipa_analyze_node (struct cgraph_node *);
 /* Aggregate jump function related functions.  */
 tree ipa_find_agg_cst_for_param (struct ipa_agg_jump_function *, HOST_WIDE_INT,
                                 bool);
-bool ipa_load_from_parm_agg (struct ipa_node_params *, gimple, tree, int *,
-                            HOST_WIDE_INT *, bool *);
+bool ipa_load_from_parm_agg (struct func_body_info *,
+                            vec<ipa_param_descriptor>, gimple, tree, int *,
+                            HOST_WIDE_INT *, HOST_WIDE_INT *, bool *);
 
 /* Debugging interface.  */
 void ipa_print_node_params (FILE *, struct cgraph_node *node);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]