diff mbox

Dump probability for edges a frequency for BBs

Message ID 1c516d8f-8ff5-4cf8-cbd6-9f503b5c1695@suse.cz
State Accepted
Commit 0d56d3c17b709688ec817372311cde1cc445ae4b
Headers show

Commit Message

Martin Liška Nov. 24, 2016, 12:59 p.m. UTC
On 11/24/2016 09:29 AM, Richard Biener wrote:
> Please guard with ! TDF_GIMPLE, otherwise the output will not be parseable

> with the GIMPLE FE.

> 

> RIchard.


Done and verified that and it provides equal dumps for -fdump*-gimple.
Installed as r242837.

Thanks for review.
Martin

Comments

Martin Sebor Nov. 30, 2016, 10:46 p.m. UTC | #1
On 11/24/2016 05:59 AM, Martin Liška wrote:
> On 11/24/2016 09:29 AM, Richard Biener wrote:

>> Please guard with ! TDF_GIMPLE, otherwise the output will not be parseable

>> with the GIMPLE FE.

>>

>> RIchard.

>

> Done and verified that and it provides equal dumps for -fdump*-gimple.

> Installed as r242837.


Hi Martin,

I'm trying to understand how to interpret the probabilities (to
make sure one of my tests, builtin-sprintf-2.c, is testing what
it's supposed to be testing).

With this example:

   char d2[2];

   void f (void)
   {
     if (2 != __builtin_sprintf (d2, "%i", 12))
       __builtin_abort ();
   }

the probability of the branch to abort is 0%:

   f1 ()
   {
     int _1;

     <bb 2> [100.0%]:
     _1 = __builtin_sprintf (&d, "%i", 12);
     if (_1 != 2)
       goto <bb 3>; [0.0%]
     else
       goto <bb 4>; [100.0%]

     <bb 3> [0.0%]:
     __builtin_abort ();

     <bb 4> [100.0%]:
     return;
   }

Yet the call to abort is in the assembly so I would expect its
probability to be more than zero.  So my question is: it it safe
to be testing for calls to abort in the optimized dump as a way
of verifying that the call has not been eliminated from the program
regardless of their probabilities?

For reference, the directive the test uses since this change was
committed looks like this:

