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]

Re: Merging Graphite to trunk


On Mon, Aug 3, 2009 at 03:32, Richard Guenther<rguenther@suse.de> wrote:
> You should be able to get edge frequencies from the edges coming into
> the SCoPs and then after going out-of-graphite do what the profile
> estimation does based on that values. ÂOr even more simple - re-run
> the profile estimates on the whole function body.
>

I implemented the second solution: recompute the profile information
after graphite code generation.

	* Makefile.in (graphite.o): Depends on PREDICT_H.
	* graphite.c: Include predict.h.
	(graphite_finalize): Call tree_estimate_probability.
	* predict.c (predict_loops): Do not call scev_initialize and
	scev_finalize.
	(tree_estimate_probability_bb): New.
	(tree_estimate_probability): Do not initialize loops: move that
	code to the driver.  Call tree_estimate_probability_bb.
	(tree_estimate_probability_driver): New.
	(pass_profile): Use tree_estimate_probability_driver.
	* predict.h (tree_estimate_probability): Declared.

I am regstrapping this patch on amd64-linux.  Okay for trunk if it passes?

Thanks,
Sebastian
	* Makefile.in (graphite.o): Depends on PREDICT_H.
	* graphite.c: Include predict.h.
	(graphite_finalize): Call tree_estimate_probability.
	* predict.c (predict_loops): Do not call scev_initialize and
	scev_finalize.
	(tree_estimate_probability_bb): New.
	(tree_estimate_probability): Do not initialize loops: move that
	code to the driver.  Call tree_estimate_probability_bb.
	(tree_estimate_probability_driver): New.
	(pass_profile): Use tree_estimate_probability_driver.
	* predict.h (tree_estimate_probability): Declared.

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index b43e6ee..a9c87ed 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -2466,7 +2466,7 @@ sese.o: sese.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
 graphite.o: graphite.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(GGC_H) $(TREE_H) $(RTL_H) $(BASIC_BLOCK_H) $(DIAGNOSTIC_H) $(TOPLEV_H) \
    $(TREE_FLOW_H) $(TREE_DUMP_H) $(TIMEVAR_H) $(CFGLOOP_H) $(GIMPLE_H) \
-   $(TREE_DATA_REF_H) tree-pass.h graphite.h \
+   $(PREDICT_H) $(TREE_DATA_REF_H) tree-pass.h graphite.h \
    pointer-set.h value-prof.h graphite-ppl.h sese.h \
    graphite-scop-detection.h graphite-clast-to-gimple.h \
    graphite-poly.h graphite-sese-to-poly.h
diff --git a/gcc/graphite.c b/gcc/graphite.c
index 0c0b607..d40cc93 100644
--- a/gcc/graphite.c
+++ b/gcc/graphite.c
@@ -54,6 +54,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "pointer-set.h"
 #include "gimple.h"
 #include "sese.h"
+#include "predict.h"
 
 #ifdef HAVE_cloog
 
@@ -229,7 +230,11 @@ static void
 graphite_finalize (bool need_cfg_cleanup_p)
 {
   if (need_cfg_cleanup_p)
-    cleanup_tree_cfg ();
+    {
+      cleanup_tree_cfg ();
+      profile_status = PROFILE_ABSENT;
+      tree_estimate_probability ();
+    }
 
   cloog_finalize ();
   free_original_copy_tables ();
diff --git a/gcc/predict.c b/gcc/predict.c
index e3b4b83..6353fb9 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -916,8 +916,6 @@ predict_loops (void)
   loop_iterator li;
   struct loop *loop;
 
-  scev_initialize ();
-
   /* Try to predict out blocks in a loop that are not part of a
      natural loop.  */
   FOR_EACH_LOOP (li, loop, 0)
@@ -1040,8 +1038,6 @@ predict_loops (void)
       /* Free basic blocks from get_loop_body.  */
       free (bbs);
     }
