Hi,

this is a new version of the patch which makes ipa analysis produce
predicates for PHI node results, at least at the bottom of the
simplest diamond and semi-diamond CFG subgraphs.  This time I also
analyze the conditions again rather than extracting information from
CFG edges, which means I can reason about substantially more PHI
nodes.

This patch makes us produce loop bounds hint for the pr48636.f90
testcase.

Bootstrapped and tested on x86_64-linux.  OK for trunk?

Thanks,

Martin


2012-08-29  Martin Jambor  <mjam...@suse.cz>

        * ipa-inline-analysis.c (phi_result_unknown_predicate): New function.
        (predicate_for_phi_result): Likewise.
        (estimate_function_body_sizes): Use the above two functions.


Index: src/gcc/ipa-inline-analysis.c
===================================================================
--- src.orig/gcc/ipa-inline-analysis.c
+++ src/gcc/ipa-inline-analysis.c
@@ -2070,6 +2070,99 @@ param_change_prob (gimple stmt, int i)
   return REG_BR_PROB_BASE;
 }
 
+/* Find whether a basic block BB is the final block of a (half) diamond CFG
+   sub-graph and if the predicate the condition depends on is known.  If so,
+   return true and store the pointer the predicate in *P.  */
+
+static bool
+phi_result_unknown_predicate (struct ipa_node_params *info,
+                             struct inline_summary *summary, basic_block bb,
+                             struct predicate *p,
+                             VEC (predicate_t, heap) *nonconstant_names)
+{
+  edge e;
+  edge_iterator ei;
+  basic_block first_bb = NULL;
+  gimple stmt;
+
+  if (single_pred_p (bb))
+    {
+      *p = false_predicate ();
+      return true;
+    }
+
+  FOR_EACH_EDGE (e, ei, bb->preds)
+    {
+      if (single_succ_p (e->src))
+       {
+         if (!single_pred_p (e->src))
+           return false;
+         if (!first_bb)
+           first_bb = single_pred (e->src);
+         else if (single_pred (e->src) != first_bb)
+           return false;
+       }
+      else
+       {
+         if (!first_bb)
+           first_bb = e->src;
+         else if (e->src != first_bb)
+           return false;
+       }
+    }
+
+  if (!first_bb)
+    return false;
+
+  stmt = last_stmt (first_bb);
+  if (!stmt
+      || gimple_code (stmt) != GIMPLE_COND
+      || !is_gimple_ip_invariant (gimple_cond_rhs (stmt)))
+    return false;
+
+  *p = will_be_nonconstant_expr_predicate (info, summary,
+                                          gimple_cond_lhs (stmt),
+                                          nonconstant_names);
+  if (true_predicate_p (p))
+    return false;
+  else
+    return true;
+}
+
+/* Given a PHI statement in a function described by inline properties SUMMARY
+   and *P being the predicate describing whether the selected PHI argument is
+   known, store a predicate for the result of the PHI statement into
+   NONCONSTANT_NAMES, if possible.  */
+
+static void
+predicate_for_phi_result (struct inline_summary *summary, gimple phi,
+                         struct predicate *p,
+                         VEC (predicate_t, heap) *nonconstant_names)
+{
+  unsigned i;
+
+  for (i = 0; i < gimple_phi_num_args (phi); i++)
+    {
+      tree arg = gimple_phi_arg (phi, i)->def;
+      if (!is_gimple_min_invariant (arg))
+       {
+         gcc_assert (TREE_CODE (arg) == SSA_NAME);
+         *p = or_predicates (summary->conds, p,
+                             &VEC_index (predicate_t, nonconstant_names,
+                                         SSA_NAME_VERSION (arg)));
+         if (true_predicate_p (p))
+           return;
+       }
+    }
+
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      fprintf (dump_file, "\t\tphi predicate: ");
+      dump_predicate (dump_file, summary->conds, p);
+    }
+  VEC_replace (predicate_t, nonconstant_names,
+              SSA_NAME_VERSION (gimple_phi_result (phi)), *p);
+}
 
 /* Compute function body size parameters for NODE.
    When EARLY is true, we compute only simple summaries without
@@ -2143,7 +2236,30 @@ estimate_function_body_sizes (struct cgr
          fprintf (dump_file, "\n BB %i predicate:", bb->index);
          dump_predicate (dump_file, info->conds, &bb_predicate);
        }
-      
+
+      if (parms_info && nonconstant_names)
+       {
+         struct predicate phi_predicate;
+         bool first_phi = true;
+
+         for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi); gsi_next (&bsi))
+           {
+             if (first_phi
+                 && !phi_result_unknown_predicate (parms_info, info, bb,
+                                                   &phi_predicate,
+                                                   nonconstant_names))
+               break;
+             first_phi = false;
+             if (dump_file && (dump_flags & TDF_DETAILS))
+               {
+                 fprintf (dump_file, "  ");
+                 print_gimple_stmt (dump_file, gsi_stmt (bsi), 0, 0);
+               }
+             predicate_for_phi_result (info, gsi_stmt (bsi), &phi_predicate,
+                                       nonconstant_names);
+           }
+       }
+
       for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
        {
          gimple stmt = gsi_stmt (bsi);

Reply via email to