{ dg-final { scan-tree-dump-times "> \\\[\[0-9.\]+%\\\]:\n 
*__builtin_abort" 114 "optimized" }

If I'm reading the heavily escaped regex right it matches any
percentage, even 0.0% (and the test passes).

Thanks
Martin
Martin Sebor Dec. 1, 2016, 4:39 p.m. UTC | #2
On 12/01/2016 02:48 AM, Martin Liška wrote:
> On 11/30/2016 11:46 PM, Martin Sebor wrote:

>> On 11/24/2016 05:59 AM, Martin Liška wrote:

>>> On 11/24/2016 09:29 AM, Richard Biener wrote:

>>>> Please guard with ! TDF_GIMPLE, otherwise the output will not be

>>>> parseable

>>>> with the GIMPLE FE.

>>>>

>>>> RIchard.

>>>

>>> Done and verified that and it provides equal dumps for -fdump*-gimple.

>>> Installed as r242837.

>>

>> Hi Martin,

>>

>> I'm trying to understand how to interpret the probabilities (to

>> make sure one of my tests, builtin-sprintf-2.c, is testing what

>> it's supposed to be testing).

>>

>> With this example:

>>

>>   char d2[2];

>>

>>   void f (void)

>>   {

>>     if (2 != __builtin_sprintf (d2, "%i", 12))

>>       __builtin_abort ();

>>   }

>>

>> the probability of the branch to abort is 0%:

>>

>>   f1 ()

>>   {

>>     int _1;

>>

>>     <bb 2> [100.0%]:

>>     _1 = __builtin_sprintf (&d, "%i", 12);

>>     if (_1 != 2)

>>       goto <bb 3>; [0.0%]

>>     else

>>       goto <bb 4>; [100.0%]

>>

>>     <bb 3> [0.0%]:

>>     __builtin_abort ();

>>

>>     <bb 4> [100.0%]:

>>     return;

>>   }

>

> Hello Martin.

>

> Looks I did a small error. I use only only one digit after decimal

> point, which is unable to

> display noreturn predictor (defined as PROB_VERY_UNLIKELY):

>

> #define PROB_VERY_UNLIKELY    (REG_BR_PROB_BASE / 2000 - 1) // this is 4

>

> I would suggest to use following patch to display at least 2 digits,

> that would distinguish

> between real zero and PROB_VERY_UNLIKELY:

>

> x.c.046t.profile_estimate:

>

> f ()

> {

>   int _1;

>

>   <bb 2> [100.00%]:

>   _1 = __builtin_sprintf (&d2, "%i", 12);

>   if (_1 != 2)

>     goto <bb 3>; [0.04%]

>   else

>     goto <bb 4>; [99.96%]

>

>   <bb 3> [0.04%]:

>   __builtin_abort ();

>

>   <bb 4> [99.96%]:

>   return;

>

> }

>

>>

>> Yet the call to abort is in the assembly so I would expect its

>> probability to be more than zero.  So my question is: it it safe

>> to be testing for calls to abort in the optimized dump as a way

>> of verifying that the call has not been eliminated from the program

>> regardless of their probabilities?

>

> I think so, otherwise the call would be removed.


Okay, thanks for the clarification.  One other question though.
Why would the probability be near zero?  In the absence of any
hints the expression 2 != sprintf(d, "%i", 12) should have
a very high probability of being true, near 100% in fact.

I ask because the test I referenced tries to verify the absence
of the sprintf return value optimization.  Without it the
likelihood of each of the calls to abort should in the EQL kind
of test cases like the one above should be nearly 100% (but not
quite).  When it's the opposite it suggests that the sprintf
optimization is providing some hint (in the form of a range of
return values) that changes the odds.  I have verified that
the optimization is not performed so something else must be
setting the probability or the value isn't correct.

Martin

>

> I'm going to test the patch (and eventually update scanned patterns).

>

> Martin

>

> Patch candidate:

>

> diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c

> index b5e866d..de57e89 100644

> --- a/gcc/gimple-pretty-print.c

> +++ b/gcc/gimple-pretty-print.c

> @@ -72,12 +72,17 @@ debug_gimple_stmt (gimple *gs)

>    print_gimple_stmt (stderr, gs, 0, TDF_VOPS|TDF_MEMSYMS);

>  }

>

> +/* Print format used for displaying probability of an edge or frequency

> +   of a basic block.  */

> +

> +#define PROBABILITY_FORMAT "[%.2f%%]"

> +

>  /* Dump E probability to BUFFER.  */

>

>  static void

>  dump_edge_probability (pretty_printer *buffer, edge e)

>  {

> -  pp_scalar (buffer, " [%.1f%%]",

> +  pp_scalar (buffer, " " PROBABILITY_FORMAT,

>           e->probability * 100.0 / REG_BR_PROB_BASE);

>  }

>

> @@ -1023,7 +1028,7 @@ dump_gimple_label (pretty_printer *buffer, glabel

> *gs, int spc, int flags)

>        dump_generic_node (buffer, label, spc, flags, false);

>        basic_block bb = gimple_bb (gs);

>        if (bb && !(flags & TDF_GIMPLE))

> -    pp_scalar (buffer, " [%.1f%%]",

> +    pp_scalar (buffer, " " PROBABILITY_FORMAT,

>             bb->frequency * 100.0 / REG_BR_PROB_BASE);

>        pp_colon (buffer);

>      }

> @@ -2590,7 +2595,8 @@ dump_gimple_bb_header (FILE *outf, basic_block bb,

> int indent, int flags)

>        if (flags & TDF_GIMPLE)

>          fprintf (outf, "%*sbb_%d:\n", indent, "", bb->index);

>        else

> -        fprintf (outf, "%*s<bb %d> [%.1f%%]:\n", indent, "", bb->index,

> +        fprintf (outf, "%*s<bb %d> " PROBABILITY_FORMAT ":\n",

> +             indent, "", bb->index,

>               bb->frequency * 100.0 / REG_BR_PROB_BASE);

>      }

>      }

>

>>

>> For reference, the directive the test uses since this change was

>> committed looks like this:

>>

>> { dg-final { scan-tree-dump-times "> \\\[\[0-9.\]+%\\\]:\n

>> *__builtin_abort" 114 "optimized" }

>>

>> If I'm reading the heavily escaped regex right it matches any

>> percentage, even 0.0% (and the test passes).

>>

>> Thanks

>> Martin

>
Martin Sebor Dec. 1, 2016, 4:49 p.m. UTC | #3
> Okay, thanks for the clarification.  One other question though.

> Why would the probability be near zero?  In the absence of any

> hints the expression 2 != sprintf(d, "%i", 12) should have

> a very high probability of being true, near 100% in fact.

>

> I ask because the test I referenced tries to verify the absence

> of the sprintf return value optimization.  Without it the

> likelihood of each of the calls to abort should in the EQL kind

> of test cases like the one above should be nearly 100% (but not

> quite).  When it's the opposite it suggests that the sprintf

> optimization is providing some hint (in the form of a range of

> return values) that changes the odds.  I have verified that

> the optimization is not performed so something else must be

> setting the probability or the value isn't correct.


I think I see what's going on.  It's the call to abort that GCC
uses for the probability (more precisely its attribute noreturn).
When I replace the abort with a function of my own that GCC knows
nothing about the probability goes up to just over 52%.  Still it
seems very low given that 2 is just one of UINT_MAX values the
function can possibly return.

Martin

$ cat a.c && gcc -O2 -S -w -fdump-tree-optimized=/dev/stdout a.c
void foo (void);

void bar (void)
{
   char d [2];
   if (2 != __builtin_sprintf (d, "%i", 12))
     foo ();
}

;; Function bar (bar, funcdef_no=0, decl_uid=1797, cgraph_uid=0, 
symbol_order=0)

Removing basic block 5
bar ()
{
   char d[2];
   int _1;

   <bb 2> [100.0%]:
   _1 = __builtin_sprintf (&d, "%i", 12);
   if (_1 != 2)
     goto <bb 3>; [52.9%]
   else
     goto <bb 4>; [47.1%]

   <bb 3> [52.9%]:
   foo ();

   <bb 4> [100.0%]:
   d ={v} {CLOBBER};
   return;

}
Jeff Law Dec. 1, 2016, 5:38 p.m. UTC | #4
On 12/01/2016 09:49 AM, Martin Sebor wrote:
>> Okay, thanks for the clarification.  One other question though.

>> Why would the probability be near zero?  In the absence of any

>> hints the expression 2 != sprintf(d, "%i", 12) should have

>> a very high probability of being true, near 100% in fact.

>>

>> I ask because the test I referenced tries to verify the absence

>> of the sprintf return value optimization.  Without it the

>> likelihood of each of the calls to abort should in the EQL kind

>> of test cases like the one above should be nearly 100% (but not

>> quite).  When it's the opposite it suggests that the sprintf

>> optimization is providing some hint (in the form of a range of

>> return values) that changes the odds.  I have verified that

>> the optimization is not performed so something else must be

>> setting the probability or the value isn't correct.

>

> I think I see what's going on.  It's the call to abort that GCC

> uses for the probability (more precisely its attribute noreturn).

Right.  An edge which leads to a noreturn call is predicated as 
esentially "never taken".  It's a good strong predictor.


> When I replace the abort with a function of my own that GCC knows

> nothing about the probability goes up to just over 52%.  Still it

> seems very low given that 2 is just one of UINT_MAX values the

> function can possibly return.

Jan would be the one to know the predictors work.  It's reasonably 
complex stuff.
Jeff
Martin Liška Dec. 1, 2016, 9:17 p.m. UTC | #5
On 12/01/2016 05:49 PM, Martin Sebor wrote:
>> Okay, thanks for the clarification.  One other question though.

>> Why would the probability be near zero?  In the absence of any

>> hints the expression 2 != sprintf(d, "%i", 12) should have

>> a very high probability of being true, near 100% in fact.

>>

>> I ask because the test I referenced tries to verify the absence

>> of the sprintf return value optimization.  Without it the

>> likelihood of each of the calls to abort should in the EQL kind

>> of test cases like the one above should be nearly 100% (but not

>> quite).  When it's the opposite it suggests that the sprintf

>> optimization is providing some hint (in the form of a range of

>> return values) that changes the odds.  I have verified that

>> the optimization is not performed so something else must be

>> setting the probability or the value isn't correct.

>

> I think I see what's going on.  It's the call to abort that GCC

> uses for the probability (more precisely its attribute noreturn).

> When I replace the abort with a function of my own that GCC knows

> nothing about the probability goes up to just over 52%.  Still it

> seems very low given that 2 is just one of UINT_MAX values the

> function can possibly return.

>

> Martin


Hi Martin.

Situation is more complicated:
$ gcc predictor.c -fdump-tree-profile_estimate=/dev/stdout -O2 -c

;; Function bar (bar, funcdef_no=0, decl_uid=1797, cgraph_uid=0, symbol_order=0)

;; 1 loops found
;;
;; Loop 0
;;  header 0, latch 1
;;  depth 0, outer -1
;;  nodes: 0 1 2 3 4
;; 2 succs { 3 4 }
;; 3 succs { 4 }
;; 4 succs { 1 }
Predictions for bb 2
   DS theory heuristics: 52.9%
   combined heuristics: 52.9%
   opcode values nonequal (on trees) heuristics of edge 2->3: 66.0%
   early return (on trees) heuristics of edge 2->4: 46.0%
   call heuristics of edge 2->3: 33.0%
Predictions for bb 3
1 edges in bb 3 predicted to even probabilities
Predictions for bb 4
1 edges in bb 4 predicted to even probabilities
bar ()
{
   char d[2];
   int _1;

   <bb 2> [100.0%]:
   _1 = __builtin_sprintf (&d, "%i", 12);
   if (_1 != 2)
     goto <bb 3>; [52.9%]
   else
     goto <bb 4>; [47.1%]

   <bb 3> [52.9%]:
   foo ();

   <bb 4> [100.0%]:
   d ={v} {CLOBBER};
   return;

}

As you can see, multiple predictors do match to edge 2->3:
   opcode values nonequal (on trees) heuristics of edge 2->3: 66.0% // this is the real probability that _x != a_value
   early return (on trees) heuristics of edge 2->4: 46.0% // 2->3 would have 54.0%
   call heuristics of edge 2->3: 33.0% // performing condition that triggers a call is unlikely

These 3 combined together would result in 52.9%. Real values for all of these predictors are received from
SPEC benchmarks (https://gcc.gnu.org/ml/gcc-patches/2016-06/msg00511.html), where we use contrib/analyze_brprob.py
script which is capable of parsing of the tree profile_estimate dumps.

Back to your question about probability that a given value (from UINT_MAX range) is equal to 2. As the predictor
is only driven by opcode and it's quite common that a comparison in a source code is to a 'special' value, that's
why the tuned value of the predictor is equal to 66%.

Martin


>

> $ cat a.c && gcc -O2 -S -w -fdump-tree-optimized=/dev/stdout a.c

> void foo (void);

>

> void bar (void)

> {

>   char d [2];

>   if (2 != __builtin_sprintf (d, "%i", 12))

>     foo ();

> }

>

> ;; Function bar (bar, funcdef_no=0, decl_uid=1797, cgraph_uid=0, symbol_order=0)

>

> Removing basic block 5

> bar ()

> {

>   char d[2];

>   int _1;

>

>   <bb 2> [100.0%]:

>   _1 = __builtin_sprintf (&d, "%i", 12);

>   if (_1 != 2)

>     goto <bb 3>; [52.9%]

>   else

>     goto <bb 4>; [47.1%]

>

>   <bb 3> [52.9%]:

>   foo ();

>

>   <bb 4> [100.0%]:

>   d ={v} {CLOBBER};

>   return;

>

> }

>

>
diff mbox

Patch

From af3fffab592e545892317b2019845f247c36d0d7 Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Wed, 9 Nov 2016 14:11:48 +0100
Subject: [PATCH] Dump probability for edges a frequency for BBs

gcc/ChangeLog:

2016-11-11  Martin Liska  <mliska@suse.cz>

	* gimple-pretty-print.c (dump_edge_probability): New function.
	(dump_gimple_switch): Dump label edge probabilities.
	(dump_gimple_cond): Likewise.
	(dump_gimple_label): Dump
	(dump_gimple_bb_header): Dump basic block frequency.
	(pp_cfg_jump): Replace e->dest argument with e.
	(dump_implicit_edges): Likewise.
	* tree-ssa-loop-ivopts.c (get_scaled_computation_cost_at):
	Use gimple_bb (at) instead of at->bb.

gcc/testsuite/ChangeLog:

2016-11-11  Martin Liska  <mliska@suse.cz>

	* gcc.dg/builtin-unreachable-6.c: Update test to not to scan
	parts for frequencies/probabilities.
	* gcc.dg/pr34027-1.c: Likewise.
	* gcc.dg/strict-overflow-2.c: Likewise.
	* gcc.dg/tree-ssa/20040703-1.c: Likewise.
	* gcc.dg/tree-ssa/builtin-sprintf-2.c: Likewise.
	* gcc.dg/tree-ssa/pr32044.c: Likewise.
	* gcc.dg/tree-ssa/vector-3.c: Likewise.
	* gcc.dg/tree-ssa/vrp101.c: Likewise.
	* gcc.dg/tree-ssa/dump-2.c: New test.
---
 gcc/gimple-pretty-print.c                         | 70 ++++++++++++++++++++---
 gcc/testsuite/gcc.dg/builtin-unreachable-6.c      |  2 +-
 gcc/testsuite/gcc.dg/pr34027-1.c                  |  4 +-
 gcc/testsuite/gcc.dg/strict-overflow-2.c          |  2 +-
 gcc/testsuite/gcc.dg/tree-ssa/20040703-1.c        |  2 +-
 gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-2.c |  4 +-
 gcc/testsuite/gcc.dg/tree-ssa/dump-2.c            |  9 +++
 gcc/testsuite/gcc.dg/tree-ssa/pr32044.c           |  4 +-
 gcc/testsuite/gcc.dg/tree-ssa/vector-3.c          |  2 +-
 gcc/testsuite/gcc.dg/tree-ssa/vrp101.c            |  2 +-
 gcc/tree-ssa-loop-ivopts.c                        |  2 +-
 11 files changed, 82 insertions(+), 21 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/dump-2.c

diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 8286326..b5e866d 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -36,6 +36,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "dumpfile.h"	/* for dump_flags */
 #include "value-prof.h"
 #include "trans-mem.h"
+#include "cfganal.h"
 
 #define INDENT(SPACE)							\
   do { int i; for (i = 0; i < SPACE; i++) pp_space (buffer); } while (0)
@@ -71,6 +72,14 @@  debug_gimple_stmt (gimple *gs)
   print_gimple_stmt (stderr, gs, 0, TDF_VOPS|TDF_MEMSYMS);
 }
 
+/* Dump E probability to BUFFER.  */
+
+static void
+dump_edge_probability (pretty_printer *buffer, edge e)
+{
+  pp_scalar (buffer, " [%.1f%%]",
+	     e->probability * 100.0 / REG_BR_PROB_BASE);
+}
 
 /* Print GIMPLE statement G to FILE using SPC indentation spaces and
    FLAGS as in pp_gimple_stmt_1.  */
@@ -905,7 +914,20 @@  dump_gimple_switch (pretty_printer *buffer, gswitch *gs, int spc,
       gcc_checking_assert (case_label != NULL_TREE);
       dump_generic_node (buffer, case_label, spc, flags, false);
       pp_space (buffer);
-      dump_generic_node (buffer, CASE_LABEL (case_label), spc, flags, false);
+      tree label = CASE_LABEL (case_label);
+      dump_generic_node (buffer, label, spc, flags, false);
+
+      if (cfun && cfun->cfg)
+	{
+	  basic_block dest = label_to_block (label);
+	  if (dest)
+	    {
+	      edge label_edge = find_edge (gimple_bb (gs), dest);
+	      if (label_edge && !(flags & TDF_GIMPLE))
+		dump_edge_probability (buffer, label_edge);
+	    }
+	}
+
       if (i < gimple_switch_num_labels (gs) - 1)
 	{
 	  if (flags & TDF_GIMPLE)
@@ -943,6 +965,23 @@  dump_gimple_cond (pretty_printer *buffer, gcond *gs, int spc, int flags)
       dump_generic_node (buffer, gimple_cond_rhs (gs), spc, flags, false);
       if (!(flags & TDF_RHS_ONLY))
 	{
+	  edge_iterator ei;
+	  edge e, true_edge = NULL, false_edge = NULL;
+	  basic_block bb = gimple_bb (gs);
+
+	  if (bb)
+	    {
+	      FOR_EACH_EDGE (e, ei, bb->succs)
+		{
+		  if (e->flags & EDGE_TRUE_VALUE)
+		    true_edge = e;
+		  else if (e->flags & EDGE_FALSE_VALUE)
+		    false_edge = e;
+		}
+	    }
+
+	  bool has_edge_info = true_edge != NULL && false_edge != NULL;
+
 	  pp_right_paren (buffer);
 
 	  if (gimple_cond_true_label (gs))
@@ -950,6 +989,8 @@  dump_gimple_cond (pretty_printer *buffer, gcond *gs, int spc, int flags)
 	      pp_string (buffer, " goto ");
 	      dump_generic_node (buffer, gimple_cond_true_label (gs),
 				 spc, flags, false);
+	      if (has_edge_info && !(flags & TDF_GIMPLE))
+		dump_edge_probability (buffer, true_edge);
 	      pp_semicolon (buffer);
 	    }
 	  if (gimple_cond_false_label (gs))
@@ -957,6 +998,9 @@  dump_gimple_cond (pretty_printer *buffer, gcond *gs, int spc, int flags)
 	      pp_string (buffer, " else goto ");
 	      dump_generic_node (buffer, gimple_cond_false_label (gs),
 				 spc, flags, false);
+	      if (has_edge_info && !(flags & TDF_GIMPLE))
+		dump_edge_probability (buffer, false_edge);
+
 	      pp_semicolon (buffer);
 	    }
 	}
@@ -977,6 +1021,10 @@  dump_gimple_label (pretty_printer *buffer, glabel *gs, int spc, int flags)
   else
     {
       dump_generic_node (buffer, label, spc, flags, false);
+      basic_block bb = gimple_bb (gs);
+      if (bb && !(flags & TDF_GIMPLE))
+	pp_scalar (buffer, " [%.1f%%]",
+		   bb->frequency * 100.0 / REG_BR_PROB_BASE);
       pp_colon (buffer);
     }
   if (flags & TDF_GIMPLE)
@@ -2542,7 +2590,8 @@  dump_gimple_bb_header (FILE *outf, basic_block bb, int indent, int flags)
 	  if (flags & TDF_GIMPLE)
 	    fprintf (outf, "%*sbb_%d:\n", indent, "", bb->index);
 	  else
-	    fprintf (outf, "%*s<bb %d>:\n", indent, "", bb->index);
+	    fprintf (outf, "%*s<bb %d> [%.1f%%]:\n", indent, "", bb->index,
+		     bb->frequency * 100.0 / REG_BR_PROB_BASE);
 	}
     }
 }
