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