* doc/install.texi: Update binutils requirement for powerpc*-linux.
[official-gcc.git] / gcc / rtl-profile.c
blobd07d564b41eca7e44c4bd3d67e74968d53151276
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, 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.
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 2, or (at your option) any later
13 version.
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING. If not, write to the Free
22 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 02111-1307, USA. */
25 /* Generate basic block profile instrumentation and auxiliary files.
26 RTL-based version. See profile.c for overview. */
28 #include "config.h"
29 #include "system.h"
30 #include "coretypes.h"
31 #include "tm.h"
32 #include "rtl.h"
33 #include "flags.h"
34 #include "output.h"
35 #include "regs.h"
36 #include "expr.h"
37 #include "function.h"
38 #include "toplev.h"
39 #include "coverage.h"
40 #include "value-prof.h"
41 #include "tree.h"
42 #include "ggc.h"
44 /* Do initialization work for the edge profiler. */
46 static void
47 rtl_init_edge_profiler (void)
49 /* gen_edge_profiler calls safe_insert_insn_on_edge which needs
50 register liveness data to be available. */
51 life_analysis (NULL, 0);
54 /* Output instructions as RTL to increment the edge execution count. */
56 static void
57 rtl_gen_edge_profiler (int edgeno, edge e)
59 rtx ref = rtl_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
60 rtx tmp;
61 enum machine_mode mode = GET_MODE (ref);
62 rtx sequence;
64 start_sequence ();
65 ref = validize_mem (ref);
67 tmp = expand_simple_binop (mode, PLUS, ref, const1_rtx,
68 ref, 0, OPTAB_WIDEN);
70 if (tmp != ref)
71 emit_move_insn (copy_rtx (ref), tmp);
73 sequence = get_insns ();
74 end_sequence ();
75 safe_insert_insn_on_edge (sequence, e);
76 rebuild_jump_labels (e->insns.r);
79 /* Output instructions as RTL to increment the interval histogram counter.
80 VALUE is the expression whose value is profiled. TAG is the tag of the
81 section for counters, BASE is offset of the counter position. */
83 static void
84 rtl_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
86 unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
87 enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
88 rtx mem_ref, tmp, tmp1, mr, val;
89 rtx sequence;
90 rtx more_label = gen_label_rtx ();
91 rtx less_label = gen_label_rtx ();
92 rtx end_of_code_label = gen_label_rtx ();
93 int per_counter = gcov_size / BITS_PER_UNIT;
94 edge e = split_block (BLOCK_FOR_INSN (value->hvalue.rtl.insn),
95 PREV_INSN (value->hvalue.rtl.insn));
97 start_sequence ();
99 if (value->hvalue.rtl.seq)
100 emit_insn (value->hvalue.rtl.seq);
102 mr = gen_reg_rtx (Pmode);
104 tmp = rtl_coverage_counter_ref (tag, base);
105 tmp = force_reg (Pmode, XEXP (tmp, 0));
107 val = expand_simple_binop (value->hvalue.rtl.mode, MINUS,
108 copy_rtx (value->hvalue.rtl.value),
109 GEN_INT (value->hdata.intvl.int_start),
110 NULL_RTX, 0, OPTAB_WIDEN);
112 do_compare_rtx_and_jump (copy_rtx (val), GEN_INT (value->hdata.intvl.steps),
113 GE, 0, value->hvalue.rtl.mode, NULL_RTX, NULL_RTX,
114 more_label);
115 do_compare_rtx_and_jump (copy_rtx (val), const0_rtx, LT, 0,
116 value->hvalue.rtl.mode,
117 NULL_RTX, NULL_RTX, less_label);
119 /* We are in range. */
120 tmp1 = expand_simple_binop (value->hvalue.rtl.mode, MULT,
121 copy_rtx (val), GEN_INT (per_counter),
122 NULL_RTX, 0, OPTAB_WIDEN);
123 tmp1 = expand_simple_binop (Pmode, PLUS, copy_rtx (tmp), tmp1, mr,
124 0, OPTAB_WIDEN);
125 if (tmp1 != mr)
126 emit_move_insn (copy_rtx (mr), tmp1);
128 emit_jump_insn (gen_jump (end_of_code_label));
129 emit_barrier ();
131 /* Above the interval. */
132 emit_label (more_label);
133 tmp1 = expand_simple_binop (Pmode, PLUS, copy_rtx (tmp),
134 GEN_INT (per_counter * value->hdata.intvl.steps),
135 mr, 0, OPTAB_WIDEN);
136 if (tmp1 != mr)
137 emit_move_insn (copy_rtx (mr), tmp1);
138 emit_jump_insn (gen_jump (end_of_code_label));
139 emit_barrier ();
141 /* Below the interval. */
142 emit_label (less_label);
143 tmp1 = expand_simple_binop (Pmode, PLUS, copy_rtx (tmp),
144 GEN_INT (per_counter * (value->hdata.intvl.steps +1)),
145 mr, 0, OPTAB_WIDEN);
146 if (tmp1 != mr)
147 emit_move_insn (copy_rtx (mr), tmp1);
149 emit_label (end_of_code_label);
151 mem_ref = validize_mem (gen_rtx_MEM (mode, mr));
153 tmp = expand_simple_binop (mode, PLUS, copy_rtx (mem_ref), const1_rtx,
154 mem_ref, 0, OPTAB_WIDEN);
156 if (tmp != mem_ref)
157 emit_move_insn (copy_rtx (mem_ref), tmp);
159 sequence = get_insns ();
160 end_sequence ();
161 rebuild_jump_labels (sequence);
162 safe_insert_insn_on_edge (sequence, e);
165 /* Output instructions as RTL to increment the power of two histogram counter.
166 VALUE is the expression whose value is profiled. TAG is the tag of the
167 section for counters, BASE is offset of the counter position. */
169 static void
170 rtl_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
172 unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
173 enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
174 rtx mem_ref, tmp, mr, uval;
175 rtx sequence;
176 rtx end_of_code_label = gen_label_rtx ();
177 rtx loop_label = gen_label_rtx ();
178 int per_counter = gcov_size / BITS_PER_UNIT;
179 edge e = split_block (BLOCK_FOR_INSN (value->hvalue.rtl.insn),
180 PREV_INSN (value->hvalue.rtl.insn));
182 start_sequence ();
184 if (value->hvalue.rtl.seq)
185 emit_insn (value->hvalue.rtl.seq);
187 mr = gen_reg_rtx (Pmode);
188 tmp = rtl_coverage_counter_ref (tag, base);
189 tmp = force_reg (Pmode, XEXP (tmp, 0));
190 emit_move_insn (mr, tmp);
192 uval = gen_reg_rtx (value->hvalue.rtl.mode);
193 emit_move_insn (uval, copy_rtx (value->hvalue.rtl.value));
195 /* Check for non-power of 2. */
196 if (value->hdata.pow2.may_be_other)
198 do_compare_rtx_and_jump (copy_rtx (uval), const0_rtx, LE, 0, value->hvalue.rtl.mode,
199 NULL_RTX, NULL_RTX, end_of_code_label);
200 tmp = expand_simple_binop (value->hvalue.rtl.mode, PLUS, copy_rtx (uval),
201 constm1_rtx, NULL_RTX, 0, OPTAB_WIDEN);
202 tmp = expand_simple_binop (value->hvalue.rtl.mode, AND, copy_rtx (uval), tmp,
203 NULL_RTX, 0, OPTAB_WIDEN);
204 do_compare_rtx_and_jump (tmp, const0_rtx, NE, 0, value->hvalue.rtl.mode, NULL_RTX,
205 NULL_RTX, end_of_code_label);
208 /* Count log_2(value). */
209 emit_label (loop_label);
211 tmp = expand_simple_binop (Pmode, PLUS, copy_rtx (mr), GEN_INT (per_counter), mr, 0, OPTAB_WIDEN);
212 if (tmp != mr)
213 emit_move_insn (copy_rtx (mr), tmp);
215 tmp = expand_simple_binop (value->hvalue.rtl.mode, ASHIFTRT, copy_rtx (uval), const1_rtx,
216 uval, 0, OPTAB_WIDEN);
217 if (tmp != uval)
218 emit_move_insn (copy_rtx (uval), tmp);
220 do_compare_rtx_and_jump (copy_rtx (uval), const0_rtx, NE, 0, value->hvalue.rtl.mode,
221 NULL_RTX, NULL_RTX, loop_label);
223 /* Increase the counter. */
224 emit_label (end_of_code_label);
226 mem_ref = validize_mem (gen_rtx_MEM (mode, mr));
228 tmp = expand_simple_binop (mode, PLUS, copy_rtx (mem_ref), const1_rtx,
229 mem_ref, 0, OPTAB_WIDEN);
231 if (tmp != mem_ref)
232 emit_move_insn (copy_rtx (mem_ref), tmp);
234 sequence = get_insns ();
235 end_sequence ();
236 rebuild_jump_labels (sequence);
237 safe_insert_insn_on_edge (sequence, e);
240 /* Output instructions as RTL for code to find the most common value.
241 VALUE is the expression whose value is profiled. TAG is the tag of the
242 section for counters, BASE is offset of the counter position. */
244 static rtx
245 rtl_gen_one_value_profiler_no_edge_manipulation (histogram_value value,
246 unsigned tag, unsigned base)
248 unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
249 enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
250 rtx stored_value_ref, counter_ref, all_ref, stored_value, counter, all;
251 rtx tmp, uval;
252 rtx sequence;
253 rtx same_label = gen_label_rtx ();
254 rtx zero_label = gen_label_rtx ();
255 rtx end_of_code_label = gen_label_rtx ();
257 start_sequence ();
259 if (value->hvalue.rtl.seq)
260 emit_insn (value->hvalue.rtl.seq);
262 stored_value_ref = rtl_coverage_counter_ref (tag, base);
263 counter_ref = rtl_coverage_counter_ref (tag, base + 1);
264 all_ref = rtl_coverage_counter_ref (tag, base + 2);
265 stored_value = validize_mem (stored_value_ref);
266 counter = validize_mem (counter_ref);
267 all = validize_mem (all_ref);
269 uval = gen_reg_rtx (mode);
270 convert_move (uval, copy_rtx (value->hvalue.rtl.value), 0);
272 /* Check if the stored value matches. */
273 do_compare_rtx_and_jump (copy_rtx (uval), copy_rtx (stored_value), EQ,
274 0, mode, NULL_RTX, NULL_RTX, same_label);
276 /* Does not match; check whether the counter is zero. */
277 do_compare_rtx_and_jump (copy_rtx (counter), const0_rtx, EQ, 0, mode,
278 NULL_RTX, NULL_RTX, zero_label);
280 /* The counter is not zero yet. */
281 tmp = expand_simple_binop (mode, PLUS, copy_rtx (counter), constm1_rtx,
282 counter, 0, OPTAB_WIDEN);
284 if (tmp != counter)
285 emit_move_insn (copy_rtx (counter), tmp);
287 emit_jump_insn (gen_jump (end_of_code_label));
288 emit_barrier ();
290 emit_label (zero_label);
291 /* Set new value. */
292 emit_move_insn (copy_rtx (stored_value), copy_rtx (uval));
294 emit_label (same_label);
295 /* Increase the counter. */
296 tmp = expand_simple_binop (mode, PLUS, copy_rtx (counter), const1_rtx,
297 counter, 0, OPTAB_WIDEN);
299 if (tmp != counter)
300 emit_move_insn (copy_rtx (counter), tmp);
302 emit_label (end_of_code_label);
304 /* Increase the counter of all executions; this seems redundant given
305 that ve have counts for edges in cfg, but it may happen that some
306 optimization will change the counts for the block (either because
307 it is unable to update them correctly, or because it will duplicate
308 the block or its part). */
309 tmp = expand_simple_binop (mode, PLUS, copy_rtx (all), const1_rtx,
310 all, 0, OPTAB_WIDEN);
312 if (tmp != all)
313 emit_move_insn (copy_rtx (all), tmp);
314 sequence = get_insns ();
315 end_sequence ();
316 return sequence;
319 /* Output instructions as RTL for code to find the most common value.
320 VALUE is the expression whose value is profiled. TAG is the tag of the
321 section for counters, BASE is offset of the counter position. */
323 static void
324 rtl_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
326 edge e = split_block (BLOCK_FOR_INSN (value->hvalue.rtl.insn),
327 PREV_INSN (value->hvalue.rtl.insn));
328 rtx sequence = rtl_gen_one_value_profiler_no_edge_manipulation (value,
329 tag, base);
330 rebuild_jump_labels (sequence);
331 safe_insert_insn_on_edge (sequence, e);
334 /* Output instructions as RTL for code to find the most common value of
335 a difference between two evaluations of an expression.
336 VALUE is the expression whose value is profiled. TAG is the tag of the
337 section for counters, BASE is offset of the counter position. */
339 static void
340 rtl_gen_const_delta_profiler (histogram_value value, unsigned tag, unsigned base)
342 histogram_value one_value_delta;
343 unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
344 enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
345 rtx stored_value_ref, stored_value, tmp, uval;
346 rtx sequence;
347 edge e = split_block (BLOCK_FOR_INSN (value->hvalue.rtl.insn),
348 PREV_INSN (value->hvalue.rtl.insn));
350 start_sequence ();
352 if (value->hvalue.rtl.seq)
353 emit_insn (value->hvalue.rtl.seq);
355 stored_value_ref = rtl_coverage_counter_ref (tag, base);
356 stored_value = validize_mem (stored_value_ref);
358 uval = gen_reg_rtx (mode);
359 convert_move (uval, copy_rtx (value->hvalue.rtl.value), 0);
360 tmp = expand_simple_binop (mode, MINUS,
361 copy_rtx (uval), copy_rtx (stored_value),
362 NULL_RTX, 0, OPTAB_WIDEN);
364 one_value_delta = ggc_alloc (sizeof (*one_value_delta));
365 one_value_delta->hvalue.rtl.value = tmp;
366 one_value_delta->hvalue.rtl.mode = mode;
367 one_value_delta->hvalue.rtl.seq = NULL_RTX;
368 one_value_delta->hvalue.rtl.insn = value->hvalue.rtl.insn;
369 one_value_delta->type = HIST_TYPE_SINGLE_VALUE;
370 emit_insn (rtl_gen_one_value_profiler_no_edge_manipulation (one_value_delta,
371 tag, base + 1));
372 emit_move_insn (copy_rtx (stored_value), uval);
373 sequence = get_insns ();
374 end_sequence ();
375 rebuild_jump_labels (sequence);
376 safe_insert_insn_on_edge (sequence, e);
379 /* Return the file on which profile dump output goes, if any. */
381 static FILE *rtl_profile_dump_file (void) {
382 return dump_file;
385 struct profile_hooks rtl_profile_hooks =
387 rtl_init_edge_profiler,
388 rtl_gen_edge_profiler,
389 rtl_gen_interval_profiler,
390 rtl_gen_pow2_profiler,
391 rtl_gen_one_value_profiler,
392 rtl_gen_const_delta_profiler,
393 rtl_profile_dump_file