@@ -2588,19 +2637,20 @@  dump_phi_nodes (pretty_printer *buffer, basic_block bb, int indent, int flags)
    to BUFFER.  */
 
 static void
-pp_cfg_jump (pretty_printer *buffer, basic_block bb, int flags)
+pp_cfg_jump (pretty_printer *buffer, edge e, int flags)
 {
   if (flags & TDF_GIMPLE)
     {
       pp_string (buffer, "goto bb_");
-      pp_decimal_int (buffer, bb->index);
+      pp_decimal_int (buffer, e->dest->index);
       pp_semicolon (buffer);
     }
   else
     {
-      gimple *stmt = first_stmt (bb);
+      gimple *stmt = first_stmt (e->dest);
+
       pp_string (buffer, "goto <bb ");
-      pp_decimal_int (buffer, bb->index);
+      pp_decimal_int (buffer, e->dest->index);
       pp_greater (buffer);
       if (stmt && gimple_code (stmt) == GIMPLE_LABEL)
 	{
@@ -2613,6 +2663,8 @@  pp_cfg_jump (pretty_printer *buffer, basic_block bb, int flags)
 	}
       else
 	pp_semicolon (buffer);
+
+      dump_edge_probability (buffer, e);
     }
 }
 
@@ -2641,11 +2693,11 @@  dump_implicit_edges (pretty_printer *buffer, basic_block bb, int indent,
       extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
 
       INDENT (indent + 2);
-      pp_cfg_jump (buffer, true_edge->dest, flags);
+      pp_cfg_jump (buffer, true_edge, flags);
       newline_and_indent (buffer, indent);
       pp_string (buffer, "else");
       newline_and_indent (buffer, indent + 2);
-      pp_cfg_jump (buffer, false_edge->dest, flags);
+      pp_cfg_jump (buffer, false_edge, flags);
       pp_newline (buffer);
       return;
     }
