This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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.


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]