PR target/4198
[official-gcc.git] / gcc / tree-profile.c
blobb588f2d12726c28d0415a396713968903b6911ed
1 /* Calculate branch probabilities, and basic block execution counts.
2 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
3 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4 Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
5 based on some ideas from Dain Samples of UC Berkeley.
6 Further mangling by Bob Manson, Cygnus Support.
7 Converted to use trees by Dale Johannesen, Apple Computer.
9 This file is part of GCC.
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 2, or (at your option) any later
14 version.
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 for more details.
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING. If not, write to the Free
23 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
24 02111-1307, USA. */
26 /* Generate basic block profile instrumentation and auxiliary files.
27 Tree-based version. See profile.c for overview. */
29 #include "config.h"
30 #include "system.h"
31 #include "coretypes.h"
32 #include "tm.h"
33 #include "rtl.h"
34 #include "flags.h"
35 #include "output.h"
36 #include "regs.h"
37 #include "expr.h"
38 #include "function.h"
39 #include "toplev.h"
40 #include "coverage.h"
41 #include "tree.h"
42 #include "tree-flow.h"
43 #include "tree-dump.h"
44 #include "tree-pass.h"
45 #include "timevar.h"
46 #include "value-prof.h"
50 /* Do initialization work for the edge profiler. */
52 static void
53 tree_init_edge_profiler (void)
57 /* Output instructions as GIMPLE trees to increment the edge
58 execution count, and insert them on E. We rely on
59 bsi_insert_on_edge to preserve the order. */
61 static void
62 tree_gen_edge_profiler (int edgeno, edge e)
64 tree tmp1 = create_tmp_var (GCOV_TYPE_NODE, "PROF");
65 tree tmp2 = create_tmp_var (GCOV_TYPE_NODE, "PROF");
66 tree ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
67 tree stmt1 = build (MODIFY_EXPR, GCOV_TYPE_NODE, tmp1, ref);
68 tree stmt2 = build (MODIFY_EXPR, GCOV_TYPE_NODE, tmp2,
69 build (PLUS_EXPR, GCOV_TYPE_NODE,
70 tmp1, integer_one_node));
71 tree stmt3 = build (MODIFY_EXPR, GCOV_TYPE_NODE, ref, tmp2);
72 bsi_insert_on_edge (e, stmt1);
73 bsi_insert_on_edge (e, stmt2);
74 bsi_insert_on_edge (e, stmt3);
77 /* Output instructions as GIMPLE trees to increment the interval histogram
78 counter. VALUE is the expression whose value is profiled. TAG is the
79 tag of the section for counters, BASE is offset of the counter position. */
81 static void
82 tree_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
84 tree op, op1, op2, op1copy, op2copy;
85 tree tmp1, tmp2, tmp3, val, index;
86 tree label_decl2, label_decl3, label_decl4, label_decl5, label_decl6;
87 edge e12, e23, e34, e45, e56;
88 tree label2, label3, label4, label5, label6;
89 tree stmt1, stmt2, stmt3, stmt4;
90 /* Initializations are to prevent bogus uninitialized warnings. */
91 tree bb1end = NULL_TREE, bb2end = NULL_TREE, bb3end = NULL_TREE;
92 tree bb4end = NULL_TREE, bb5end = NULL_TREE;
93 tree ref = tree_coverage_counter_ref (tag, base), ref2;
94 basic_block bb2, bb3, bb4, bb5, bb6;
95 tree stmt = value->hvalue.tree.stmt;
96 block_stmt_iterator bsi = bsi_for_stmt (stmt);
97 basic_block bb = bb_for_stmt (stmt);
98 tree optype;
100 op = stmt;
101 if (TREE_CODE (stmt) == RETURN_EXPR
102 && TREE_OPERAND (stmt, 0)
103 && TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR)
104 op = TREE_OPERAND (stmt, 0);
105 /* op == MODIFY_EXPR */
106 op = TREE_OPERAND (op, 1);
107 /* op == TRUNC_DIV or TRUNC_MOD */
108 op1 = TREE_OPERAND (op, 0);
109 op2 = TREE_OPERAND (op, 1);
110 optype = TREE_TYPE (op);
112 /* Blocks:
113 Original = 1
114 For 2nd compare = 2
115 Normal case, neither more nor less = 3
116 More = 4
117 Less = 5
118 End = 6 */
119 label_decl2 = create_artificial_label ();
120 label_decl3 = create_artificial_label ();
121 label_decl4 = create_artificial_label ();
122 label_decl5 = create_artificial_label ();
123 label_decl6 = create_artificial_label ();
125 /* Do not evaluate op1 or op2 more than once. Probably
126 volatile loads are the only things that could cause
127 a problem, but this is harmless in any case. */
128 op1copy = create_tmp_var (optype, "PROF");
129 op2copy = create_tmp_var (optype, "PROF");
130 stmt1 = build2 (MODIFY_EXPR, optype, op1copy, op1);
131 stmt2 = build2 (MODIFY_EXPR, optype, op2copy, op2);
132 TREE_OPERAND (op, 0) = op1copy;
133 TREE_OPERAND (op, 1) = op2copy;
135 val = create_tmp_var (optype, "PROF");
136 stmt3 = build2 (MODIFY_EXPR, optype, val,
137 build2 (TRUNC_DIV_EXPR, optype, op1copy, op2copy));
138 stmt4 = build2 (MODIFY_EXPR, optype, val,
139 build2 (MINUS_EXPR, optype, val,
140 build_int_cst (optype, value->hdata.intvl.int_start)));
141 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
142 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
143 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
144 bsi_insert_before (&bsi, stmt4, BSI_SAME_STMT);
146 index = create_tmp_var (GCOV_TYPE_NODE, "PROF");
148 /* Check for too big. */
149 stmt1 = build3 (COND_EXPR, void_type_node,
150 build2 (GE_EXPR, boolean_type_node, val,
151 build_int_cst (optype, value->hdata.intvl.steps)),
152 build1 (GOTO_EXPR, void_type_node, label_decl4),
153 build1 (GOTO_EXPR, void_type_node, label_decl2));
154 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
155 bb1end = stmt1;
157 /* Check for too small. */
158 label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
159 bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
160 stmt1 = build3 (COND_EXPR, void_type_node,
161 build2 (LT_EXPR, boolean_type_node, val, integer_zero_node),
162 build1 (GOTO_EXPR, void_type_node, label_decl5),
163 build1 (GOTO_EXPR, void_type_node, label_decl3));
164 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
165 bb2end = stmt1;
167 /* Normal case, within range. */
168 label3 = build1 (LABEL_EXPR, void_type_node, label_decl3);
169 bsi_insert_before (&bsi, label3, BSI_SAME_STMT);
170 stmt1 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, index,
171 build1 (NOP_EXPR, GCOV_TYPE_NODE, val));
172 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
173 bb3end = stmt1;
175 /* Too big */
176 label4 = build1 (LABEL_EXPR, void_type_node, label_decl4);
177 stmt1 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, index,
178 build_int_cst (GCOV_TYPE_NODE, value->hdata.intvl.steps));
179 bsi_insert_before (&bsi, label4, BSI_SAME_STMT);
180 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
181 bb4end = stmt1;
183 /* Too small */
184 label5 = build1 (LABEL_EXPR, void_type_node, label_decl5);
185 stmt1 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, index,
186 build_int_cst (GCOV_TYPE_NODE, value->hdata.intvl.steps + 1));
187 bsi_insert_before (&bsi, label5, BSI_SAME_STMT);
188 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
189 bb5end = stmt1;
191 /* Increment appropriate counter. */
192 label6 = build1 (LABEL_EXPR, void_type_node, label_decl6);
193 bsi_insert_before (&bsi, label6, BSI_SAME_STMT);
195 tmp1 = create_tmp_var (GCOV_TYPE_NODE, "PROF");
196 tmp2 = create_tmp_var (GCOV_TYPE_NODE, "PROF");
197 tmp3 = create_tmp_var (GCOV_TYPE_NODE, "PROF");
198 stmt1 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, tmp1,
199 build2 (PLUS_EXPR, GCOV_TYPE_NODE, index,
200 TREE_OPERAND (ref, 1)));
201 TREE_OPERAND (ref, 1) = tmp1;
202 /* Make a copy to avoid sharing complaints. */
203 ref2 = build4 (ARRAY_REF, TREE_TYPE (ref), TREE_OPERAND (ref, 0),
204 TREE_OPERAND (ref, 1), TREE_OPERAND (ref, 2),
205 TREE_OPERAND (ref, 3));
207 stmt2 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, tmp2, ref);
208 stmt3 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, tmp3,
209 build2 (PLUS_EXPR, GCOV_TYPE_NODE, tmp2, integer_one_node));
210 stmt4 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, ref2, tmp3);
211 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
212 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
213 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
214 bsi_insert_before (&bsi, stmt4, BSI_SAME_STMT);
216 /* Now fix up the CFG. */
217 /* 1->2,4; 2->3,5; 3->6; 4->6; 5->6 */
218 e12 = split_block (bb, bb1end);
219 bb2 = e12->dest;
220 e23 = split_block (bb2, bb2end);
221 bb3 = e23->dest;
222 e34 = split_block (bb3, bb3end);
223 bb4 = e34->dest;
224 e45 = split_block (bb4, bb4end);
225 bb5 = e45->dest;
226 e56 = split_block (bb5, bb5end);
227 bb6 = e56->dest;
229 e12->flags &= ~EDGE_FALLTHRU;
230 e12->flags |= EDGE_FALSE_VALUE;
231 make_edge (bb, bb4, EDGE_TRUE_VALUE);
232 e23->flags &= ~EDGE_FALLTHRU;
233 e23->flags |= EDGE_FALSE_VALUE;
234 make_edge (bb2, bb5, EDGE_TRUE_VALUE);
235 remove_edge (e34);
236 make_edge (bb3, bb6, EDGE_FALLTHRU);
237 remove_edge (e45);
238 make_edge (bb4, bb6, EDGE_FALLTHRU);
241 /* Output instructions as GIMPLE trees to increment the power of two histogram
242 counter. VALUE is the expression whose value is profiled. TAG is the tag
243 of the section for counters, BASE is offset of the counter position. */
245 static void
246 tree_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
248 tree op;
249 tree tmp1, tmp2, tmp3;
250 tree index, denom;
251 tree label_decl1 = create_artificial_label ();
252 tree label_decl2 = create_artificial_label ();
253 tree label_decl3 = create_artificial_label ();
254 tree label1, label2, label3;
255 tree stmt1, stmt2, stmt3, stmt4;
256 tree bb1end, bb2end, bb3end;
257 tree ref = tree_coverage_counter_ref (tag, base), ref2;
258 basic_block bb2, bb3, bb4;
259 tree stmt = value->hvalue.tree.stmt;
260 block_stmt_iterator bsi = bsi_for_stmt (stmt);
261 basic_block bb = bb_for_stmt (stmt);
262 tree optype, optypesigned, optypeunsigned;
264 op = stmt;
265 if (TREE_CODE (stmt) == RETURN_EXPR
266 && TREE_OPERAND (stmt, 0)
267 && TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR)
268 op = TREE_OPERAND (stmt, 0);
269 /* op == MODIFY_EXPR */
270 op = TREE_OPERAND (op, 1);
271 /* op == TRUNC_DIV or TRUNC_MOD */
272 op = TREE_OPERAND (op, 1);
273 /* op == denominator */
274 optype = TREE_TYPE (op);
275 if (TYPE_UNSIGNED (optype))
277 /* Right shift must be unsigned. */
278 optypeunsigned = optype;
279 optypesigned = build_distinct_type_copy (optype);
280 TYPE_UNSIGNED (optypesigned) = false;
282 else
284 /* Compare to zero must be signed. */
285 optypesigned = optype;
286 optypeunsigned = build_distinct_type_copy (optype);
287 TYPE_UNSIGNED (optypeunsigned) = true;
290 /* Set up variables and check if denominator is negative when considered
291 as signed. */
292 index = create_tmp_var (GCOV_TYPE_NODE, "PROF");
293 denom = create_tmp_var (optype, "PROF");
294 stmt1 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, index, integer_zero_node);
295 stmt2 = build2 (MODIFY_EXPR, optype, denom, op);
296 if (optypesigned == optype)
298 tmp1 = denom;
299 stmt3 = NULL_TREE;
301 else
303 tmp1 = create_tmp_var (optypesigned, "PROF");
304 stmt3 = build2 (MODIFY_EXPR, optypesigned, tmp1,
305 build1 (NOP_EXPR, optypesigned, denom));
307 stmt4 = build3 (COND_EXPR, void_type_node,
308 build2 (LE_EXPR, boolean_type_node, tmp1, integer_zero_node),
309 build1 (GOTO_EXPR, void_type_node, label_decl3),
310 build1 (GOTO_EXPR, void_type_node, label_decl1));
311 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
312 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
313 if (stmt3)
314 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
315 bsi_insert_before (&bsi, stmt4, BSI_SAME_STMT);
316 bb1end = stmt4;
318 /* Nonnegative. Check if denominator is power of 2. */
319 label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
320 tmp1 = create_tmp_var (optype, "PROF");
321 tmp2 = create_tmp_var (optype, "PROF");
322 stmt1 = build2 (MODIFY_EXPR, optype, tmp1,
323 build2 (PLUS_EXPR, optype, denom, integer_minus_one_node));
324 stmt2 = build2 (MODIFY_EXPR, optype, tmp2,
325 build2 (BIT_AND_EXPR, optype, tmp1, denom));
326 stmt3 = build3 (COND_EXPR, void_type_node,
327 build2 (NE_EXPR, boolean_type_node, tmp2, integer_zero_node),
328 build1 (GOTO_EXPR, void_type_node, label_decl3),
329 build1 (GOTO_EXPR, void_type_node, label_decl2));
330 bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
331 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
332 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
333 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
334 bb2end = stmt3;
336 /* Loop. Increment index, shift denominator, repeat if denominator nonzero. */
337 label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
338 stmt1 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, index,
339 build2 (PLUS_EXPR, GCOV_TYPE_NODE, index, integer_one_node));
340 if (optypeunsigned == optype)
342 tmp1 = denom;
343 stmt2 = NULL_TREE;
345 else
347 tmp1 = create_tmp_var (optypeunsigned, "PROF");
348 stmt2 = build2 (MODIFY_EXPR, optypeunsigned, tmp1,
349 build1 (NOP_EXPR, optypeunsigned, denom));
351 stmt3 = build2 (MODIFY_EXPR, optype, denom,
352 build2 (RSHIFT_EXPR, optype, tmp1, integer_one_node));
353 stmt4 = build3 (COND_EXPR, void_type_node,
354 build2 (NE_EXPR, boolean_type_node, denom, integer_zero_node),
355 build1 (GOTO_EXPR, void_type_node, label_decl2),
356 build1 (GOTO_EXPR, void_type_node, label_decl3));
357 bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
358 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
359 if (stmt2)
360 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
361 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
362 bsi_insert_before (&bsi, stmt4, BSI_SAME_STMT);
363 bb3end = stmt4;
365 /* Increment the appropriate counter. */
366 label3 = build1 (LABEL_EXPR, void_type_node, label_decl3);
367 tmp1 = create_tmp_var (GCOV_TYPE_NODE, "PROF");
368 tmp2 = create_tmp_var (GCOV_TYPE_NODE, "PROF");
369 tmp3 = create_tmp_var (GCOV_TYPE_NODE, "PROF");
370 stmt1 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, tmp1,
371 build2 (PLUS_EXPR, GCOV_TYPE_NODE, index, TREE_OPERAND (ref, 1)));
372 TREE_OPERAND (ref, 1) = tmp1;
373 /* Make a copy to avoid sharing complaints. */
374 ref2 = build4 (ARRAY_REF, TREE_TYPE (ref), TREE_OPERAND (ref, 0),
375 TREE_OPERAND (ref, 1), TREE_OPERAND (ref, 2), TREE_OPERAND (ref, 3));
376 stmt2 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, tmp2, ref);
377 stmt3 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, tmp3,
378 build2 (PLUS_EXPR, GCOV_TYPE_NODE, tmp2, integer_one_node));
379 stmt4 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, ref2, tmp3);
380 bsi_insert_before (&bsi, label3, BSI_SAME_STMT);
381 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
382 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
383 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
384 bsi_insert_before (&bsi, stmt4, BSI_SAME_STMT);
386 /* Now fix up the CFG. */
387 bb2 = (split_block (bb, bb1end))->dest;
388 bb3 = (split_block (bb2, bb2end))->dest;
389 bb4 = (split_block (bb3, bb3end))->dest;
391 EDGE_SUCC (bb, 0)->flags &= ~EDGE_FALLTHRU;
392 EDGE_SUCC (bb, 0)->flags |= EDGE_FALSE_VALUE;
393 make_edge (bb, bb4, EDGE_TRUE_VALUE);
395 EDGE_SUCC (bb2, 0)->flags &= ~EDGE_FALLTHRU;
396 EDGE_SUCC (bb2, 0)->flags |= EDGE_FALSE_VALUE;
397 make_edge (bb2, bb4, EDGE_TRUE_VALUE);
399 EDGE_SUCC (bb3, 0)->flags &= ~EDGE_FALLTHRU;
400 EDGE_SUCC (bb3, 0)->flags |= EDGE_FALSE_VALUE;
401 make_edge (bb3, bb3, EDGE_TRUE_VALUE);
404 /* Output instructions as GIMPLE trees for code to find the most common value.
405 VALUE is the expression whose value is profiled. TAG is the tag of the
406 section for counters, BASE is offset of the counter position. */
408 static void
409 tree_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
411 tree op;
412 tree tmp1, tmp2, tmp3;
413 tree label_decl1 = create_artificial_label ();
414 tree label_decl2 = create_artificial_label ();
415 tree label_decl3 = create_artificial_label ();
416 tree label_decl4 = create_artificial_label ();
417 tree label_decl5 = create_artificial_label ();
418 tree label1, label2, label3, label4, label5;
419 tree stmt1, stmt2, stmt3, stmt4;
420 tree bb1end, bb2end, bb3end, bb4end, bb5end;
421 tree ref1 = tree_coverage_counter_ref (tag, base);
422 tree ref2 = tree_coverage_counter_ref (tag, base + 1);
423 tree ref3 = tree_coverage_counter_ref (tag, base + 2);
424 basic_block bb2, bb3, bb4, bb5, bb6;
425 tree stmt = value->hvalue.tree.stmt;
426 block_stmt_iterator bsi = bsi_for_stmt (stmt);
427 basic_block bb = bb_for_stmt (stmt);
428 tree optype;
430 op = stmt;
431 if (TREE_CODE (stmt) == RETURN_EXPR
432 && TREE_OPERAND (stmt, 0)
433 && TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR)
434 op = TREE_OPERAND (stmt, 0);
435 /* op == MODIFY_EXPR */
436 op = TREE_OPERAND (op, 1);
437 /* op == TRUNC_DIV or TRUNC_MOD */
438 op = TREE_OPERAND (op, 1);
439 /* op == denominator */
440 optype = TREE_TYPE (op);
442 /* Check if the stored value matches. */
443 tmp1 = create_tmp_var (GCOV_TYPE_NODE, "PROF");
444 tmp2 = create_tmp_var (optype, "PROF");
445 tmp3 = create_tmp_var (optype, "PROF");
446 stmt1 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, tmp1, ref1);
447 stmt2 = build2 (MODIFY_EXPR, optype, tmp2,
448 build1 (NOP_EXPR, optype, tmp1));
449 stmt3 = build2 (MODIFY_EXPR, optype, tmp3, op);
450 stmt4 = build3 (COND_EXPR, void_type_node,
451 build2 (EQ_EXPR, boolean_type_node, tmp2, tmp3),
452 build1 (GOTO_EXPR, void_type_node, label_decl4),
453 build1 (GOTO_EXPR, void_type_node, label_decl1));
454 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
455 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
456 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
457 bsi_insert_before (&bsi, stmt4, BSI_SAME_STMT);
458 bb1end = stmt4;
460 /* Does not match; check whether the counter is zero. */
461 label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
462 tmp1 = create_tmp_var (GCOV_TYPE_NODE, "PROF");
463 stmt1 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, tmp1, ref2);
464 stmt2 = build3 (COND_EXPR, void_type_node,
465 build2 (EQ_EXPR, boolean_type_node, tmp1, integer_zero_node),
466 build1 (GOTO_EXPR, void_type_node, label_decl3),
467 build1 (GOTO_EXPR, void_type_node, label_decl2));
468 bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
469 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
470 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
471 bb2end = stmt2;
473 /* Counter is not zero yet, decrement. */
474 label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
475 tmp1 = create_tmp_var (GCOV_TYPE_NODE, "PROF");
476 tmp2 = create_tmp_var (GCOV_TYPE_NODE, "PROF");
477 stmt1 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, tmp1, ref2);
478 stmt2 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, tmp2,
479 build (MINUS_EXPR, GCOV_TYPE_NODE,
480 tmp1, integer_one_node));
481 stmt3 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, ref2, tmp2);
482 bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
483 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
484 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
485 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
486 bb3end = stmt3;
488 /* Counter was zero, store new value. */
489 label3 = build1 (LABEL_EXPR, void_type_node, label_decl3);
490 tmp1 = create_tmp_var (optype, "PROF");
491 tmp2 = create_tmp_var (GCOV_TYPE_NODE, "PROF");
492 stmt1 = build2 (MODIFY_EXPR, optype, tmp1, op);
493 stmt2 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, tmp2,
494 build1 (NOP_EXPR, GCOV_TYPE_NODE, tmp1));
495 stmt3 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, ref1, tmp2);
496 bsi_insert_before (&bsi, label3, BSI_SAME_STMT);
497 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
498 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
499 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
500 bb4end = stmt3;
501 /* (fall through) */
503 /* Increment counter. */
504 label4 = build1 (LABEL_EXPR, void_type_node, label_decl4);
505 tmp1 = create_tmp_var (GCOV_TYPE_NODE, "PROF");
506 tmp2 = create_tmp_var (GCOV_TYPE_NODE, "PROF");
507 stmt1 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, tmp1, ref2);
508 stmt2 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, tmp2,
509 build (PLUS_EXPR, GCOV_TYPE_NODE,
510 tmp1, integer_one_node));
511 stmt3 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, ref2, tmp2);
512 bsi_insert_before (&bsi, label4, BSI_SAME_STMT);
513 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
514 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
515 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
516 bb5end = stmt3;
518 /* Increment the counter of all executions; this seems redundant given
519 that we have counts for edges in cfg, but it may happen that some
520 optimization will change the counts for the block (either because
521 it is unable to update them correctly, or because it will duplicate
522 the block or its part). */
523 label5 = build1 (LABEL_EXPR, void_type_node, label_decl5);
524 tmp1 = create_tmp_var (GCOV_TYPE_NODE, "PROF");
525 tmp2 = create_tmp_var (GCOV_TYPE_NODE, "PROF");
526 stmt1 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, tmp1, ref3);
527 stmt2 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, tmp2,
528 build (PLUS_EXPR, GCOV_TYPE_NODE,
529 tmp1, integer_one_node));
530 stmt3 = build2 (MODIFY_EXPR, GCOV_TYPE_NODE, ref3, tmp2);
531 bsi_insert_before (&bsi, label5, BSI_SAME_STMT);
532 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
533 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
534 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
536 /* Now fix up the CFG. */
537 bb2 = (split_block (bb, bb1end))->dest;
538 bb3 = (split_block (bb2, bb2end))->dest;
539 bb4 = (split_block (bb3, bb3end))->dest;
540 bb5 = (split_block (bb4, bb4end))->dest;
541 bb6 = (split_block (bb5, bb5end))->dest;
543 EDGE_SUCC (bb, 0)->flags &= ~EDGE_FALLTHRU;
544 EDGE_SUCC (bb, 0)->flags |= EDGE_FALSE_VALUE;
545 make_edge (bb, bb5, EDGE_TRUE_VALUE);
547 EDGE_SUCC (bb2, 0)->flags &= ~EDGE_FALLTHRU;
548 EDGE_SUCC (bb2, 0)->flags |= EDGE_FALSE_VALUE;
549 make_edge (bb2, bb4, EDGE_TRUE_VALUE);
551 remove_edge (EDGE_SUCC (bb3, 0));
552 make_edge (bb3, bb6, EDGE_FALLTHRU);
555 /* Output instructions as GIMPLE trees for code to find the most common value
556 of a difference between two evaluations of an expression.
557 VALUE is the expression whose value is profiled. TAG is the tag of the
558 section for counters, BASE is offset of the counter position. */
560 static void
561 tree_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED,
562 unsigned tag ATTRIBUTE_UNUSED,
563 unsigned base ATTRIBUTE_UNUSED)
565 /* FIXME implement this. */
566 #ifdef ENABLE_CHECKING
567 internal_error ("unimplemented functionality");
568 #endif
569 gcc_unreachable ();
572 /* Return 1 if tree-based profiling is in effect, else 0.
573 If it is, set up hooks for tree-based profiling.
574 Gate for pass_tree_profile. */
576 static bool
577 do_tree_profiling (void)
579 if (flag_tree_based_profiling
580 && (profile_arc_flag || flag_test_coverage || flag_branch_probabilities))
582 tree_register_profile_hooks ();
583 tree_register_value_prof_hooks ();
584 return true;
586 return false;
589 /* Return the file on which profile dump output goes, if any. */
591 static FILE *tree_profile_dump_file (void) {
592 return dump_file;
595 static void
596 tree_profiling (void)
598 branch_prob ();
599 if (flag_branch_probabilities
600 && flag_profile_values
601 && flag_value_profile_transformations)
602 value_profile_transformations ();
603 /* The above could hose dominator info. Currently there is
604 none coming in, this is a safety valve. It should be
605 easy to adjust it, if and when there is some. */
606 free_dominance_info (CDI_DOMINATORS);
607 free_dominance_info (CDI_POST_DOMINATORS);
610 struct tree_opt_pass pass_tree_profile =
612 "tree_profile", /* name */
613 do_tree_profiling, /* gate */
614 tree_profiling, /* execute */
615 NULL, /* sub */
616 NULL, /* next */
617 0, /* static_pass_number */
618 TV_BRANCH_PROB, /* tv_id */
619 PROP_gimple_leh | PROP_cfg, /* properties_required */
620 PROP_gimple_leh | PROP_cfg, /* properties_provided */
621 0, /* properties_destroyed */
622 0, /* todo_flags_start */
623 TODO_verify_stmts, /* todo_flags_finish */
624 0 /* letter */
627 struct profile_hooks tree_profile_hooks =
629 tree_init_edge_profiler, /* init_edge_profiler */
630 tree_gen_edge_profiler, /* gen_edge_profiler */
631 tree_gen_interval_profiler, /* gen_interval_profiler */
632 tree_gen_pow2_profiler, /* gen_pow2_profiler */
633 tree_gen_one_value_profiler, /* gen_one_value_profiler */
634 tree_gen_const_delta_profiler,/* gen_const_delta_profiler */
635 tree_profile_dump_file /* profile_dump_file */