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)
