diff mbox

add dbgcnt and opt-info support for devirtualization

Message ID CAAkRFZKGLC9vW3-niUu2QrQGKZzUeq6Qv989bOaHdLjkn=6JqA@mail.gmail.com
State New
Headers show

Commit Message

Xinliang David Li May 15, 2014, 11:54 p.m. UTC
Hi, debugging runtime bugs due to devirtualization can be hard for
very large C++ programs with complicated class hierarchy. This patch
adds the support to report this high level transformation via
-fopt-info (not hidden inside dump file) and the ability the do binary
search with cutoff.

Ok for trunk after build and test?

thanks,

David

Comments

Richard Biener May 16, 2014, 11 a.m. UTC | #1
On Fri, May 16, 2014 at 1:54 AM, Xinliang David Li <davidxl@google.com> wrote:
> Hi, debugging runtime bugs due to devirtualization can be hard for
> very large C++ programs with complicated class hierarchy. This patch
> adds the support to report this high level transformation via
> -fopt-info (not hidden inside dump file) and the ability the do binary
> search with cutoff.
>
> Ok for trunk after build and test?

+          else if (dump_enabled_p ())
+           {
+             location_t loc = gimple_location (ie->call_stmt);
+             dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
+                              "Discovered direct call to non-function in %s, "

diagnostics start with lower-case.  Why not merge this with the
dump_file case?  The point of all the infrastructure was to _not_
need to distinguish the cases ...

(similar for the other cases, and IIRC you miss one case in
tree-ssa-pre.c calling ipa_intraprocedural_devirtualization?)

Thanks,
Richard.


> thanks,
>
> David
Xinliang David Li May 16, 2014, 3:30 p.m. UTC | #2
On Fri, May 16, 2014 at 4:00 AM, Richard Biener
<richard.guenther@gmail.com> wrote:
> On Fri, May 16, 2014 at 1:54 AM, Xinliang David Li <davidxl@google.com> wrote:
>> Hi, debugging runtime bugs due to devirtualization can be hard for
>> very large C++ programs with complicated class hierarchy. This patch
>> adds the support to report this high level transformation via
>> -fopt-info (not hidden inside dump file) and the ability the do binary
>> search with cutoff.
>>
>> Ok for trunk after build and test?
>
> +          else if (dump_enabled_p ())
> +           {
> +             location_t loc = gimple_location (ie->call_stmt);
> +             dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
> +                              "Discovered direct call to non-function in %s, "
>
> diagnostics start with lower-case.  Why not merge this with the
> dump_file case?  The point of all the infrastructure was to _not_
> need to distinguish the cases ...
>

Right -- however in this case I don't want the node 'order' to leak
into the opt report. Should we drop it?


> (similar for the other cases, and IIRC you miss one case in
> tree-ssa-pre.c calling ipa_intraprocedural_devirtualization?)

Good catch. Will add it.

thanks,

David
>
> Thanks,
> Richard.
>
>
>> thanks,
>>
>> David
Jan Hubicka May 16, 2014, 4:03 p.m. UTC | #3
> Hi, debugging runtime bugs due to devirtualization can be hard for
> very large C++ programs with complicated class hierarchy. This patch
> adds the support to report this high level transformation via
> -fopt-info (not hidden inside dump file) and the ability the do binary
> search with cutoff.
> 
> Ok for trunk after build and test?

Seems resonable to me.
> 
> thanks,
> 
> David

> Index: ChangeLog
> ===================================================================
> --- ChangeLog	(revision 210479)
> +++ ChangeLog	(working copy)
> @@ -1,3 +1,18 @@
> +2014-05-15  Xinliang David Li  <davidxl@google.com>
> +
> +	* cgraphunit.c (walk_polymorphic_call_targets): Add
> +	dbgcnt and fopt-info support.
> +	2014-05-15  Xinliang David Li  <davidxl@google.com>
> +
> +		* cgraphunit.c (walk_polymorphic_call_targets): Add
> +		dbgcnt and fopt-info support.
> +		* ipa-prop.c (ipa_make_edge_direct_to_target): Ditto.
> +		* ipa-devirt.c (ipa_devirt): Ditto.
> +		* ipa.c (walk_polymorphic_call_targets): Ditto.
> +		* gimple-fold.c (fold_gimple_assign): Ditto.
> +		(gimple_fold_call): Ditto.
> +		* dbgcnt.def: New counter.
> +
>  2014-05-15  Martin Jambor  <mjambor@suse.cz>
>  
>  	PR ipa/61085
> Index: ipa-prop.c
> ===================================================================
> --- ipa-prop.c	(revision 210479)
> +++ ipa-prop.c	(working copy)
> @@ -59,6 +59,7 @@ along with GCC; see the file COPYING3.
>  #include "ipa-utils.h"
>  #include "stringpool.h"
>  #include "tree-ssanames.h"
> +#include "dbgcnt.h"
>  
>  /* Intermediate information about a parameter that is only useful during the
>     run of ipa_analyze_node and is not kept afterwards.  */
> @@ -2494,6 +2495,13 @@ ipa_make_edge_direct_to_target (struct c
>  	    fprintf (dump_file, "ipa-prop: Discovered direct call to non-function"
>  				" in %s/%i, making it unreachable.\n",
>  		     ie->caller->name (), ie->caller->order);
> +          else if (dump_enabled_p ())
> +	    {
> +	      location_t loc = gimple_location (ie->call_stmt);
> +	      dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
> +			       "Discovered direct call to non-function in %s, "
> +			       "making it unreachable\n", ie->caller->name ());

Perhaps "turning it to __builtin_unreachable call" and similarly in the other cases
we introduce __builtin_unreachable? I think that could be easier for user to work
out.

What king of problems in devirtualizatoin you are seeing?


Honza
Xinliang David Li May 16, 2014, 4:14 p.m. UTC | #4
On Fri, May 16, 2014 at 9:03 AM, Jan Hubicka <hubicka@ucw.cz> wrote:
>> Hi, debugging runtime bugs due to devirtualization can be hard for
>> very large C++ programs with complicated class hierarchy. This patch
>> adds the support to report this high level transformation via
>> -fopt-info (not hidden inside dump file) and the ability the do binary
>> search with cutoff.
>>
>> Ok for trunk after build and test?
>
> Seems resonable to me.
>>
>> thanks,
>>
>> David
>
>> Index: ChangeLog
>> ===================================================================
>> --- ChangeLog (revision 210479)
>> +++ ChangeLog (working copy)
>> @@ -1,3 +1,18 @@
>> +2014-05-15  Xinliang David Li  <davidxl@google.com>
>> +
>> +     * cgraphunit.c (walk_polymorphic_call_targets): Add
>> +     dbgcnt and fopt-info support.
>> +     2014-05-15  Xinliang David Li  <davidxl@google.com>
>> +
>> +             * cgraphunit.c (walk_polymorphic_call_targets): Add
>> +             dbgcnt and fopt-info support.
>> +             * ipa-prop.c (ipa_make_edge_direct_to_target): Ditto.
>> +             * ipa-devirt.c (ipa_devirt): Ditto.
>> +             * ipa.c (walk_polymorphic_call_targets): Ditto.
>> +             * gimple-fold.c (fold_gimple_assign): Ditto.
>> +             (gimple_fold_call): Ditto.
>> +             * dbgcnt.def: New counter.
>> +
>>  2014-05-15  Martin Jambor  <mjambor@suse.cz>
>>
>>       PR ipa/61085
>> Index: ipa-prop.c
>> ===================================================================
>> --- ipa-prop.c        (revision 210479)
>> +++ ipa-prop.c        (working copy)
>> @@ -59,6 +59,7 @@ along with GCC; see the file COPYING3.
>>  #include "ipa-utils.h"
>>  #include "stringpool.h"
>>  #include "tree-ssanames.h"
>> +#include "dbgcnt.h"
>>
>>  /* Intermediate information about a parameter that is only useful during the
>>     run of ipa_analyze_node and is not kept afterwards.  */
>> @@ -2494,6 +2495,13 @@ ipa_make_edge_direct_to_target (struct c
>>           fprintf (dump_file, "ipa-prop: Discovered direct call to non-function"
>>                               " in %s/%i, making it unreachable.\n",
>>                    ie->caller->name (), ie->caller->order);
>> +          else if (dump_enabled_p ())
>> +         {
>> +           location_t loc = gimple_location (ie->call_stmt);
>> +           dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
>> +                            "Discovered direct call to non-function in %s, "
>> +                            "making it unreachable\n", ie->caller->name ());
>
> Perhaps "turning it to __builtin_unreachable call" and similarly in the other cases
> we introduce __builtin_unreachable? I think that could be easier for user to work
> out.

Ok.

>
> What king of problems in devirtualizatoin you are seeing?

I have been chasing a runtime failure of a very large test built with
gcc-4_9. The bad code either calls a pure function or turn a virtual
call into __builtin_unreachable (incomplete target set). The indirect
info shows the otr type to be !maybe_derived_type, and the outer-type
gets cleared during inline update. I isolated a small test case -- but
the good news is that gcc-4_9 @head already fixed the problem.

I will  check in the test case to trunk later.

thanks,

David

>
>
> Honza
Jan Hubicka May 16, 2014, 4:51 p.m. UTC | #5
> 
> I have been chasing a runtime failure of a very large test built with
> gcc-4_9. The bad code either calls a pure function or turn a virtual
> call into __builtin_unreachable (incomplete target set). The indirect
> info shows the otr type to be !maybe_derived_type, and the outer-type
> gets cleared during inline update. I isolated a small test case -- but
> the good news is that gcc-4_9 @head already fixed the problem.
> 
> I will  check in the test case to trunk later.

Good, testcase would be welcome.  I guess it was the fix for placement_new bug.
It disables some valid devirtualizations (and I thus may revisit the fix for
4.10), so it would be good to know if your testcase differs from the original
PR one.

Honza
> 
> thanks,
> 
> David
> 
> >
> >
> > Honza
Xinliang David Li May 16, 2014, 5:45 p.m. UTC | #6
On Fri, May 16, 2014 at 9:51 AM, Jan Hubicka <hubicka@ucw.cz> wrote:
>>
>> I have been chasing a runtime failure of a very large test built with
>> gcc-4_9. The bad code either calls a pure function or turn a virtual
>> call into __builtin_unreachable (incomplete target set). The indirect
>> info shows the otr type to be !maybe_derived_type, and the outer-type
>> gets cleared during inline update. I isolated a small test case -- but
>> the good news is that gcc-4_9 @head already fixed the problem.
>>
>> I will  check in the test case to trunk later.
>
> Good, testcase would be welcome.  I guess it was the fix for placement_new bug.
> It disables some valid devirtualizations (and I thus may revisit the fix for
> 4.10), so it would be good to know if your testcase differs from the original
> PR one.

I thought so too -- but when I backed out this single change from
trunk, the test still passes, so something else is also going on.

David

>
> Honza
>>
>> thanks,
>>
>> David
>>
>> >
>> >
>> > Honza
Xinliang David Li May 16, 2014, 9:19 p.m. UTC | #7
Modified the patch according to yours and Richard's feedback. PTAL.

thanks,

David

On Fri, May 16, 2014 at 9:03 AM, Jan Hubicka <hubicka@ucw.cz> wrote:
>> Hi, debugging runtime bugs due to devirtualization can be hard for
>> very large C++ programs with complicated class hierarchy. This patch
>> adds the support to report this high level transformation via
>> -fopt-info (not hidden inside dump file) and the ability the do binary
>> search with cutoff.
>>
>> Ok for trunk after build and test?
>
> Seems resonable to me.
>>
>> thanks,
>>
>> David
>
>> Index: ChangeLog
>> ===================================================================
>> --- ChangeLog (revision 210479)
>> +++ ChangeLog (working copy)
>> @@ -1,3 +1,18 @@
>> +2014-05-15  Xinliang David Li  <davidxl@google.com>
>> +
>> +     * cgraphunit.c (walk_polymorphic_call_targets): Add
>> +     dbgcnt and fopt-info support.
>> +     2014-05-15  Xinliang David Li  <davidxl@google.com>
>> +
>> +             * cgraphunit.c (walk_polymorphic_call_targets): Add
>> +             dbgcnt and fopt-info support.
>> +             * ipa-prop.c (ipa_make_edge_direct_to_target): Ditto.
>> +             * ipa-devirt.c (ipa_devirt): Ditto.
>> +             * ipa.c (walk_polymorphic_call_targets): Ditto.
>> +             * gimple-fold.c (fold_gimple_assign): Ditto.
>> +             (gimple_fold_call): Ditto.
>> +             * dbgcnt.def: New counter.
>> +
>>  2014-05-15  Martin Jambor  <mjambor@suse.cz>
>>
>>       PR ipa/61085
>> Index: ipa-prop.c
>> ===================================================================
>> --- ipa-prop.c        (revision 210479)
>> +++ ipa-prop.c        (working copy)
>> @@ -59,6 +59,7 @@ along with GCC; see the file COPYING3.
>>  #include "ipa-utils.h"
>>  #include "stringpool.h"
>>  #include "tree-ssanames.h"
>> +#include "dbgcnt.h"
>>
>>  /* Intermediate information about a parameter that is only useful during the
>>     run of ipa_analyze_node and is not kept afterwards.  */
>> @@ -2494,6 +2495,13 @@ ipa_make_edge_direct_to_target (struct c
>>           fprintf (dump_file, "ipa-prop: Discovered direct call to non-function"
>>                               " in %s/%i, making it unreachable.\n",
>>                    ie->caller->name (), ie->caller->order);
>> +          else if (dump_enabled_p ())
>> +         {
>> +           location_t loc = gimple_location (ie->call_stmt);
>> +           dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
>> +                            "Discovered direct call to non-function in %s, "
>> +                            "making it unreachable\n", ie->caller->name ());
>
> Perhaps "turning it to __builtin_unreachable call" and similarly in the other cases
> we introduce __builtin_unreachable? I think that could be easier for user to work
> out.
>
> What king of problems in devirtualizatoin you are seeing?
>
>
> Honza
Xinliang David Li May 18, 2014, 9:55 p.m. UTC | #8
There is no test regression. Ok with this patch?

David

On Fri, May 16, 2014 at 2:19 PM, Xinliang David Li <davidxl@google.com> wrote:
> Modified the patch according to yours and Richard's feedback. PTAL.
>
> thanks,
>
> David
>
> On Fri, May 16, 2014 at 9:03 AM, Jan Hubicka <hubicka@ucw.cz> wrote:
>>> Hi, debugging runtime bugs due to devirtualization can be hard for
>>> very large C++ programs with complicated class hierarchy. This patch
>>> adds the support to report this high level transformation via
>>> -fopt-info (not hidden inside dump file) and the ability the do binary
>>> search with cutoff.
>>>
>>> Ok for trunk after build and test?
>>
>> Seems resonable to me.
>>>
>>> thanks,
>>>
>>> David
>>
>>> Index: ChangeLog
>>> ===================================================================
>>> --- ChangeLog (revision 210479)
>>> +++ ChangeLog (working copy)
>>> @@ -1,3 +1,18 @@
>>> +2014-05-15  Xinliang David Li  <davidxl@google.com>
>>> +
>>> +     * cgraphunit.c (walk_polymorphic_call_targets): Add
>>> +     dbgcnt and fopt-info support.
>>> +     2014-05-15  Xinliang David Li  <davidxl@google.com>
>>> +
>>> +             * cgraphunit.c (walk_polymorphic_call_targets): Add
>>> +             dbgcnt and fopt-info support.
>>> +             * ipa-prop.c (ipa_make_edge_direct_to_target): Ditto.
>>> +             * ipa-devirt.c (ipa_devirt): Ditto.
>>> +             * ipa.c (walk_polymorphic_call_targets): Ditto.
>>> +             * gimple-fold.c (fold_gimple_assign): Ditto.
>>> +             (gimple_fold_call): Ditto.
>>> +             * dbgcnt.def: New counter.
>>> +
>>>  2014-05-15  Martin Jambor  <mjambor@suse.cz>
>>>
>>>       PR ipa/61085
>>> Index: ipa-prop.c
>>> ===================================================================
>>> --- ipa-prop.c        (revision 210479)
>>> +++ ipa-prop.c        (working copy)
>>> @@ -59,6 +59,7 @@ along with GCC; see the file COPYING3.
>>>  #include "ipa-utils.h"
>>>  #include "stringpool.h"
>>>  #include "tree-ssanames.h"
>>> +#include "dbgcnt.h"
>>>
>>>  /* Intermediate information about a parameter that is only useful during the
>>>     run of ipa_analyze_node and is not kept afterwards.  */
>>> @@ -2494,6 +2495,13 @@ ipa_make_edge_direct_to_target (struct c
>>>           fprintf (dump_file, "ipa-prop: Discovered direct call to non-function"
>>>                               " in %s/%i, making it unreachable.\n",
>>>                    ie->caller->name (), ie->caller->order);
>>> +          else if (dump_enabled_p ())
>>> +         {
>>> +           location_t loc = gimple_location (ie->call_stmt);
>>> +           dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
>>> +                            "Discovered direct call to non-function in %s, "
>>> +                            "making it unreachable\n", ie->caller->name ());
>>
>> Perhaps "turning it to __builtin_unreachable call" and similarly in the other cases
>> we introduce __builtin_unreachable? I think that could be easier for user to work
>> out.
>>
>> What king of problems in devirtualizatoin you are seeing?
>>
>>
>> Honza
Richard Biener May 19, 2014, 9:21 a.m. UTC | #9
On Fri, May 16, 2014 at 11:19 PM, Xinliang David Li <davidxl@google.com> wrote:
> Modified the patch according to yours and Richard's feedback. PTAL.

ENOPATCH.

Btw, I don't see any issue with leaking node order to opt-report.

Richard.

> thanks,
>
> David
>
> On Fri, May 16, 2014 at 9:03 AM, Jan Hubicka <hubicka@ucw.cz> wrote:
>>> Hi, debugging runtime bugs due to devirtualization can be hard for
>>> very large C++ programs with complicated class hierarchy. This patch
>>> adds the support to report this high level transformation via
>>> -fopt-info (not hidden inside dump file) and the ability the do binary
>>> search with cutoff.
>>>
>>> Ok for trunk after build and test?
>>
>> Seems resonable to me.
>>>
>>> thanks,
>>>
>>> David
>>
>>> Index: ChangeLog
>>> ===================================================================
>>> --- ChangeLog (revision 210479)
>>> +++ ChangeLog (working copy)
>>> @@ -1,3 +1,18 @@
>>> +2014-05-15  Xinliang David Li  <davidxl@google.com>
>>> +
>>> +     * cgraphunit.c (walk_polymorphic_call_targets): Add
>>> +     dbgcnt and fopt-info support.
>>> +     2014-05-15  Xinliang David Li  <davidxl@google.com>
>>> +
>>> +             * cgraphunit.c (walk_polymorphic_call_targets): Add
>>> +             dbgcnt and fopt-info support.
>>> +             * ipa-prop.c (ipa_make_edge_direct_to_target): Ditto.
>>> +             * ipa-devirt.c (ipa_devirt): Ditto.
>>> +             * ipa.c (walk_polymorphic_call_targets): Ditto.
>>> +             * gimple-fold.c (fold_gimple_assign): Ditto.
>>> +             (gimple_fold_call): Ditto.
>>> +             * dbgcnt.def: New counter.
>>> +
>>>  2014-05-15  Martin Jambor  <mjambor@suse.cz>
>>>
>>>       PR ipa/61085
>>> Index: ipa-prop.c
>>> ===================================================================
>>> --- ipa-prop.c        (revision 210479)
>>> +++ ipa-prop.c        (working copy)
>>> @@ -59,6 +59,7 @@ along with GCC; see the file COPYING3.
>>>  #include "ipa-utils.h"
>>>  #include "stringpool.h"
>>>  #include "tree-ssanames.h"
>>> +#include "dbgcnt.h"
>>>
>>>  /* Intermediate information about a parameter that is only useful during the
>>>     run of ipa_analyze_node and is not kept afterwards.  */
>>> @@ -2494,6 +2495,13 @@ ipa_make_edge_direct_to_target (struct c
>>>           fprintf (dump_file, "ipa-prop: Discovered direct call to non-function"
>>>                               " in %s/%i, making it unreachable.\n",
>>>                    ie->caller->name (), ie->caller->order);
>>> +          else if (dump_enabled_p ())
>>> +         {
>>> +           location_t loc = gimple_location (ie->call_stmt);
>>> +           dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
>>> +                            "Discovered direct call to non-function in %s, "
>>> +                            "making it unreachable\n", ie->caller->name ());
>>
>> Perhaps "turning it to __builtin_unreachable call" and similarly in the other cases
>> we introduce __builtin_unreachable? I think that could be easier for user to work
>> out.
>>
>> What king of problems in devirtualizatoin you are seeing?
>>
>>
>> Honza
diff mbox

Patch

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 210479)
+++ ChangeLog	(working copy)
@@ -1,3 +1,18 @@ 
+2014-05-15  Xinliang David Li  <davidxl@google.com>
+
+	* cgraphunit.c (walk_polymorphic_call_targets): Add
+	dbgcnt and fopt-info support.
+	2014-05-15  Xinliang David Li  <davidxl@google.com>
+
+		* cgraphunit.c (walk_polymorphic_call_targets): Add
+		dbgcnt and fopt-info support.
+		* ipa-prop.c (ipa_make_edge_direct_to_target): Ditto.
+		* ipa-devirt.c (ipa_devirt): Ditto.
+		* ipa.c (walk_polymorphic_call_targets): Ditto.
+		* gimple-fold.c (fold_gimple_assign): Ditto.
+		(gimple_fold_call): Ditto.
+		* dbgcnt.def: New counter.
+
 2014-05-15  Martin Jambor  <mjambor@suse.cz>
 
 	PR ipa/61085
Index: ipa-prop.c
===================================================================
--- ipa-prop.c	(revision 210479)
+++ ipa-prop.c	(working copy)
@@ -59,6 +59,7 @@  along with GCC; see the file COPYING3.
 #include "ipa-utils.h"
 #include "stringpool.h"
 #include "tree-ssanames.h"
+#include "dbgcnt.h"
 
 /* Intermediate information about a parameter that is only useful during the
    run of ipa_analyze_node and is not kept afterwards.  */
@@ -2494,6 +2495,13 @@  ipa_make_edge_direct_to_target (struct c
 	    fprintf (dump_file, "ipa-prop: Discovered direct call to non-function"
 				" in %s/%i, making it unreachable.\n",
 		     ie->caller->name (), ie->caller->order);
+          else if (dump_enabled_p ())
+	    {
+	      location_t loc = gimple_location (ie->call_stmt);
+	      dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
+			       "Discovered direct call to non-function in %s, "
+			       "making it unreachable\n", ie->caller->name ());
+	    }
 	  target = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
 	  callee = cgraph_get_create_node (target);
 	  unreachable = true;
@@ -2527,6 +2535,10 @@  ipa_make_edge_direct_to_target (struct c
 	}
       callee = cgraph_get_create_node (target);
     }
+
+  if (!dbg_cnt (devirt))
+    return NULL;
+
   ipa_check_create_node_params ();
 
   /* We can not make edges to inline clones.  It is bug that someone removed
@@ -2547,6 +2559,13 @@  ipa_make_edge_direct_to_target (struct c
       else
 	fprintf (dump_file, "with uid %i\n", ie->lto_stmt_uid);
      }
+  if (dump_enabled_p ())
+    {
+      location_t loc = gimple_location (ie->call_stmt);
+      dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
+		       "Converting indirect call in %s to direct call to %s\n",
+		       ie->caller->name (), callee->name ());
+    }
   ie = cgraph_make_edge_direct (ie, callee);
   es = inline_edge_summary (ie);
   es->call_stmt_size -= (eni_size_weights.indirect_call_cost
Index: gimple-fold.c
===================================================================
--- gimple-fold.c	(revision 210479)
+++ gimple-fold.c	(working copy)
@@ -52,6 +52,7 @@  along with GCC; see the file COPYING3.
 #include "tree-ssa-address.h"
 #include "langhooks.h"
 #include "gimplify-me.h"
+#include "dbgcnt.h"
 
 /* Return true when DECL can be referenced from current unit.
    FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
@@ -389,10 +390,23 @@  fold_gimple_assign (gimple_stmt_iterator
 		if (final && targets.length () <= 1)
 		  {
 		    tree fndecl;
+		    if (!dbg_cnt (devirt))
+		      return val;
+
 		    if (targets.length () == 1)
 		      fndecl = targets[0]->decl;
 		    else
 		      fndecl = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
+		    if (dump_enabled_p ())
+		      {
+			location_t loc = gimple_location (stmt);
+			dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
+					 "Resolving virtual function address "
+					 "reference to function %s\n",
+					 targets.length () == 1
+					 ? targets[0]->name ()
+					 : "unreachable function"); 
+		      }
 		    val = fold_convert (TREE_TYPE (val), fndecl);
 		    STRIP_USELESS_TYPE_CONVERSION (val);
 		    return val;
@@ -1124,9 +1138,18 @@  gimple_fold_call (gimple_stmt_iterator *
 	  bool final;
 	  vec <cgraph_node *>targets
 	    = possible_polymorphic_call_targets (callee, &final);
-	  if (final && targets.length () <= 1)
+	  if (final && targets.length () <= 1 && !dbg_cnt (devirt))
 	    {
 	      tree lhs = gimple_call_lhs (stmt);
+	      if (dump_enabled_p ())
+		{
+		  location_t loc = gimple_location (stmt);
+		  dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
+				   "Folding virtual function call to %s\n",
+		 		   targets.length () == 1
+		  		   ? targets[0]->name ()
+		  		   : "unreachable function"); 
+		}
 	      if (targets.length () == 1)
 		{
 		  gimple_call_set_fndecl (stmt, targets[0]->decl);
Index: cgraphunit.c
===================================================================
--- cgraphunit.c	(revision 210479)
+++ cgraphunit.c	(working copy)
@@ -210,6 +210,7 @@  along with GCC; see the file COPYING3.
 #include "pass_manager.h"
 #include "tree-nested.h"
 #include "gimplify.h"
+#include "dbgcnt.h"
 
 /* Queue of cgraph nodes scheduled to be added into cgraph.  This is a
    secondary queue used during optimization to accommodate passes that
@@ -888,6 +889,9 @@  walk_polymorphic_call_targets (pointer_s
     {
       if (targets.length () <= 1)
 	{
+	  if (!dbg_cnt (devirt))
+	    return;
+
 	  cgraph_node *target;
 	  if (targets.length () == 1)
 	    target = targets[0];
@@ -903,6 +907,14 @@  walk_polymorphic_call_targets (pointer_s
 				 edge->call_stmt, 0,
 				 TDF_SLIM);
 	    }
+          else if (dump_enabled_p ())
+            {
+	      location_t locus = gimple_location (edge->call_stmt);
+	      dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, locus,
+                               "Devirtualizing call in %s to %s\n",
+                               edge->caller->name (), target->name ());
+	    }
+
 	  cgraph_make_edge_direct (edge, target);
 	  cgraph_redirect_edge_call_stmt_to_callee (edge);
 	  if (cgraph_dump_file)
Index: ipa-devirt.c
===================================================================
--- ipa-devirt.c	(revision 210479)
+++ ipa-devirt.c	(working copy)
@@ -129,6 +129,7 @@  along with GCC; see the file COPYING3.
 #include "diagnostic.h"
 #include "tree-dfa.h"
 #include "demangle.h"
+#include "dbgcnt.h"
 
 static bool odr_violation_reported = false;
 
@@ -2069,12 +2070,22 @@  ipa_devirt (void)
 	      }
 	    else
 	      {
-		if (dump_file)
-		  fprintf (dump_file,
-			   "Speculatively devirtualizing call in %s/%i to %s/%i\n\n",
-			   n->name (), n->order,
-			   likely_target->name (),
-			   likely_target->order);
+                if (!dbg_cnt (devirt))
+                  continue;
+		if (dump_enabled_p ())
+                  {
+                    location_t locus = gimple_location (e->call_stmt);
+                    if (dump_file)
+                      dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, locus,
+                                       "Speculatively devirtualizing call in %s/%i to %s/%i\n\n",
+                                       n->name (), n->order,
+                                       likely_target->name (),
+                                       likely_target->order);
+                    else
+                      dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, locus,
+                                       "Speculatively devirtualizing call in %s to %s\n",
+                                       n->name (), likely_target->name ());
+                  }
 		if (!symtab_can_be_discarded (likely_target))
 		  {
 		    cgraph_node *alias;
Index: ipa.c
===================================================================
--- ipa.c	(revision 210479)
+++ ipa.c	(working copy)
@@ -37,6 +37,10 @@  along with GCC; see the file COPYING3.
 #include "tree-inline.h"
 #include "profile.h"
 #include "params.h"
+#include "internal-fn.h"
+#include "tree-ssa-alias.h"
+#include "gimple.h"
+#include "dbgcnt.h"
 
 /* Return true when NODE can not be local. Worker for cgraph_local_node_p.  */
 
@@ -215,6 +219,9 @@  walk_polymorphic_call_targets (pointer_s
     {
       if (targets.length () <= 1)
 	{
+	  if (!dbg_cnt (devirt))
+             return;
+
 	  cgraph_node *target, *node = edge->caller;
 	  if (targets.length () == 1)
 	    target = targets[0];
@@ -222,12 +229,20 @@  walk_polymorphic_call_targets (pointer_s
 	    target = cgraph_get_create_node
 		       (builtin_decl_implicit (BUILT_IN_UNREACHABLE));
 
-	  if (dump_file)
-	    fprintf (dump_file,
-		     "Devirtualizing call in %s/%i to %s/%i\n",
-		     edge->caller->name (),
-		     edge->caller->order,
-		     target->name (), target->order);
+	  if (dump_enabled_p ())
+            {
+              location_t locus = gimple_location (edge->call_stmt);
+              if (dump_file)
+                dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, locus,
+				 "Devirtualizing call in %s/%i to %s/%i\n",
+				 edge->caller->name (), edge->caller->order,
+				 target->name (),
+				 target->order);
+	      else
+		dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, locus,
+				 "Devirtualizing call in %s to %s\n",
+				 edge->caller->name (), target->name ());
+	    }
 	  edge = cgraph_make_edge_direct (edge, target);
 	  if (inline_summary_vec)
 	    inline_update_overall_summary (node);
Index: dbgcnt.def
===================================================================
--- dbgcnt.def	(revision 210479)
+++ dbgcnt.def	(working copy)
@@ -150,6 +150,7 @@  DEBUG_COUNTER (dce)
 DEBUG_COUNTER (dce_fast)
 DEBUG_COUNTER (dce_ud)
 DEBUG_COUNTER (delete_trivial_dead)
+DEBUG_COUNTER (devirt)
 DEBUG_COUNTER (df_byte_scan)
 DEBUG_COUNTER (dse)
 DEBUG_COUNTER (dse1)