-
-  scev_finalize ();
 }
 
 /* Attempt to predict probabilities of BB outgoing edges using local
@@ -1608,16 +1604,96 @@ assert_is_empty (const void *key ATTRIBUTE_UNUSED, void **value,
 }
 #endif
 
-/* Predict branch probabilities and estimate profile of the tree CFG.  */
-static unsigned int
+/* Predict branch probabilities and estimate profile for basic block BB.  */
+
+static void
+tree_estimate_probability_bb (basic_block bb)
+{
+  edge e;
+  edge_iterator ei;
+  gimple last;
+
+  FOR_EACH_EDGE (e, ei, bb->succs)
+    {
+      /* Predict early returns to be probable, as we've already taken
+	 care for error returns and other cases are often used for
+	 fast paths through function.
+
+	 Since we've already removed the return statements, we are
+	 looking for CFG like:
+
+	 if (conditional)
+	 {
+	 ..
+	 goto return_block
+	 }
+	 some other blocks
+	 return_block:
+	 return_stmt.  */
+      if (e->dest != bb->next_bb
+	  && e->dest != EXIT_BLOCK_PTR
+	  && single_succ_p (e->dest)
+	  && single_succ_edge (e->dest)->dest == EXIT_BLOCK_PTR
+	  && (last = last_stmt (e->dest)) != NULL
+	  && gimple_code (last) == GIMPLE_RETURN)
+	{
+	  edge e1;
+	  edge_iterator ei1;
+
+	  if (single_succ_p (bb))
+	    {
+	      FOR_EACH_EDGE (e1, ei1, bb->preds)
+		if (!predicted_by_p (e1->src, PRED_NULL_RETURN)
+		    && !predicted_by_p (e1->src, PRED_CONST_RETURN)
+		    && !predicted_by_p (e1->src, PRED_NEGATIVE_RETURN))
+		  predict_edge_def (e1, PRED_TREE_EARLY_RETURN, NOT_TAKEN);
+	    }
+	  else
+	    if (!predicted_by_p (e->src, PRED_NULL_RETURN)
+		&& !predicted_by_p (e->src, PRED_CONST_RETURN)
+		&& !predicted_by_p (e->src, PRED_NEGATIVE_RETURN))
+	      predict_edge_def (e, PRED_TREE_EARLY_RETURN, NOT_TAKEN);
+	}
+
+      /* Look for block we are guarding (ie we dominate it,
+	 but it doesn't postdominate us).  */
+      if (e->dest != EXIT_BLOCK_PTR && e->dest != bb
+	  && dominated_by_p (CDI_DOMINATORS, e->dest, e->src)
+	  && !dominated_by_p (CDI_POST_DOMINATORS, e->src, e->dest))
+	{
+	  gimple_stmt_iterator bi;
+
+	  /* The call heuristic claims that a guarded function call
+	     is improbable.  This is because such calls are often used
+	     to signal exceptional situations such as printing error
+	     messages.  */
+	  for (bi = gsi_start_bb (e->dest); !gsi_end_p (bi);
+	       gsi_next (&bi))
+	    {
+	      gimple stmt = gsi_stmt (bi);
+	      if (is_gimple_call (stmt)
+		  /* Constant and pure calls are hardly used to signalize
+		     something exceptional.  */
+		  && gimple_has_side_effects (stmt))
+		{
+		  predict_edge_def (e, PRED_CALL, NOT_TAKEN);
+		  break;
+		}
+	    }
+	}
+    }
+  tree_predict_by_opcode (bb);
+}
+
+/* Predict branch probabilities and estimate profile of the tree CFG.
+   This function can be called from the loop optimizers to recompute
+   the profile information.  */
+
+void
 tree_estimate_probability (void)
 {
   basic_block bb;
 
-  loop_optimizer_init (0);
-  if (dump_file && (dump_flags & TDF_DETAILS))
-    flow_loops_dump (dump_file, NULL, 0);
-
   add_noreturn_fake_exit_edges ();
   connect_infinite_loops_to_exit ();
   /* We use loop_niter_by_eval, which requires that the loops have
@@ -1627,89 +1703,14 @@ tree_estimate_probability (void)
 
   bb_predictions = pointer_map_create ();
   tree_bb_level_predictions ();
-
-  mark_irreducible_loops ();
   record_loop_exits ();
+
   if (number_of_loops () > 1)
     predict_loops ();
 
   FOR_EACH_BB (bb)
-    {
-      edge e;
-      edge_iterator ei;
-      gimple last;
-
-      FOR_EACH_EDGE (e, ei, bb->succs)
-	{
-	  /* Predict early returns to be probable, as we've already taken
-	     care for error returns and other cases are often used for
-	     fast paths through function. 
-
-	     Since we've already removed the return statements, we are
-	     looking for CFG like:
-
-	       if (conditional)
-	         {
-		   ..
-		   goto return_block
-	         }
-	       some other blocks
-	     return_block:
-	       return_stmt.  */
-	  if (e->dest != bb->next_bb
-	      && e->dest != EXIT_BLOCK_PTR
-	      && single_succ_p (e->dest)
-	      && single_succ_edge (e->dest)->dest == EXIT_BLOCK_PTR
-	      && (last = last_stmt (e->dest)) != NULL
-	      && gimple_code (last) == GIMPLE_RETURN)
-	    {
-	      edge e1;
-	      edge_iterator ei1;
-
-	      if (single_succ_p (bb))
-		{
-		  FOR_EACH_EDGE (e1, ei1, bb->preds)
-		    if (!predicted_by_p (e1->src, PRED_NULL_RETURN)
-			&& !predicted_by_p (e1->src, PRED_CONST_RETURN)
-			&& !predicted_by_p (e1->src, PRED_NEGATIVE_RETURN))
-		      predict_edge_def (e1, PRED_TREE_EARLY_RETURN, NOT_TAKEN);
-		}
-	       else
-		if (!predicted_by_p (e->src, PRED_NULL_RETURN)
-		    && !predicted_by_p (e->src, PRED_CONST_RETURN)
-		    && !predicted_by_p (e->src, PRED_NEGATIVE_RETURN))
-		  predict_edge_def (e, PRED_TREE_EARLY_RETURN, NOT_TAKEN);
-	    }
+    tree_estimate_probability_bb (bb);
 
-	  /* Look for block we are guarding (ie we dominate it,
-	     but it doesn't postdominate us).  */
-	  if (e->dest != EXIT_BLOCK_PTR && e->dest != bb
-	      && dominated_by_p (CDI_DOMINATORS, e->dest, e->src)
-	      && !dominated_by_p (CDI_POST_DOMINATORS, e->src, e->dest))
-	    {
-	      gimple_stmt_iterator bi;
-
-	      /* The call heuristic claims that a guarded function call
-		 is improbable.  This is because such calls are often used
-		 to signal exceptional situations such as printing error
-		 messages.  */
-	      for (bi = gsi_start_bb (e->dest); !gsi_end_p (bi);
-		   gsi_next (&bi))
-		{
-		  gimple stmt = gsi_stmt (bi);
-		  if (is_gimple_call (stmt)
-		      /* Constant and pure calls are hardly used to signalize
-			 something exceptional.  */
-		      && gimple_has_side_effects (stmt))
-		    {
-		      predict_edge_def (e, PRED_CALL, NOT_TAKEN);
-		      break;
-		    }
-		}
-	    }
-	}
-      tree_predict_by_opcode (bb);
-    }
   FOR_EACH_BB (bb)
     combine_predictions_for_bb (bb);
 
