diff mbox

[3/3] Compute predicates for phi node results in ipa-inline-analysis.c

Message ID 20120830151135.GD3395@virgil.arch.suse.de
State New
Headers show

Commit Message

Martin Jambor Aug. 30, 2012, 3:11 p.m. UTC
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  <mjambor@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.

Comments

Jan Hubicka Aug. 31, 2012, 8:52 a.m. UTC | #1
> 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?

OK,
thanks!  Do you think you can add testcase?
I plan to reorg the analysis to work in dominator order (now we compute
dominators anyway for lop analysis) that will make this also bit more strong
across non-trivial CFGs. (originally I did not care much since inliner cares
only about simple functions with simple CFG, but with inline hints and other 
stuff we need to be more careful to not throw away useful info.

Honza
diff mbox

Patch

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);