]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/tracer.c
backport: As described in http://gcc.gnu.org/ml/gcc/2012-08/msg00015.html...
[thirdparty/gcc.git] / gcc / tracer.c
CommitLineData
5c856b23
JH
1/* The tracer pass for the GNU compiler.
2 Contributed by Jan Hubicka, SuSE Labs.
232abc3f 3 Adapted to work on GIMPLE instead of RTL by Robert Kidd, UIUC.
66647d44 4 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
6fb5fa3c 5 Free Software Foundation, Inc.
5c856b23
JH
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by
9dcd6f09 11 the Free Software Foundation; either version 3, or (at your option)
5c856b23
JH
12 any later version.
13
14 GCC is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17 License for more details.
18
19 You should have received a copy of the GNU General Public License
9dcd6f09
NC
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
5c856b23
JH
22
23/* This pass performs the tail duplication needed for superblock formation.
24 For more information see:
25
26 Design and Analysis of Profile-Based Optimization in Compaq's
27 Compilation Tools for Alpha; Journal of Instruction-Level
28 Parallelism 3 (2000) 1-25
29
30 Unlike Compaq's implementation we don't do the loop peeling as most
31 probably a better job can be done by a special pass and we don't
32 need to worry too much about the code size implications as the tail
33 duplicates are crossjumped again if optimizations are not
34 performed. */
35
36
37#include "config.h"
38#include "system.h"
4977bab6
ZW
39#include "coretypes.h"
40#include "tm.h"
5c856b23
JH
41#include "tree.h"
42#include "rtl.h"
43#include "hard-reg-set.h"
44#include "basic-block.h"
5c856b23
JH
45#include "fibheap.h"
46#include "flags.h"
47#include "params.h"
ca29da43 48#include "coverage.h"
ef330312 49#include "tree-pass.h"
232abc3f
RK
50#include "tree-flow.h"
51#include "tree-inline.h"
0b9066cf 52#include "cfgloop.h"
5c856b23 53
232abc3f 54static int count_insns (basic_block);
ed7a4b4b
KG
55static bool ignore_bb_p (const_basic_block);
56static bool better_p (const_edge, const_edge);
46c5ad27
AJ
57static edge find_best_successor (basic_block);
58static edge find_best_predecessor (basic_block);
59static int find_trace (basic_block, basic_block *);
5c856b23
JH
60
61/* Minimal outgoing edge probability considered for superblock formation. */
62static int probability_cutoff;
63static int branch_ratio_cutoff;
64
232abc3f
RK
65/* A bit BB->index is set if BB has already been seen, i.e. it is
66 connected to some trace already. */
67sbitmap bb_seen;
5c856b23 68
232abc3f
RK
69static inline void
70mark_bb_seen (basic_block bb)
71{
72 unsigned int size = SBITMAP_SIZE_BYTES (bb_seen) * 8;
73
74 if ((unsigned int)bb->index >= size)
75 bb_seen = sbitmap_resize (bb_seen, size * 2, 0);
76
77 SET_BIT (bb_seen, bb->index);
78}
79
80static inline bool
81bb_seen_p (basic_block bb)
82{
83 return TEST_BIT (bb_seen, bb->index);
84}
5c856b23 85
4b7e68e7 86/* Return true if we should ignore the basic block for purposes of tracing. */
5c856b23 87static bool
ed7a4b4b 88ignore_bb_p (const_basic_block bb)
5c856b23 89{
2e85d5e2
PM
90 gimple g;
91
24bd1a0b 92 if (bb->index < NUM_FIXED_BLOCKS)
5c856b23 93 return true;
efd8f750 94 if (optimize_bb_for_size_p (bb))
5c856b23 95 return true;
2e85d5e2
PM
96
97 /* A transaction is a single entry multiple exit region. It must be
98 duplicated in its entirety or not at all. */
99 g = last_stmt (CONST_CAST_BB (bb));
100 if (g && gimple_code (g) == GIMPLE_TRANSACTION)
101 return true;
102
5c856b23
JH
103 return false;
104}
105
106/* Return number of instructions in the block. */
107
108static int
232abc3f 109count_insns (basic_block bb)
5c856b23 110{
726a989a
RB
111 gimple_stmt_iterator gsi;
112 gimple stmt;
5c856b23
JH
113 int n = 0;
114
726a989a 115 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
232abc3f 116 {
726a989a 117 stmt = gsi_stmt (gsi);
232abc3f
RK
118 n += estimate_num_insns (stmt, &eni_size_weights);
119 }
5c856b23
JH
120 return n;
121}
122
123/* Return true if E1 is more frequent than E2. */
124static bool
ed7a4b4b 125better_p (const_edge e1, const_edge e2)
5c856b23
JH
126{
127 if (e1->count != e2->count)
128 return e1->count > e2->count;
129 if (e1->src->frequency * e1->probability !=
130 e2->src->frequency * e2->probability)
131 return (e1->src->frequency * e1->probability
132 > e2->src->frequency * e2->probability);
133 /* This is needed to avoid changes in the decision after
134 CFG is modified. */
135 if (e1->src != e2->src)
136 return e1->src->index > e2->src->index;
137 return e1->dest->index > e2->dest->index;
138}
139
140/* Return most frequent successor of basic block BB. */
141
142static edge
46c5ad27 143find_best_successor (basic_block bb)
5c856b23
JH
144{
145 edge e;
146 edge best = NULL;
628f6a4e 147 edge_iterator ei;
5c856b23 148
628f6a4e 149 FOR_EACH_EDGE (e, ei, bb->succs)
5c856b23
JH
150 if (!best || better_p (e, best))
151 best = e;
152 if (!best || ignore_bb_p (best->dest))
153 return NULL;
154 if (best->probability <= probability_cutoff)
155 return NULL;
156 return best;
157}
158
159/* Return most frequent predecessor of basic block BB. */
160
161static edge
46c5ad27 162find_best_predecessor (basic_block bb)
5c856b23
JH
163{
164 edge e;
165 edge best = NULL;
628f6a4e 166 edge_iterator ei;
5c856b23 167
628f6a4e 168 FOR_EACH_EDGE (e, ei, bb->preds)
5c856b23
JH
169 if (!best || better_p (e, best))
170 best = e;
171 if (!best || ignore_bb_p (best->src))
172 return NULL;
173 if (EDGE_FREQUENCY (best) * REG_BR_PROB_BASE
174 < bb->frequency * branch_ratio_cutoff)
175 return NULL;
176 return best;
177}
178
179/* Find the trace using bb and record it in the TRACE array.
180 Return number of basic blocks recorded. */
181
182static int
46c5ad27 183find_trace (basic_block bb, basic_block *trace)
5c856b23
JH
184{
185 int i = 0;
186 edge e;
187
c263766c
RH
188 if (dump_file)
189 fprintf (dump_file, "Trace seed %i [%i]", bb->index, bb->frequency);
5c856b23
JH
190
191 while ((e = find_best_predecessor (bb)) != NULL)
192 {
193 basic_block bb2 = e->src;
232abc3f 194 if (bb_seen_p (bb2) || (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX))
5c856b23
JH
195 || find_best_successor (bb2) != e)
196 break;
c263766c
RH
197 if (dump_file)
198 fprintf (dump_file, ",%i [%i]", bb->index, bb->frequency);
5c856b23
JH
199 bb = bb2;
200 }
c263766c
RH
201 if (dump_file)
202 fprintf (dump_file, " forward %i [%i]", bb->index, bb->frequency);
5c856b23
JH
203 trace[i++] = bb;
204
205 /* Follow the trace in forward direction. */
206 while ((e = find_best_successor (bb)) != NULL)
207 {
208 bb = e->dest;
232abc3f 209 if (bb_seen_p (bb) || (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX))
5c856b23
JH
210 || find_best_predecessor (bb) != e)
211 break;
c263766c
RH
212 if (dump_file)
213 fprintf (dump_file, ",%i [%i]", bb->index, bb->frequency);
5c856b23
JH
214 trace[i++] = bb;
215 }
c263766c
RH
216 if (dump_file)
217 fprintf (dump_file, "\n");
5c856b23
JH
218 return i;
219}
220
221/* Look for basic blocks in frequency order, construct traces and tail duplicate
222 if profitable. */
223
07b1bf20 224static bool
46c5ad27 225tail_duplicate (void)
5c856b23 226{
5ed6ace5
MD
227 fibnode_t *blocks = XCNEWVEC (fibnode_t, last_basic_block);
228 basic_block *trace = XNEWVEC (basic_block, n_basic_blocks);
229 int *counts = XNEWVEC (int, last_basic_block);
5c856b23
JH
230 int ninsns = 0, nduplicated = 0;
231 gcov_type weighted_insns = 0, traced_insns = 0;
232 fibheap_t heap = fibheap_new ();
233 gcov_type cover_insns;
234 int max_dup_insns;
235 basic_block bb;
07b1bf20 236 bool changed = false;
5c856b23 237
232abc3f
RK
238 /* Create an oversized sbitmap to reduce the chance that we need to
239 resize it. */
240 bb_seen = sbitmap_alloc (last_basic_block * 2);
241 sbitmap_zero (bb_seen);
242 initialize_original_copy_tables ();
243
cdb23767 244 if (profile_info && flag_branch_probabilities)
5c856b23
JH
245 probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY_FEEDBACK);
246 else
247 probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY);
248 probability_cutoff = REG_BR_PROB_BASE / 100 * probability_cutoff;
249
250 branch_ratio_cutoff =
251 (REG_BR_PROB_BASE / 100 * PARAM_VALUE (TRACER_MIN_BRANCH_RATIO));
252
253 FOR_EACH_BB (bb)
254 {
255 int n = count_insns (bb);
256 if (!ignore_bb_p (bb))
257 blocks[bb->index] = fibheap_insert (heap, -bb->frequency,
258 bb);
259
260 counts [bb->index] = n;
261 ninsns += n;
262 weighted_insns += n * bb->frequency;
263 }
264
cdb23767 265 if (profile_info && flag_branch_probabilities)
5c856b23
JH
266 cover_insns = PARAM_VALUE (TRACER_DYNAMIC_COVERAGE_FEEDBACK);
267 else
268 cover_insns = PARAM_VALUE (TRACER_DYNAMIC_COVERAGE);
269 cover_insns = (weighted_insns * cover_insns + 50) / 100;
270 max_dup_insns = (ninsns * PARAM_VALUE (TRACER_MAX_CODE_GROWTH) + 50) / 100;
271
272 while (traced_insns < cover_insns && nduplicated < max_dup_insns
273 && !fibheap_empty (heap))
274 {
3d9a9f94 275 basic_block bb = (basic_block) fibheap_extract_min (heap);
5c856b23
JH
276 int n, pos;
277
278 if (!bb)
279 break;
280
281 blocks[bb->index] = NULL;
282
283 if (ignore_bb_p (bb))
284 continue;
232abc3f 285 gcc_assert (!bb_seen_p (bb));
5c856b23
JH
286
287 n = find_trace (bb, trace);
288
289 bb = trace[0];
290 traced_insns += bb->frequency * counts [bb->index];
291 if (blocks[bb->index])
292 {
293 fibheap_delete_node (heap, blocks[bb->index]);
294 blocks[bb->index] = NULL;
295 }
296
297 for (pos = 1; pos < n; pos++)
298 {
299 basic_block bb2 = trace[pos];
300
301 if (blocks[bb2->index])
302 {
303 fibheap_delete_node (heap, blocks[bb2->index]);
304 blocks[bb2->index] = NULL;
305 }
306 traced_insns += bb2->frequency * counts [bb2->index];
628f6a4e 307 if (EDGE_COUNT (bb2->preds) > 1
0b9066cf
RG
308 && can_duplicate_block_p (bb2)
309 /* We have the tendency to duplicate the loop header
310 of all do { } while loops. Do not do that - it is
311 not profitable and it might create a loop with multiple
312 entries or at least rotate the loop. */
313 && (!current_loops
314 || bb2->loop_father->header != bb2))
5c856b23 315 {
628f6a4e 316 edge e;
232abc3f
RK
317 basic_block copy;
318
319 nduplicated += counts [bb2->index];
5c856b23 320
9ff3d2de 321 e = find_edge (bb, bb2);
b8698a0f 322
232abc3f
RK
323 copy = duplicate_block (bb2, e, bb);
324 flush_pending_stmts (e);
628f6a4e 325
5f40b3cb 326 add_phi_args_after_copy (&copy, 1, NULL);
5c856b23
JH
327
328 /* Reconsider the original copy of block we've duplicated.
14b493d6 329 Removing the most common predecessor may make it to be
5c856b23 330 head. */
232abc3f
RK
331 blocks[bb2->index] =
332 fibheap_insert (heap, -bb2->frequency, bb2);
5c856b23 333
c263766c
RH
334 if (dump_file)
335 fprintf (dump_file, "Duplicated %i as %i [%i]\n",
232abc3f
RK
336 bb2->index, copy->index, copy->frequency);
337
338 bb2 = copy;
07b1bf20 339 changed = true;
5c856b23 340 }
232abc3f 341 mark_bb_seen (bb2);
5c856b23
JH
342 bb = bb2;
343 /* In case the trace became infrequent, stop duplicating. */
344 if (ignore_bb_p (bb))
345 break;
346 }
c263766c
RH
347 if (dump_file)
348 fprintf (dump_file, " covered now %.1f\n\n",
5c856b23
JH
349 traced_insns * 100.0 / weighted_insns);
350 }
c263766c
RH
351 if (dump_file)
352 fprintf (dump_file, "Duplicated %i insns (%i%%)\n", nduplicated,
5c856b23
JH
353 nduplicated * 100 / ninsns);
354
232abc3f
RK
355 free_original_copy_tables ();
356 sbitmap_free (bb_seen);
5c856b23
JH
357 free (blocks);
358 free (trace);
359 free (counts);
360 fibheap_delete (heap);
07b1bf20
RG
361
362 return changed;
5c856b23
JH
363}
364
ad21dab7 365/* Main entry point to this file. */
5c856b23 366
232abc3f 367static unsigned int
ad21dab7 368tracer (void)
5c856b23 369{
07b1bf20
RG
370 bool changed;
371
24bd1a0b 372 if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1)
232abc3f 373 return 0;
38700cee 374
5c856b23 375 mark_dfs_back_edges ();
c263766c 376 if (dump_file)
c4669594 377 brief_dump_cfg (dump_file, dump_flags);
232abc3f
RK
378
379 /* Trace formation is done on the fly inside tail_duplicate */
07b1bf20
RG
380 changed = tail_duplicate ();
381 if (changed)
382 free_dominance_info (CDI_DOMINATORS);
232abc3f 383
c263766c 384 if (dump_file)
c4669594 385 brief_dump_cfg (dump_file, dump_flags);
38700cee 386
07b1bf20 387 return changed ? TODO_cleanup_cfg : 0;
ef330312
PB
388}
389\f
390static bool
232abc3f 391gate_tracer (void)
ef330312 392{
232abc3f 393 return (optimize > 0 && flag_tracer && flag_reorder_blocks);
5c856b23 394}
ef330312 395
8ddbbcae 396struct gimple_opt_pass pass_tracer =
ef330312 397{
8ddbbcae
JH
398 {
399 GIMPLE_PASS,
ef330312 400 "tracer", /* name */
232abc3f
RK
401 gate_tracer, /* gate */
402 tracer, /* execute */
ef330312
PB
403 NULL, /* sub */
404 NULL, /* next */
405 0, /* static_pass_number */
406 TV_TRACER, /* tv_id */
407 0, /* properties_required */
408 0, /* properties_provided */
409 0, /* properties_destroyed */
410 0, /* todo_flags_start */
22c5fa5f 411 TODO_update_ssa
8ddbbcae
JH
412 | TODO_verify_ssa /* todo_flags_finish */
413 }
ef330312 414};