@@ -1722,6 +1723,31 @@ tree_estimate_probability (void)
   estimate_bb_frequencies ();
   free_dominance_info (CDI_POST_DOMINATORS);
   remove_fake_exit_edges ();
+}
+
+/* Predict branch probabilities and estimate profile of the tree CFG.
+   This is the driver function for PASS_PROFILE.  */
+
+static unsigned int
+tree_estimate_probability_driver (void)
+{
+  unsigned nb_loops;
+
+  loop_optimizer_init (0);
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    flow_loops_dump (dump_file, NULL, 0);
+
+  mark_irreducible_loops ();
+
+  nb_loops = number_of_loops ();
+  if (nb_loops > 1)
+    scev_initialize ();
+
+  tree_estimate_probability ();
+
+  if (nb_loops > 1)
+    scev_finalize ();
+
   loop_optimizer_finalize ();
   if (dump_file && (dump_flags & TDF_DETAILS))
     gimple_dump_cfg (dump_file, dump_flags);
@@ -2203,7 +2229,7 @@ struct gimple_opt_pass pass_profile =
   GIMPLE_PASS,
   "profile",				/* name */
   gate_estimate_probability,		/* gate */
-  tree_estimate_probability,		/* execute */
+  tree_estimate_probability_driver,	/* execute */
   NULL,					/* sub */
   NULL,					/* next */
   0,					/* static_pass_number */
diff --git a/gcc/predict.h b/gcc/predict.h
index e115bb5..0e04041 100644
--- a/gcc/predict.h
+++ b/gcc/predict.h
@@ -40,5 +40,6 @@ extern int counts_to_freqs (void);
 extern void estimate_bb_frequencies (void);
 extern const char *predictor_name (enum br_predictor);
 extern tree build_predict_expr (enum br_predictor, enum prediction);
+extern void tree_estimate_probability (void);
 
 #endif  /* GCC_PREDICT_H */

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