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: [PATCH] Fix branch probability computation in do_compare_rtx_and_jump (PR tree-optimization/83081)


Dne 2018-01-22 19:36, Jakub Jelinek napsal:
On Mon, Jan 22, 2018 at 06:44:17PM +0100, Jan Hubicka wrote:
> +  /* Split *THIS (ORIG) probability into 2 probabilities, such that
> +     the returned one (FIRST) is *THIS * CPROB and *THIS is
> +     adjusted (SECOND) so that FIRST + FIRST.invert () * SECOND
> +     == ORIG.  */

To make documentation clear, i would include the pseudocode with
conditionals and individual
probabilities.
It is bit non-obvious transformation and it would be nice to reduce level of
apparent
magicness in profiling code :)

So like this?

2018-01-22  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/83081
	* profile-count.h (profile_probability::split): New method.
	* dojump.c (do_jump_1) <case TRUTH_ANDIF_EXPR, case TRUTH_ORIF_EXPR>:
	Use profile_probability::split.
	(do_compare_rtx_and_jump): Fix adjustment of probabilities
	when splitting a single conditional jump into 2.

	* gcc.dg/predict-8.c: Adjust expected probability.

Looks great. Thanks a lot!
Honza

--- gcc/profile-count.h.jj	2018-01-19 19:41:52.910549618 +0100
+++ gcc/profile-count.h	2018-01-22 16:20:27.073096515 +0100
@@ -410,6 +410,30 @@ public:
       return *this;
     }

+  /* Split *THIS (ORIG) probability into 2 probabilities, such that
+     the returned one (FIRST) is *THIS * CPROB and *THIS is
+     adjusted (SECOND) so that FIRST + FIRST.invert () * SECOND
+     == ORIG.  This is useful e.g. when splitting a conditional
+     branch like:
+     if (cond)
+       goto lab; // ORIG probability
+     into
+     if (cond1)
+       goto lab; // FIRST = ORIG * CPROB probability
+     if (cond2)
+       goto lab; // SECOND probability
+     such that the overall probability of jumping to lab remains
+     the same.  CPROB gives the relative probability between the
+     branches.  */
+  profile_probability split (const profile_probability &cprob)
+    {
+      profile_probability ret = *this * cprob;
+      /* The following is equivalent to:
+         *this = cprob.invert () * *this / ret.invert ();  */
+      *this = (*this - ret) / ret.invert ();
+      return ret;
+    }
+
   gcov_type apply (gcov_type val) const
     {
       if (*this == profile_probability::uninitialized ())
--- gcc/dojump.c.jj	2018-01-19 19:41:49.978548984 +0100
+++ gcc/dojump.c	2018-01-22 16:31:43.867185428 +0100
@@ -347,13 +347,11 @@ do_jump_1 (enum tree_code code, tree op0
profile_probability op1_prob = profile_probability::uninitialized ();
         if (prob.initialized_p ())
           {
-            profile_probability false_prob = prob.invert ();
- profile_probability op0_false_prob = false_prob.apply_scale (1, 2); - profile_probability op1_false_prob = false_prob.apply_scale (1, 2)
-				/ op0_false_prob.invert ();
+	    op1_prob = prob.invert ();
+	    op0_prob = op1_prob.split (profile_probability::even ());
             /* Get the probability that each jump below is true.  */
-            op0_prob = op0_false_prob.invert ();
-            op1_prob = op1_false_prob.invert ();
+	    op0_prob = op0_prob.invert ();
+	    op1_prob = op1_prob.invert ();
           }
 	if (if_false_label == NULL)
           {
@@ -380,8 +378,8 @@ do_jump_1 (enum tree_code code, tree op0
profile_probability op1_prob = profile_probability::uninitialized ();
         if (prob.initialized_p ())
           {
-            op0_prob = prob.apply_scale (1, 2);
-            op1_prob = prob.apply_scale (1, 2) / op0_prob.invert ();
+	    op1_prob = prob;
+	    op0_prob = op1_prob.split (profile_probability::even ());
 	  }
 	if (if_true_label == NULL)
 	  {
@@ -1120,16 +1118,27 @@ do_compare_rtx_and_jump (rtx op0, rtx op

 	  else
 	    {
-	      profile_probability first_prob = prob;
+	      profile_probability cprob
+		= profile_probability::guessed_always ();
 	      if (first_code == UNORDERED)
-		first_prob = profile_probability::guessed_always ().apply_scale
-				 (1, 100);
+		cprob = cprob.apply_scale (1, 100);
 	      else if (first_code == ORDERED)
-		first_prob = profile_probability::guessed_always ().apply_scale
-				 (99, 100);
+		cprob = cprob.apply_scale (99, 100);
+	      else
+		cprob = profile_probability::even ();
+	      /* We want to split:
+		 if (x) goto t; // prob;
+		 into
+		 if (a) goto t; // first_prob;
+		 if (b) goto t; // prob;
+		 such that the overall probability of jumping to t
+		 remains the same and first_prob is prob * cprob.  */
 	      if (and_them)
 		{
 		  rtx_code_label *dest_label;
+		  prob = prob.invert ();
+		  profile_probability first_prob = prob.split (cprob).invert ();
+		  prob = prob.invert ();
 		  /* If we only jump if true, just bypass the second jump.  */
 		  if (! if_false_label)
 		    {
@@ -1143,8 +1152,11 @@ do_compare_rtx_and_jump (rtx op0, rtx op
 					   size, dest_label, NULL, first_prob);
 		}
               else
- do_compare_rtx_and_jump (op0, op1, first_code, unsignedp, mode,
-					 size, NULL, if_true_label, first_prob);
+		{
+		  profile_probability first_prob = prob.split (cprob);
+		  do_compare_rtx_and_jump (op0, op1, first_code, unsignedp, mode,
+					   size, NULL, if_true_label, first_prob);
+		}
 	    }
 	}

--- gcc/testsuite/gcc.dg/predict-8.c.jj 2017-10-12 20:51:33.192974887 +0200 +++ gcc/testsuite/gcc.dg/predict-8.c 2018-01-22 16:18:09.528071106 +0100
@@ -8,4 +8,4 @@ int foo(float a, float b) {
     return 2;
 }

-/* { dg-final { scan-rtl-dump-times "99.0. .guessed" 2 "expand"} } */
+/* { dg-final { scan-rtl-dump-times "65.\[34]. .guessed" 2 "expand"} } */


	Jakub


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