xref: /dflybsd-src/contrib/gcc-4.7/gcc/tree-profile.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* Calculate branch probabilities, and basic block execution counts.
2*e4b17023SJohn Marino    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
3*e4b17023SJohn Marino    2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010
4*e4b17023SJohn Marino    Free Software Foundation, Inc.
5*e4b17023SJohn Marino    Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
6*e4b17023SJohn Marino    based on some ideas from Dain Samples of UC Berkeley.
7*e4b17023SJohn Marino    Further mangling by Bob Manson, Cygnus Support.
8*e4b17023SJohn Marino    Converted to use trees by Dale Johannesen, Apple Computer.
9*e4b17023SJohn Marino 
10*e4b17023SJohn Marino This file is part of GCC.
11*e4b17023SJohn Marino 
12*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
13*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
14*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
15*e4b17023SJohn Marino version.
16*e4b17023SJohn Marino 
17*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
18*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
19*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20*e4b17023SJohn Marino for more details.
21*e4b17023SJohn Marino 
22*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
23*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
24*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
25*e4b17023SJohn Marino 
26*e4b17023SJohn Marino /* Generate basic block profile instrumentation and auxiliary files.
27*e4b17023SJohn Marino    Tree-based version.  See profile.c for overview.  */
28*e4b17023SJohn Marino 
29*e4b17023SJohn Marino #include "config.h"
30*e4b17023SJohn Marino #include "system.h"
31*e4b17023SJohn Marino #include "coretypes.h"
32*e4b17023SJohn Marino #include "tm.h"
33*e4b17023SJohn Marino #include "flags.h"
34*e4b17023SJohn Marino #include "regs.h"
35*e4b17023SJohn Marino #include "function.h"
36*e4b17023SJohn Marino #include "basic-block.h"
37*e4b17023SJohn Marino #include "diagnostic-core.h"
38*e4b17023SJohn Marino #include "coverage.h"
39*e4b17023SJohn Marino #include "tree.h"
40*e4b17023SJohn Marino #include "tree-flow.h"
41*e4b17023SJohn Marino #include "tree-dump.h"
42*e4b17023SJohn Marino #include "tree-pass.h"
43*e4b17023SJohn Marino #include "timevar.h"
44*e4b17023SJohn Marino #include "value-prof.h"
45*e4b17023SJohn Marino #include "cgraph.h"
46*e4b17023SJohn Marino #include "profile.h"
47*e4b17023SJohn Marino #include "target.h"
48*e4b17023SJohn Marino #include "output.h"
49*e4b17023SJohn Marino 
50*e4b17023SJohn Marino static GTY(()) tree gcov_type_node;
51*e4b17023SJohn Marino static GTY(()) tree gcov_type_tmp_var;
52*e4b17023SJohn Marino static GTY(()) tree tree_interval_profiler_fn;
53*e4b17023SJohn Marino static GTY(()) tree tree_pow2_profiler_fn;
54*e4b17023SJohn Marino static GTY(()) tree tree_one_value_profiler_fn;
55*e4b17023SJohn Marino static GTY(()) tree tree_indirect_call_profiler_fn;
56*e4b17023SJohn Marino static GTY(()) tree tree_average_profiler_fn;
57*e4b17023SJohn Marino static GTY(()) tree tree_ior_profiler_fn;
58*e4b17023SJohn Marino 
59*e4b17023SJohn Marino 
60*e4b17023SJohn Marino static GTY(()) tree ic_void_ptr_var;
61*e4b17023SJohn Marino static GTY(()) tree ic_gcov_type_ptr_var;
62*e4b17023SJohn Marino static GTY(()) tree ptr_void;
63*e4b17023SJohn Marino 
64*e4b17023SJohn Marino /* Do initialization work for the edge profiler.  */
65*e4b17023SJohn Marino 
66*e4b17023SJohn Marino /* Add code:
67*e4b17023SJohn Marino    static gcov*	__gcov_indirect_call_counters; // pointer to actual counter
68*e4b17023SJohn Marino    static void*	__gcov_indirect_call_callee; // actual callee address
69*e4b17023SJohn Marino */
70*e4b17023SJohn Marino static void
init_ic_make_global_vars(void)71*e4b17023SJohn Marino init_ic_make_global_vars (void)
72*e4b17023SJohn Marino {
73*e4b17023SJohn Marino   tree  gcov_type_ptr;
74*e4b17023SJohn Marino 
75*e4b17023SJohn Marino   ptr_void = build_pointer_type (void_type_node);
76*e4b17023SJohn Marino 
77*e4b17023SJohn Marino   ic_void_ptr_var
78*e4b17023SJohn Marino     = build_decl (UNKNOWN_LOCATION, VAR_DECL,
79*e4b17023SJohn Marino 		  get_identifier ("__gcov_indirect_call_callee"),
80*e4b17023SJohn Marino 		  ptr_void);
81*e4b17023SJohn Marino   TREE_STATIC (ic_void_ptr_var) = 1;
82*e4b17023SJohn Marino   TREE_PUBLIC (ic_void_ptr_var) = 0;
83*e4b17023SJohn Marino   DECL_ARTIFICIAL (ic_void_ptr_var) = 1;
84*e4b17023SJohn Marino   DECL_INITIAL (ic_void_ptr_var) = NULL;
85*e4b17023SJohn Marino   if (targetm.have_tls)
86*e4b17023SJohn Marino     DECL_TLS_MODEL (ic_void_ptr_var) =
87*e4b17023SJohn Marino       decl_default_tls_model (ic_void_ptr_var);
88*e4b17023SJohn Marino 
89*e4b17023SJohn Marino   varpool_finalize_decl (ic_void_ptr_var);
90*e4b17023SJohn Marino   varpool_mark_needed_node (varpool_node (ic_void_ptr_var));
91*e4b17023SJohn Marino 
92*e4b17023SJohn Marino   gcov_type_ptr = build_pointer_type (get_gcov_type ());
93*e4b17023SJohn Marino   ic_gcov_type_ptr_var
94*e4b17023SJohn Marino     = build_decl (UNKNOWN_LOCATION, VAR_DECL,
95*e4b17023SJohn Marino 		  get_identifier ("__gcov_indirect_call_counters"),
96*e4b17023SJohn Marino 		  gcov_type_ptr);
97*e4b17023SJohn Marino   TREE_STATIC (ic_gcov_type_ptr_var) = 1;
98*e4b17023SJohn Marino   TREE_PUBLIC (ic_gcov_type_ptr_var) = 0;
99*e4b17023SJohn Marino   DECL_ARTIFICIAL (ic_gcov_type_ptr_var) = 1;
100*e4b17023SJohn Marino   DECL_INITIAL (ic_gcov_type_ptr_var) = NULL;
101*e4b17023SJohn Marino   if (targetm.have_tls)
102*e4b17023SJohn Marino     DECL_TLS_MODEL (ic_gcov_type_ptr_var) =
103*e4b17023SJohn Marino       decl_default_tls_model (ic_gcov_type_ptr_var);
104*e4b17023SJohn Marino 
105*e4b17023SJohn Marino   varpool_finalize_decl (ic_gcov_type_ptr_var);
106*e4b17023SJohn Marino   varpool_mark_needed_node (varpool_node (ic_gcov_type_ptr_var));
107*e4b17023SJohn Marino }
108*e4b17023SJohn Marino 
109*e4b17023SJohn Marino void
gimple_init_edge_profiler(void)110*e4b17023SJohn Marino gimple_init_edge_profiler (void)
111*e4b17023SJohn Marino {
112*e4b17023SJohn Marino   tree interval_profiler_fn_type;
113*e4b17023SJohn Marino   tree pow2_profiler_fn_type;
114*e4b17023SJohn Marino   tree one_value_profiler_fn_type;
115*e4b17023SJohn Marino   tree gcov_type_ptr;
116*e4b17023SJohn Marino   tree ic_profiler_fn_type;
117*e4b17023SJohn Marino   tree average_profiler_fn_type;
118*e4b17023SJohn Marino 
119*e4b17023SJohn Marino   if (!gcov_type_node)
120*e4b17023SJohn Marino     {
121*e4b17023SJohn Marino       gcov_type_node = get_gcov_type ();
122*e4b17023SJohn Marino       gcov_type_ptr = build_pointer_type (gcov_type_node);
123*e4b17023SJohn Marino 
124*e4b17023SJohn Marino       /* void (*) (gcov_type *, gcov_type, int, unsigned)  */
125*e4b17023SJohn Marino       interval_profiler_fn_type
126*e4b17023SJohn Marino 	      = build_function_type_list (void_type_node,
127*e4b17023SJohn Marino 					  gcov_type_ptr, gcov_type_node,
128*e4b17023SJohn Marino 					  integer_type_node,
129*e4b17023SJohn Marino 					  unsigned_type_node, NULL_TREE);
130*e4b17023SJohn Marino       tree_interval_profiler_fn
131*e4b17023SJohn Marino 	      = build_fn_decl ("__gcov_interval_profiler",
132*e4b17023SJohn Marino 				     interval_profiler_fn_type);
133*e4b17023SJohn Marino       TREE_NOTHROW (tree_interval_profiler_fn) = 1;
134*e4b17023SJohn Marino       DECL_ATTRIBUTES (tree_interval_profiler_fn)
135*e4b17023SJohn Marino 	= tree_cons (get_identifier ("leaf"), NULL,
136*e4b17023SJohn Marino 		     DECL_ATTRIBUTES (tree_interval_profiler_fn));
137*e4b17023SJohn Marino 
138*e4b17023SJohn Marino       /* void (*) (gcov_type *, gcov_type)  */
139*e4b17023SJohn Marino       pow2_profiler_fn_type
140*e4b17023SJohn Marino 	      = build_function_type_list (void_type_node,
141*e4b17023SJohn Marino 					  gcov_type_ptr, gcov_type_node,
142*e4b17023SJohn Marino 					  NULL_TREE);
143*e4b17023SJohn Marino       tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler",
144*e4b17023SJohn Marino 						   pow2_profiler_fn_type);
145*e4b17023SJohn Marino       TREE_NOTHROW (tree_pow2_profiler_fn) = 1;
146*e4b17023SJohn Marino       DECL_ATTRIBUTES (tree_pow2_profiler_fn)
147*e4b17023SJohn Marino 	= tree_cons (get_identifier ("leaf"), NULL,
148*e4b17023SJohn Marino 		     DECL_ATTRIBUTES (tree_pow2_profiler_fn));
149*e4b17023SJohn Marino 
150*e4b17023SJohn Marino       /* void (*) (gcov_type *, gcov_type)  */
151*e4b17023SJohn Marino       one_value_profiler_fn_type
152*e4b17023SJohn Marino 	      = build_function_type_list (void_type_node,
153*e4b17023SJohn Marino 					  gcov_type_ptr, gcov_type_node,
154*e4b17023SJohn Marino 					  NULL_TREE);
155*e4b17023SJohn Marino       tree_one_value_profiler_fn
156*e4b17023SJohn Marino 	      = build_fn_decl ("__gcov_one_value_profiler",
157*e4b17023SJohn Marino 				     one_value_profiler_fn_type);
158*e4b17023SJohn Marino       TREE_NOTHROW (tree_one_value_profiler_fn) = 1;
159*e4b17023SJohn Marino       DECL_ATTRIBUTES (tree_one_value_profiler_fn)
160*e4b17023SJohn Marino 	= tree_cons (get_identifier ("leaf"), NULL,
161*e4b17023SJohn Marino 		     DECL_ATTRIBUTES (tree_one_value_profiler_fn));
162*e4b17023SJohn Marino 
163*e4b17023SJohn Marino       init_ic_make_global_vars ();
164*e4b17023SJohn Marino 
165*e4b17023SJohn Marino       /* void (*) (gcov_type *, gcov_type, void *, void *)  */
166*e4b17023SJohn Marino       ic_profiler_fn_type
167*e4b17023SJohn Marino 	       = build_function_type_list (void_type_node,
168*e4b17023SJohn Marino 					  gcov_type_ptr, gcov_type_node,
169*e4b17023SJohn Marino 					  ptr_void,
170*e4b17023SJohn Marino 					  ptr_void, NULL_TREE);
171*e4b17023SJohn Marino       tree_indirect_call_profiler_fn
172*e4b17023SJohn Marino 	      = build_fn_decl ("__gcov_indirect_call_profiler",
173*e4b17023SJohn Marino 				     ic_profiler_fn_type);
174*e4b17023SJohn Marino       TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1;
175*e4b17023SJohn Marino       DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)
176*e4b17023SJohn Marino 	= tree_cons (get_identifier ("leaf"), NULL,
177*e4b17023SJohn Marino 		     DECL_ATTRIBUTES (tree_indirect_call_profiler_fn));
178*e4b17023SJohn Marino 
179*e4b17023SJohn Marino       /* void (*) (gcov_type *, gcov_type)  */
180*e4b17023SJohn Marino       average_profiler_fn_type
181*e4b17023SJohn Marino 	      = build_function_type_list (void_type_node,
182*e4b17023SJohn Marino 					  gcov_type_ptr, gcov_type_node, NULL_TREE);
183*e4b17023SJohn Marino       tree_average_profiler_fn
184*e4b17023SJohn Marino 	      = build_fn_decl ("__gcov_average_profiler",
185*e4b17023SJohn Marino 				     average_profiler_fn_type);
186*e4b17023SJohn Marino       TREE_NOTHROW (tree_average_profiler_fn) = 1;
187*e4b17023SJohn Marino       DECL_ATTRIBUTES (tree_average_profiler_fn)
188*e4b17023SJohn Marino 	= tree_cons (get_identifier ("leaf"), NULL,
189*e4b17023SJohn Marino 		     DECL_ATTRIBUTES (tree_average_profiler_fn));
190*e4b17023SJohn Marino       tree_ior_profiler_fn
191*e4b17023SJohn Marino 	      = build_fn_decl ("__gcov_ior_profiler",
192*e4b17023SJohn Marino 				     average_profiler_fn_type);
193*e4b17023SJohn Marino       TREE_NOTHROW (tree_ior_profiler_fn) = 1;
194*e4b17023SJohn Marino       DECL_ATTRIBUTES (tree_ior_profiler_fn)
195*e4b17023SJohn Marino 	= tree_cons (get_identifier ("leaf"), NULL,
196*e4b17023SJohn Marino 		     DECL_ATTRIBUTES (tree_ior_profiler_fn));
197*e4b17023SJohn Marino 
198*e4b17023SJohn Marino       /* LTO streamer needs assembler names.  Because we create these decls
199*e4b17023SJohn Marino          late, we need to initialize them by hand.  */
200*e4b17023SJohn Marino       DECL_ASSEMBLER_NAME (tree_interval_profiler_fn);
201*e4b17023SJohn Marino       DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn);
202*e4b17023SJohn Marino       DECL_ASSEMBLER_NAME (tree_one_value_profiler_fn);
203*e4b17023SJohn Marino       DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn);
204*e4b17023SJohn Marino       DECL_ASSEMBLER_NAME (tree_average_profiler_fn);
205*e4b17023SJohn Marino       DECL_ASSEMBLER_NAME (tree_ior_profiler_fn);
206*e4b17023SJohn Marino     }
207*e4b17023SJohn Marino }
208*e4b17023SJohn Marino 
209*e4b17023SJohn Marino /* Output instructions as GIMPLE trees to increment the edge
210*e4b17023SJohn Marino    execution count, and insert them on E.  We rely on
211*e4b17023SJohn Marino    gsi_insert_on_edge to preserve the order.  */
212*e4b17023SJohn Marino 
213*e4b17023SJohn Marino void
gimple_gen_edge_profiler(int edgeno,edge e)214*e4b17023SJohn Marino gimple_gen_edge_profiler (int edgeno, edge e)
215*e4b17023SJohn Marino {
216*e4b17023SJohn Marino   tree ref, one;
217*e4b17023SJohn Marino   gimple stmt1, stmt2, stmt3;
218*e4b17023SJohn Marino 
219*e4b17023SJohn Marino   /* We share one temporary variable declaration per function.  This
220*e4b17023SJohn Marino      gets re-set in tree_profiling.  */
221*e4b17023SJohn Marino   if (gcov_type_tmp_var == NULL_TREE)
222*e4b17023SJohn Marino     gcov_type_tmp_var = create_tmp_reg (gcov_type_node, "PROF_edge_counter");
223*e4b17023SJohn Marino   ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
224*e4b17023SJohn Marino   one = build_int_cst (gcov_type_node, 1);
225*e4b17023SJohn Marino   stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
226*e4b17023SJohn Marino   gimple_assign_set_lhs (stmt1, make_ssa_name (gcov_type_tmp_var, stmt1));
227*e4b17023SJohn Marino   find_referenced_vars_in (stmt1);
228*e4b17023SJohn Marino   stmt2 = gimple_build_assign_with_ops (PLUS_EXPR, gcov_type_tmp_var,
229*e4b17023SJohn Marino 					gimple_assign_lhs (stmt1), one);
230*e4b17023SJohn Marino   gimple_assign_set_lhs (stmt2, make_ssa_name (gcov_type_tmp_var, stmt2));
231*e4b17023SJohn Marino   stmt3 = gimple_build_assign (unshare_expr (ref), gimple_assign_lhs (stmt2));
232*e4b17023SJohn Marino   gsi_insert_on_edge (e, stmt1);
233*e4b17023SJohn Marino   gsi_insert_on_edge (e, stmt2);
234*e4b17023SJohn Marino   gsi_insert_on_edge (e, stmt3);
235*e4b17023SJohn Marino }
236*e4b17023SJohn Marino 
237*e4b17023SJohn Marino /* Emits code to get VALUE to instrument at GSI, and returns the
238*e4b17023SJohn Marino    variable containing the value.  */
239*e4b17023SJohn Marino 
240*e4b17023SJohn Marino static tree
prepare_instrumented_value(gimple_stmt_iterator * gsi,histogram_value value)241*e4b17023SJohn Marino prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value)
242*e4b17023SJohn Marino {
243*e4b17023SJohn Marino   tree val = value->hvalue.value;
244*e4b17023SJohn Marino   if (POINTER_TYPE_P (TREE_TYPE (val)))
245*e4b17023SJohn Marino     val = fold_convert (build_nonstandard_integer_type
246*e4b17023SJohn Marino 			  (TYPE_PRECISION (TREE_TYPE (val)), 1), val);
247*e4b17023SJohn Marino   return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val),
248*e4b17023SJohn Marino 				   true, NULL_TREE, true, GSI_SAME_STMT);
249*e4b17023SJohn Marino }
250*e4b17023SJohn Marino 
251*e4b17023SJohn Marino /* Output instructions as GIMPLE trees to increment the interval histogram
252*e4b17023SJohn Marino    counter.  VALUE is the expression whose value is profiled.  TAG is the
253*e4b17023SJohn Marino    tag of the section for counters, BASE is offset of the counter position.  */
254*e4b17023SJohn Marino 
255*e4b17023SJohn Marino void
gimple_gen_interval_profiler(histogram_value value,unsigned tag,unsigned base)256*e4b17023SJohn Marino gimple_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
257*e4b17023SJohn Marino {
258*e4b17023SJohn Marino   gimple stmt = value->hvalue.stmt;
259*e4b17023SJohn Marino   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
260*e4b17023SJohn Marino   tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
261*e4b17023SJohn Marino   gimple call;
262*e4b17023SJohn Marino   tree val;
263*e4b17023SJohn Marino   tree start = build_int_cst_type (integer_type_node,
264*e4b17023SJohn Marino 				   value->hdata.intvl.int_start);
265*e4b17023SJohn Marino   tree steps = build_int_cst_type (unsigned_type_node,
266*e4b17023SJohn Marino 				   value->hdata.intvl.steps);
267*e4b17023SJohn Marino 
268*e4b17023SJohn Marino   ref_ptr = force_gimple_operand_gsi (&gsi,
269*e4b17023SJohn Marino 				      build_addr (ref, current_function_decl),
270*e4b17023SJohn Marino 				      true, NULL_TREE, true, GSI_SAME_STMT);
271*e4b17023SJohn Marino   val = prepare_instrumented_value (&gsi, value);
272*e4b17023SJohn Marino   call = gimple_build_call (tree_interval_profiler_fn, 4,
273*e4b17023SJohn Marino 			    ref_ptr, val, start, steps);
274*e4b17023SJohn Marino   find_referenced_vars_in (call);
275*e4b17023SJohn Marino   gsi_insert_before (&gsi, call, GSI_NEW_STMT);
276*e4b17023SJohn Marino }
277*e4b17023SJohn Marino 
278*e4b17023SJohn Marino /* Output instructions as GIMPLE trees to increment the power of two histogram
279*e4b17023SJohn Marino    counter.  VALUE is the expression whose value is profiled.  TAG is the tag
280*e4b17023SJohn Marino    of the section for counters, BASE is offset of the counter position.  */
281*e4b17023SJohn Marino 
282*e4b17023SJohn Marino void
gimple_gen_pow2_profiler(histogram_value value,unsigned tag,unsigned base)283*e4b17023SJohn Marino gimple_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
284*e4b17023SJohn Marino {
285*e4b17023SJohn Marino   gimple stmt = value->hvalue.stmt;
286*e4b17023SJohn Marino   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
287*e4b17023SJohn Marino   tree ref_ptr = tree_coverage_counter_addr (tag, base);
288*e4b17023SJohn Marino   gimple call;
289*e4b17023SJohn Marino   tree val;
290*e4b17023SJohn Marino 
291*e4b17023SJohn Marino   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
292*e4b17023SJohn Marino 				      true, NULL_TREE, true, GSI_SAME_STMT);
293*e4b17023SJohn Marino   val = prepare_instrumented_value (&gsi, value);
294*e4b17023SJohn Marino   call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val);
295*e4b17023SJohn Marino   find_referenced_vars_in (call);
296*e4b17023SJohn Marino   gsi_insert_before (&gsi, call, GSI_NEW_STMT);
297*e4b17023SJohn Marino }
298*e4b17023SJohn Marino 
299*e4b17023SJohn Marino /* Output instructions as GIMPLE trees for code to find the most common value.
300*e4b17023SJohn Marino    VALUE is the expression whose value is profiled.  TAG is the tag of the
301*e4b17023SJohn Marino    section for counters, BASE is offset of the counter position.  */
302*e4b17023SJohn Marino 
303*e4b17023SJohn Marino void
gimple_gen_one_value_profiler(histogram_value value,unsigned tag,unsigned base)304*e4b17023SJohn Marino gimple_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
305*e4b17023SJohn Marino {
306*e4b17023SJohn Marino   gimple stmt = value->hvalue.stmt;
307*e4b17023SJohn Marino   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
308*e4b17023SJohn Marino   tree ref_ptr = tree_coverage_counter_addr (tag, base);
309*e4b17023SJohn Marino   gimple call;
310*e4b17023SJohn Marino   tree val;
311*e4b17023SJohn Marino 
312*e4b17023SJohn Marino   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
313*e4b17023SJohn Marino 				      true, NULL_TREE, true, GSI_SAME_STMT);
314*e4b17023SJohn Marino   val = prepare_instrumented_value (&gsi, value);
315*e4b17023SJohn Marino   call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val);
316*e4b17023SJohn Marino   find_referenced_vars_in (call);
317*e4b17023SJohn Marino   gsi_insert_before (&gsi, call, GSI_NEW_STMT);
318*e4b17023SJohn Marino }
319*e4b17023SJohn Marino 
320*e4b17023SJohn Marino 
321*e4b17023SJohn Marino /* Output instructions as GIMPLE trees for code to find the most
322*e4b17023SJohn Marino    common called function in indirect call.
323*e4b17023SJohn Marino    VALUE is the call expression whose indirect callee is profiled.
324*e4b17023SJohn Marino    TAG is the tag of the section for counters, BASE is offset of the
325*e4b17023SJohn Marino    counter position.  */
326*e4b17023SJohn Marino 
327*e4b17023SJohn Marino void
gimple_gen_ic_profiler(histogram_value value,unsigned tag,unsigned base)328*e4b17023SJohn Marino gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
329*e4b17023SJohn Marino {
330*e4b17023SJohn Marino   tree tmp1;
331*e4b17023SJohn Marino   gimple stmt1, stmt2, stmt3;
332*e4b17023SJohn Marino   gimple stmt = value->hvalue.stmt;
333*e4b17023SJohn Marino   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
334*e4b17023SJohn Marino   tree ref_ptr = tree_coverage_counter_addr (tag, base);
335*e4b17023SJohn Marino 
336*e4b17023SJohn Marino   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
337*e4b17023SJohn Marino 				      true, NULL_TREE, true, GSI_SAME_STMT);
338*e4b17023SJohn Marino 
339*e4b17023SJohn Marino   /* Insert code:
340*e4b17023SJohn Marino 
341*e4b17023SJohn Marino     __gcov_indirect_call_counters = get_relevant_counter_ptr ();
342*e4b17023SJohn Marino     __gcov_indirect_call_callee = (void *) indirect call argument;
343*e4b17023SJohn Marino    */
344*e4b17023SJohn Marino 
345*e4b17023SJohn Marino   tmp1 = create_tmp_reg (ptr_void, "PROF");
346*e4b17023SJohn Marino   stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr);
347*e4b17023SJohn Marino   find_referenced_vars_in (stmt1);
348*e4b17023SJohn Marino   stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
349*e4b17023SJohn Marino   gimple_assign_set_lhs (stmt2, make_ssa_name (tmp1, stmt2));
350*e4b17023SJohn Marino   find_referenced_vars_in (stmt2);
351*e4b17023SJohn Marino   stmt3 = gimple_build_assign (ic_void_ptr_var, gimple_assign_lhs (stmt2));
352*e4b17023SJohn Marino   add_referenced_var (ic_void_ptr_var);
353*e4b17023SJohn Marino 
354*e4b17023SJohn Marino   gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
355*e4b17023SJohn Marino   gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
356*e4b17023SJohn Marino   gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
357*e4b17023SJohn Marino }
358*e4b17023SJohn Marino 
359*e4b17023SJohn Marino 
360*e4b17023SJohn Marino /* Output instructions as GIMPLE trees for code to find the most
361*e4b17023SJohn Marino    common called function in indirect call. Insert instructions at the
362*e4b17023SJohn Marino    beginning of every possible called function.
363*e4b17023SJohn Marino   */
364*e4b17023SJohn Marino 
365*e4b17023SJohn Marino void
gimple_gen_ic_func_profiler(void)366*e4b17023SJohn Marino gimple_gen_ic_func_profiler (void)
367*e4b17023SJohn Marino {
368*e4b17023SJohn Marino   struct cgraph_node * c_node = cgraph_get_node (current_function_decl);
369*e4b17023SJohn Marino   gimple_stmt_iterator gsi;
370*e4b17023SJohn Marino   gimple stmt1, stmt2;
371*e4b17023SJohn Marino   tree tree_uid, cur_func, counter_ptr, ptr_var, void0;
372*e4b17023SJohn Marino 
373*e4b17023SJohn Marino   if (cgraph_only_called_directly_p (c_node))
374*e4b17023SJohn Marino     return;
375*e4b17023SJohn Marino 
376*e4b17023SJohn Marino   gimple_init_edge_profiler ();
377*e4b17023SJohn Marino 
378*e4b17023SJohn Marino   gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
379*e4b17023SJohn Marino 
380*e4b17023SJohn Marino   cur_func = force_gimple_operand_gsi (&gsi,
381*e4b17023SJohn Marino 				       build_addr (current_function_decl,
382*e4b17023SJohn Marino 						   current_function_decl),
383*e4b17023SJohn Marino 				       true, NULL_TREE,
384*e4b17023SJohn Marino 				       true, GSI_SAME_STMT);
385*e4b17023SJohn Marino   counter_ptr = force_gimple_operand_gsi (&gsi, ic_gcov_type_ptr_var,
386*e4b17023SJohn Marino 					  true, NULL_TREE, true,
387*e4b17023SJohn Marino 					  GSI_SAME_STMT);
388*e4b17023SJohn Marino   add_referenced_var (ic_gcov_type_ptr_var);
389*e4b17023SJohn Marino   ptr_var = force_gimple_operand_gsi (&gsi, ic_void_ptr_var,
390*e4b17023SJohn Marino 				      true, NULL_TREE, true,
391*e4b17023SJohn Marino 				      GSI_SAME_STMT);
392*e4b17023SJohn Marino   add_referenced_var (ic_void_ptr_var);
393*e4b17023SJohn Marino   tree_uid = build_int_cst (gcov_type_node, current_function_funcdef_no);
394*e4b17023SJohn Marino   stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 4,
395*e4b17023SJohn Marino 			     counter_ptr, tree_uid, cur_func, ptr_var);
396*e4b17023SJohn Marino   gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
397*e4b17023SJohn Marino 
398*e4b17023SJohn Marino   /* Set __gcov_indirect_call_callee to 0,
399*e4b17023SJohn Marino      so that calls from other modules won't get misattributed
400*e4b17023SJohn Marino      to the last caller of the current callee. */
401*e4b17023SJohn Marino   void0 = build_int_cst (build_pointer_type (void_type_node), 0);
402*e4b17023SJohn Marino   stmt2 = gimple_build_assign (ic_void_ptr_var, void0);
403*e4b17023SJohn Marino   gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
404*e4b17023SJohn Marino }
405*e4b17023SJohn Marino 
406*e4b17023SJohn Marino /* Output instructions as GIMPLE trees for code to find the most common value
407*e4b17023SJohn Marino    of a difference between two evaluations of an expression.
408*e4b17023SJohn Marino    VALUE is the expression whose value is profiled.  TAG is the tag of the
409*e4b17023SJohn Marino    section for counters, BASE is offset of the counter position.  */
410*e4b17023SJohn Marino 
411*e4b17023SJohn Marino void
gimple_gen_const_delta_profiler(histogram_value value ATTRIBUTE_UNUSED,unsigned tag ATTRIBUTE_UNUSED,unsigned base ATTRIBUTE_UNUSED)412*e4b17023SJohn Marino gimple_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED,
413*e4b17023SJohn Marino 			       unsigned tag ATTRIBUTE_UNUSED,
414*e4b17023SJohn Marino 			       unsigned base ATTRIBUTE_UNUSED)
415*e4b17023SJohn Marino {
416*e4b17023SJohn Marino   /* FIXME implement this.  */
417*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
418*e4b17023SJohn Marino   internal_error ("unimplemented functionality");
419*e4b17023SJohn Marino #endif
420*e4b17023SJohn Marino   gcc_unreachable ();
421*e4b17023SJohn Marino }
422*e4b17023SJohn Marino 
423*e4b17023SJohn Marino /* Output instructions as GIMPLE trees to increment the average histogram
424*e4b17023SJohn Marino    counter.  VALUE is the expression whose value is profiled.  TAG is the
425*e4b17023SJohn Marino    tag of the section for counters, BASE is offset of the counter position.  */
426*e4b17023SJohn Marino 
427*e4b17023SJohn Marino void
gimple_gen_average_profiler(histogram_value value,unsigned tag,unsigned base)428*e4b17023SJohn Marino gimple_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
429*e4b17023SJohn Marino {
430*e4b17023SJohn Marino   gimple stmt = value->hvalue.stmt;
431*e4b17023SJohn Marino   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
432*e4b17023SJohn Marino   tree ref_ptr = tree_coverage_counter_addr (tag, base);
433*e4b17023SJohn Marino   gimple call;
434*e4b17023SJohn Marino   tree val;
435*e4b17023SJohn Marino 
436*e4b17023SJohn Marino   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
437*e4b17023SJohn Marino 				      true, NULL_TREE,
438*e4b17023SJohn Marino 				      true, GSI_SAME_STMT);
439*e4b17023SJohn Marino   val = prepare_instrumented_value (&gsi, value);
440*e4b17023SJohn Marino   call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
441*e4b17023SJohn Marino   find_referenced_vars_in (call);
442*e4b17023SJohn Marino   gsi_insert_before (&gsi, call, GSI_NEW_STMT);
443*e4b17023SJohn Marino }
444*e4b17023SJohn Marino 
445*e4b17023SJohn Marino /* Output instructions as GIMPLE trees to increment the ior histogram
446*e4b17023SJohn Marino    counter.  VALUE is the expression whose value is profiled.  TAG is the
447*e4b17023SJohn Marino    tag of the section for counters, BASE is offset of the counter position.  */
448*e4b17023SJohn Marino 
449*e4b17023SJohn Marino void
gimple_gen_ior_profiler(histogram_value value,unsigned tag,unsigned base)450*e4b17023SJohn Marino gimple_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
451*e4b17023SJohn Marino {
452*e4b17023SJohn Marino   gimple stmt = value->hvalue.stmt;
453*e4b17023SJohn Marino   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
454*e4b17023SJohn Marino   tree ref_ptr = tree_coverage_counter_addr (tag, base);
455*e4b17023SJohn Marino   gimple call;
456*e4b17023SJohn Marino   tree val;
457*e4b17023SJohn Marino 
458*e4b17023SJohn Marino   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
459*e4b17023SJohn Marino 				      true, NULL_TREE, true, GSI_SAME_STMT);
460*e4b17023SJohn Marino   val = prepare_instrumented_value (&gsi, value);
461*e4b17023SJohn Marino   call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
462*e4b17023SJohn Marino   find_referenced_vars_in (call);
463*e4b17023SJohn Marino   gsi_insert_before (&gsi, call, GSI_NEW_STMT);
464*e4b17023SJohn Marino }
465*e4b17023SJohn Marino 
466*e4b17023SJohn Marino /* Profile all functions in the callgraph.  */
467*e4b17023SJohn Marino 
468*e4b17023SJohn Marino static unsigned int
tree_profiling(void)469*e4b17023SJohn Marino tree_profiling (void)
470*e4b17023SJohn Marino {
471*e4b17023SJohn Marino   struct cgraph_node *node;
472*e4b17023SJohn Marino 
473*e4b17023SJohn Marino   /* Don't profile functions produced at destruction time, particularly
474*e4b17023SJohn Marino      the gcov datastructure initializer.  Don't profile if it has been
475*e4b17023SJohn Marino      already instrumented either (when OpenMP expansion creates
476*e4b17023SJohn Marino      child function from already instrumented body).  */
477*e4b17023SJohn Marino   if (cgraph_state == CGRAPH_STATE_FINISHED)
478*e4b17023SJohn Marino     return 0;
479*e4b17023SJohn Marino 
480*e4b17023SJohn Marino   init_node_map();
481*e4b17023SJohn Marino 
482*e4b17023SJohn Marino   for (node = cgraph_nodes; node; node = node->next)
483*e4b17023SJohn Marino     {
484*e4b17023SJohn Marino       if (!node->analyzed
485*e4b17023SJohn Marino 	  || !gimple_has_body_p (node->decl))
486*e4b17023SJohn Marino 	continue;
487*e4b17023SJohn Marino 
488*e4b17023SJohn Marino       /* Don't profile functions produced for builtin stuff.  */
489*e4b17023SJohn Marino       if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION
490*e4b17023SJohn Marino 	  || DECL_STRUCT_FUNCTION (node->decl)->after_tree_profile)
491*e4b17023SJohn Marino 	continue;
492*e4b17023SJohn Marino 
493*e4b17023SJohn Marino       push_cfun (DECL_STRUCT_FUNCTION (node->decl));
494*e4b17023SJohn Marino       current_function_decl = node->decl;
495*e4b17023SJohn Marino 
496*e4b17023SJohn Marino       /* Re-set global shared temporary variable for edge-counters.  */
497*e4b17023SJohn Marino       gcov_type_tmp_var = NULL_TREE;
498*e4b17023SJohn Marino 
499*e4b17023SJohn Marino       /* Local pure-const may imply need to fixup the cfg.  */
500*e4b17023SJohn Marino       if (execute_fixup_cfg () & TODO_cleanup_cfg)
501*e4b17023SJohn Marino 	cleanup_tree_cfg ();
502*e4b17023SJohn Marino       branch_prob ();
503*e4b17023SJohn Marino 
504*e4b17023SJohn Marino       if (! flag_branch_probabilities
505*e4b17023SJohn Marino 	  && flag_profile_values)
506*e4b17023SJohn Marino 	gimple_gen_ic_func_profiler ();
507*e4b17023SJohn Marino 
508*e4b17023SJohn Marino       if (flag_branch_probabilities
509*e4b17023SJohn Marino 	  && flag_profile_values
510*e4b17023SJohn Marino 	  && flag_value_profile_transformations)
511*e4b17023SJohn Marino 	gimple_value_profile_transformations ();
512*e4b17023SJohn Marino 
513*e4b17023SJohn Marino       /* The above could hose dominator info.  Currently there is
514*e4b17023SJohn Marino 	 none coming in, this is a safety valve.  It should be
515*e4b17023SJohn Marino 	 easy to adjust it, if and when there is some.  */
516*e4b17023SJohn Marino       free_dominance_info (CDI_DOMINATORS);
517*e4b17023SJohn Marino       free_dominance_info (CDI_POST_DOMINATORS);
518*e4b17023SJohn Marino 
519*e4b17023SJohn Marino       current_function_decl = NULL;
520*e4b17023SJohn Marino       pop_cfun ();
521*e4b17023SJohn Marino     }
522*e4b17023SJohn Marino 
523*e4b17023SJohn Marino   /* Drop pure/const flags from instrumented functions.  */
524*e4b17023SJohn Marino   for (node = cgraph_nodes; node; node = node->next)
525*e4b17023SJohn Marino     {
526*e4b17023SJohn Marino       if (!node->analyzed
527*e4b17023SJohn Marino 	  || !gimple_has_body_p (node->decl)
528*e4b17023SJohn Marino 	  || !(!node->clone_of || node->decl != node->clone_of->decl))
529*e4b17023SJohn Marino 	continue;
530*e4b17023SJohn Marino 
531*e4b17023SJohn Marino       /* Don't profile functions produced for builtin stuff.  */
532*e4b17023SJohn Marino       if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION
533*e4b17023SJohn Marino 	  || DECL_STRUCT_FUNCTION (node->decl)->after_tree_profile)
534*e4b17023SJohn Marino 	continue;
535*e4b17023SJohn Marino 
536*e4b17023SJohn Marino       cgraph_set_const_flag (node, false, false);
537*e4b17023SJohn Marino       cgraph_set_pure_flag (node, false, false);
538*e4b17023SJohn Marino     }
539*e4b17023SJohn Marino 
540*e4b17023SJohn Marino   /* Update call statements and rebuild the cgraph.  */
541*e4b17023SJohn Marino   for (node = cgraph_nodes; node; node = node->next)
542*e4b17023SJohn Marino     {
543*e4b17023SJohn Marino       basic_block bb;
544*e4b17023SJohn Marino 
545*e4b17023SJohn Marino       if (!node->analyzed
546*e4b17023SJohn Marino 	  || !gimple_has_body_p (node->decl)
547*e4b17023SJohn Marino 	  || !(!node->clone_of || node->decl != node->clone_of->decl))
548*e4b17023SJohn Marino 	continue;
549*e4b17023SJohn Marino 
550*e4b17023SJohn Marino       /* Don't profile functions produced for builtin stuff.  */
551*e4b17023SJohn Marino       if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION
552*e4b17023SJohn Marino 	  || DECL_STRUCT_FUNCTION (node->decl)->after_tree_profile)
553*e4b17023SJohn Marino 	continue;
554*e4b17023SJohn Marino 
555*e4b17023SJohn Marino       push_cfun (DECL_STRUCT_FUNCTION (node->decl));
556*e4b17023SJohn Marino       current_function_decl = node->decl;
557*e4b17023SJohn Marino 
558*e4b17023SJohn Marino       FOR_EACH_BB (bb)
559*e4b17023SJohn Marino 	{
560*e4b17023SJohn Marino 	  gimple_stmt_iterator gsi;
561*e4b17023SJohn Marino 	  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
562*e4b17023SJohn Marino 	    {
563*e4b17023SJohn Marino 	      gimple stmt = gsi_stmt (gsi);
564*e4b17023SJohn Marino 	      if (is_gimple_call (stmt))
565*e4b17023SJohn Marino 		update_stmt (stmt);
566*e4b17023SJohn Marino 	    }
567*e4b17023SJohn Marino 	}
568*e4b17023SJohn Marino 
569*e4b17023SJohn Marino       cfun->after_tree_profile = 1;
570*e4b17023SJohn Marino       update_ssa (TODO_update_ssa);
571*e4b17023SJohn Marino 
572*e4b17023SJohn Marino       rebuild_cgraph_edges ();
573*e4b17023SJohn Marino 
574*e4b17023SJohn Marino       current_function_decl = NULL;
575*e4b17023SJohn Marino       pop_cfun ();
576*e4b17023SJohn Marino     }
577*e4b17023SJohn Marino 
578*e4b17023SJohn Marino   del_node_map();
579*e4b17023SJohn Marino   return 0;
580*e4b17023SJohn Marino }
581*e4b17023SJohn Marino 
582*e4b17023SJohn Marino /* When profile instrumentation, use or test coverage shall be performed.  */
583*e4b17023SJohn Marino 
584*e4b17023SJohn Marino static bool
gate_tree_profile_ipa(void)585*e4b17023SJohn Marino gate_tree_profile_ipa (void)
586*e4b17023SJohn Marino {
587*e4b17023SJohn Marino   return (!in_lto_p
588*e4b17023SJohn Marino 	  && (flag_branch_probabilities || flag_test_coverage
589*e4b17023SJohn Marino 	      || profile_arc_flag));
590*e4b17023SJohn Marino }
591*e4b17023SJohn Marino 
592*e4b17023SJohn Marino struct simple_ipa_opt_pass pass_ipa_tree_profile =
593*e4b17023SJohn Marino {
594*e4b17023SJohn Marino  {
595*e4b17023SJohn Marino   SIMPLE_IPA_PASS,
596*e4b17023SJohn Marino   "profile",  		               /* name */
597*e4b17023SJohn Marino   gate_tree_profile_ipa,               /* gate */
598*e4b17023SJohn Marino   tree_profiling,                      /* execute */
599*e4b17023SJohn Marino   NULL,                                /* sub */
600*e4b17023SJohn Marino   NULL,                                /* next */
601*e4b17023SJohn Marino   0,                                   /* static_pass_number */
602*e4b17023SJohn Marino   TV_IPA_PROFILE,                      /* tv_id */
603*e4b17023SJohn Marino   0,                                   /* properties_required */
604*e4b17023SJohn Marino   0,                                   /* properties_provided */
605*e4b17023SJohn Marino   0,                                   /* properties_destroyed */
606*e4b17023SJohn Marino   0,                                   /* todo_flags_start */
607*e4b17023SJohn Marino   0                                    /* todo_flags_finish */
608*e4b17023SJohn Marino  }
609*e4b17023SJohn Marino };
610*e4b17023SJohn Marino 
611*e4b17023SJohn Marino #include "gt-tree-profile.h"
612