@@ -2662,7 +2714,7 @@  dump_implicit_edges (pretty_printer *buffer, basic_block bb, int indent,
 	  && e->goto_locus != UNKNOWN_LOCATION)
 	dump_location (buffer, e->goto_locus);
 
-      pp_cfg_jump (buffer, e->dest, flags);
+      pp_cfg_jump (buffer, e, flags);
       pp_newline (buffer);
     }
 }
diff --git a/gcc/testsuite/gcc.dg/builtin-unreachable-6.c b/gcc/testsuite/gcc.dg/builtin-unreachable-6.c
index 2f8ca36..d2596e9 100644
--- a/gcc/testsuite/gcc.dg/builtin-unreachable-6.c
+++ b/gcc/testsuite/gcc.dg/builtin-unreachable-6.c
@@ -16,5 +16,5 @@  lab2:
   goto *x;
 }
 
-/* { dg-final { scan-tree-dump-times "lab:" 1 "fab1" } } */
+/* { dg-final { scan-tree-dump-times "lab \\\[\[0-9.\]+%\\\]" 1 "fab1" } } */
 /* { dg-final { scan-tree-dump-times "__builtin_unreachable" 1 "fab1" } } */
diff --git a/gcc/testsuite/gcc.dg/pr34027-1.c b/gcc/testsuite/gcc.dg/pr34027-1.c
index b1163ce..0405e35 100644
--- a/gcc/testsuite/gcc.dg/pr34027-1.c
+++ b/gcc/testsuite/gcc.dg/pr34027-1.c
@@ -11,5 +11,5 @@  unsigned long foobar(unsigned long ns)
 /* This test was originally introduced to test that we transform
    to ns % 10000.  See the discussion of PR 32044 why we do not do
    that anymore.  */
-/* { dg-final { scan-tree-dump-times "%" 0 "optimized" } } */
-/* { dg-final { scan-tree-dump-times "/" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " % " 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " / " 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/strict-overflow-2.c b/gcc/testsuite/gcc.dg/strict-overflow-2.c
index c39d8e8..f23c43a 100644
--- a/gcc/testsuite/gcc.dg/strict-overflow-2.c
+++ b/gcc/testsuite/gcc.dg/strict-overflow-2.c
@@ -12,4 +12,4 @@  foo (int i)
   return (i * 100) / 10;
 }
 
-/* { dg-final { scan-tree-dump-not "100" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "\\\* 100" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040703-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040703-1.c
index 25e470a..2980047 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/20040703-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/20040703-1.c
@@ -9,4 +9,4 @@  float foo(float x)
 }
 
 /* We should *not* fold the arithmetic.  */
-/* { dg-final { scan-tree-dump-times "0\\.0" 0 "dom2"} } */
+/* { dg-final { scan-tree-dump-times "0\\.0\[^%\]" 0 "dom2"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-2.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-2.c
index 1996665..6279956 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-2.c
@@ -252,5 +252,5 @@  RNG (0,  6,   8, "%s%ls", "1", L"2");
 
 */
 
-/* { dg-final { scan-tree-dump-times ">:\n *__builtin_abort" 114 "optimized" { target { ilp32 || lp64 } } } } */
-/* { dg-final { scan-tree-dump-times ">:\n *__builtin_abort" 83 "optimized" { target { { ! ilp32 } && { ! lp64 } } } } } */
+/* { dg-final { scan-tree-dump-times "> \\\[\[0-9.\]+%\\\]:\n *__builtin_abort" 114 "optimized" { target { ilp32 || lp64 } } } } */
+/* { dg-final { scan-tree-dump-times "> \\\[\[0-9.\]+%\\\]:\n *__builtin_abort" 83 "optimized" { target { { ! ilp32 } && { ! lp64 } } } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/dump-2.c b/gcc/testsuite/gcc.dg/tree-ssa/dump-2.c
new file mode 100644
index 0000000..11cde92
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/dump-2.c
@@ -0,0 +1,9 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized" } */
+
+int f(void)
+{
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "<bb \[0-9\]> \\\[100\\\.0%\\\]:" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr32044.c b/gcc/testsuite/gcc.dg/tree-ssa/pr32044.c
index 745a5e4..8a8977a 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr32044.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr32044.c
@@ -48,6 +48,6 @@  int baz (int n)
 
 /* There should be no division/modulo in the final dump (division and modulo
    by 64 are done using bit operations).  */
-/* { dg-final { scan-tree-dump-times "/" 0 "optimized" } } */
-/* { dg-final { scan-tree-dump-times "%" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " / " 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " % " 0 "optimized" } } */
 
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vector-3.c b/gcc/testsuite/gcc.dg/tree-ssa/vector-3.c
index ecdebf6..589ee7e 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vector-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vector-3.c
@@ -14,6 +14,6 @@  float f(float b)
 
 /* We should be able to optimize this to just "return 0.0;" */
 /* { dg-final { scan-tree-dump-times "BIT_FIELD_REF" 0 "optimized"} } */
-/* { dg-final { scan-tree-dump-times "0\\\.0" 1 "optimized"} } */
+/* { dg-final { scan-tree-dump-times " 0\\\.0" 1 "optimized"} } */
 
 
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp101.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp101.c
index cfca539..bf4109f 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp101.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp101.c
@@ -10,4 +10,4 @@  int main ()
   return 0;
 }
 
-/* { dg-final { scan-tree-dump "<bb 2>:\[\n\r \]*return 0;" "optimized" } } */
+/* { dg-final { scan-tree-dump "<bb 2> \\\[\[0-9.\]+%\\\]:\[\n\r \]*return 0;" "optimized" } } */
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index 2655c23..5c667a2 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -4807,7 +4807,7 @@  get_scaled_computation_cost_at (ivopts_data *data, gimple *at, iv_cand *cand,
 				comp_cost cost)
 {
    int loop_freq = data->current_loop->header->frequency;
-   int bb_freq = at->bb->frequency;
+   int bb_freq = gimple_bb (at)->frequency;
    if (loop_freq != 0)
      {
        gcc_assert (cost.scratch <= cost.cost);
-- 
2.10.2