]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/tracer.c
2012-04-04 Tristan Gingold <gingold@adacore.com>
[thirdparty/gcc.git] / gcc / tracer.c
CommitLineData
fa99ab3d 1/* The tracer pass for the GNU compiler.
2 Contributed by Jan Hubicka, SuSE Labs.
3ddccd57 3 Adapted to work on GIMPLE instead of RTL by Robert Kidd, UIUC.
cfaf579d 4 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
3072d30e 5 Free Software Foundation, Inc.
fa99ab3d 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
8c4c00c1 11 the Free Software Foundation; either version 3, or (at your option)
fa99ab3d 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
8c4c00c1 20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
fa99ab3d 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"
805e22b2 39#include "coretypes.h"
40#include "tm.h"
fa99ab3d 41#include "tree.h"
42#include "rtl.h"
43#include "hard-reg-set.h"
44#include "basic-block.h"
45#include "output.h"
46#include "cfglayout.h"
47#include "fibheap.h"
48#include "flags.h"
e7f8f0eb 49#include "timevar.h"
fa99ab3d 50#include "params.h"
44359ced 51#include "coverage.h"
77fce4cd 52#include "tree-pass.h"
3ddccd57 53#include "tree-flow.h"
54#include "tree-inline.h"
fa99ab3d 55
3ddccd57 56static int count_insns (basic_block);
7ecb5bb2 57static bool ignore_bb_p (const_basic_block);
58static bool better_p (const_edge, const_edge);
60b8c5b3 59static edge find_best_successor (basic_block);
60static edge find_best_predecessor (basic_block);
61static int find_trace (basic_block, basic_block *);
fa99ab3d 62
63/* Minimal outgoing edge probability considered for superblock formation. */
64static int probability_cutoff;
65static int branch_ratio_cutoff;
66
3ddccd57 67/* A bit BB->index is set if BB has already been seen, i.e. it is
68 connected to some trace already. */
69sbitmap bb_seen;
fa99ab3d 70
3ddccd57 71static inline void
72mark_bb_seen (basic_block bb)
73{
74 unsigned int size = SBITMAP_SIZE_BYTES (bb_seen) * 8;
75
76 if ((unsigned int)bb->index >= size)
77 bb_seen = sbitmap_resize (bb_seen, size * 2, 0);
78
79 SET_BIT (bb_seen, bb->index);
80}
81
82static inline bool
83bb_seen_p (basic_block bb)
84{
85 return TEST_BIT (bb_seen, bb->index);
86}
fa99ab3d 87
7299020b 88/* Return true if we should ignore the basic block for purposes of tracing. */
fa99ab3d 89static bool
7ecb5bb2 90ignore_bb_p (const_basic_block bb)
fa99ab3d 91{
09a1f31f 92 gimple g;
93
4d2e5d52 94 if (bb->index < NUM_FIXED_BLOCKS)
fa99ab3d 95 return true;
0bfd8d5c 96 if (optimize_bb_for_size_p (bb))
fa99ab3d 97 return true;
09a1f31f 98
99 /* A transaction is a single entry multiple exit region. It must be
100 duplicated in its entirety or not at all. */
101 g = last_stmt (CONST_CAST_BB (bb));
102 if (g && gimple_code (g) == GIMPLE_TRANSACTION)
103 return true;
104
fa99ab3d 105 return false;
106}
107
108/* Return number of instructions in the block. */
109
110static int
3ddccd57 111count_insns (basic_block bb)
fa99ab3d 112{
75a70cf9 113 gimple_stmt_iterator gsi;
114 gimple stmt;
fa99ab3d 115 int n = 0;
116
75a70cf9 117 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
3ddccd57 118 {
75a70cf9 119 stmt = gsi_stmt (gsi);
3ddccd57 120 n += estimate_num_insns (stmt, &eni_size_weights);
121 }
fa99ab3d 122 return n;
123}
124
125/* Return true if E1 is more frequent than E2. */
126static bool
7ecb5bb2 127better_p (const_edge e1, const_edge e2)
fa99ab3d 128{
129 if (e1->count != e2->count)
130 return e1->count > e2->count;
131 if (e1->src->frequency * e1->probability !=
132 e2->src->frequency * e2->probability)
133 return (e1->src->frequency * e1->probability
134 > e2->src->frequency * e2->probability);
135 /* This is needed to avoid changes in the decision after
136 CFG is modified. */
137 if (e1->src != e2->src)
138 return e1->src->index > e2->src->index;
139 return e1->dest->index > e2->dest->index;
140}
141
142/* Return most frequent successor of basic block BB. */
143
144static edge
60b8c5b3 145find_best_successor (basic_block bb)
fa99ab3d 146{
147 edge e;
148 edge best = NULL;
cd665a06 149 edge_iterator ei;
fa99ab3d 150
cd665a06 151 FOR_EACH_EDGE (e, ei, bb->succs)
fa99ab3d 152 if (!best || better_p (e, best))
153 best = e;
154 if (!best || ignore_bb_p (best->dest))
155 return NULL;
156 if (best->probability <= probability_cutoff)
157 return NULL;
158 return best;
159}
160
161/* Return most frequent predecessor of basic block BB. */
162
163static edge
60b8c5b3 164find_best_predecessor (basic_block bb)
fa99ab3d 165{
166 edge e;
167 edge best = NULL;
cd665a06 168 edge_iterator ei;
fa99ab3d 169
cd665a06 170 FOR_EACH_EDGE (e, ei, bb->preds)
fa99ab3d 171 if (!best || better_p (e, best))
172 best = e;
173 if (!best || ignore_bb_p (best->src))
174 return NULL;
175 if (EDGE_FREQUENCY (best) * REG_BR_PROB_BASE
176 < bb->frequency * branch_ratio_cutoff)
177 return NULL;
178 return best;
179}
180
181/* Find the trace using bb and record it in the TRACE array.
182 Return number of basic blocks recorded. */
183
184static int
60b8c5b3 185find_trace (basic_block bb, basic_block *trace)
fa99ab3d 186{
187 int i = 0;
188 edge e;
189
450d042a 190 if (dump_file)
191 fprintf (dump_file, "Trace seed %i [%i]", bb->index, bb->frequency);
fa99ab3d 192
193 while ((e = find_best_predecessor (bb)) != NULL)
194 {
195 basic_block bb2 = e->src;
3ddccd57 196 if (bb_seen_p (bb2) || (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX))
fa99ab3d 197 || find_best_successor (bb2) != e)
198 break;
450d042a 199 if (dump_file)
200 fprintf (dump_file, ",%i [%i]", bb->index, bb->frequency);
fa99ab3d 201 bb = bb2;
202 }
450d042a 203 if (dump_file)
204 fprintf (dump_file, " forward %i [%i]", bb->index, bb->frequency);
fa99ab3d 205 trace[i++] = bb;
206
207 /* Follow the trace in forward direction. */
208 while ((e = find_best_successor (bb)) != NULL)
209 {
210 bb = e->dest;
3ddccd57 211 if (bb_seen_p (bb) || (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX))
fa99ab3d 212 || find_best_predecessor (bb) != e)
213 break;
450d042a 214 if (dump_file)
215 fprintf (dump_file, ",%i [%i]", bb->index, bb->frequency);
fa99ab3d 216 trace[i++] = bb;
217 }
450d042a 218 if (dump_file)
219 fprintf (dump_file, "\n");
fa99ab3d 220 return i;
221}
222
223/* Look for basic blocks in frequency order, construct traces and tail duplicate
224 if profitable. */
225
35c67c83 226static bool
60b8c5b3 227tail_duplicate (void)
fa99ab3d 228{
4c36ffe6 229 fibnode_t *blocks = XCNEWVEC (fibnode_t, last_basic_block);
230 basic_block *trace = XNEWVEC (basic_block, n_basic_blocks);
231 int *counts = XNEWVEC (int, last_basic_block);
fa99ab3d 232 int ninsns = 0, nduplicated = 0;
233 gcov_type weighted_insns = 0, traced_insns = 0;
234 fibheap_t heap = fibheap_new ();
235 gcov_type cover_insns;
236 int max_dup_insns;
237 basic_block bb;
35c67c83 238 bool changed = false;
fa99ab3d 239
3ddccd57 240 /* Create an oversized sbitmap to reduce the chance that we need to
241 resize it. */
242 bb_seen = sbitmap_alloc (last_basic_block * 2);
243 sbitmap_zero (bb_seen);
244 initialize_original_copy_tables ();
245
ab6a34f2 246 if (profile_info && flag_branch_probabilities)
fa99ab3d 247 probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY_FEEDBACK);
248 else
249 probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY);
250 probability_cutoff = REG_BR_PROB_BASE / 100 * probability_cutoff;
251
252 branch_ratio_cutoff =
253 (REG_BR_PROB_BASE / 100 * PARAM_VALUE (TRACER_MIN_BRANCH_RATIO));
254
255 FOR_EACH_BB (bb)
256 {
257 int n = count_insns (bb);
258 if (!ignore_bb_p (bb))
259 blocks[bb->index] = fibheap_insert (heap, -bb->frequency,
260 bb);
261
262 counts [bb->index] = n;
263 ninsns += n;
264 weighted_insns += n * bb->frequency;
265 }
266
ab6a34f2 267 if (profile_info && flag_branch_probabilities)
fa99ab3d 268 cover_insns = PARAM_VALUE (TRACER_DYNAMIC_COVERAGE_FEEDBACK);
269 else
270 cover_insns = PARAM_VALUE (TRACER_DYNAMIC_COVERAGE);
271 cover_insns = (weighted_insns * cover_insns + 50) / 100;
272 max_dup_insns = (ninsns * PARAM_VALUE (TRACER_MAX_CODE_GROWTH) + 50) / 100;
273
274 while (traced_insns < cover_insns && nduplicated < max_dup_insns
275 && !fibheap_empty (heap))
276 {
45ba1503 277 basic_block bb = (basic_block) fibheap_extract_min (heap);
fa99ab3d 278 int n, pos;
279
280 if (!bb)
281 break;
282
283 blocks[bb->index] = NULL;
284
285 if (ignore_bb_p (bb))
286 continue;
3ddccd57 287 gcc_assert (!bb_seen_p (bb));
fa99ab3d 288
289 n = find_trace (bb, trace);
290
291 bb = trace[0];
292 traced_insns += bb->frequency * counts [bb->index];
293 if (blocks[bb->index])
294 {
295 fibheap_delete_node (heap, blocks[bb->index]);
296 blocks[bb->index] = NULL;
297 }
298
299 for (pos = 1; pos < n; pos++)
300 {
301 basic_block bb2 = trace[pos];
302
303 if (blocks[bb2->index])
304 {
305 fibheap_delete_node (heap, blocks[bb2->index]);
306 blocks[bb2->index] = NULL;
307 }
308 traced_insns += bb2->frequency * counts [bb2->index];
cd665a06 309 if (EDGE_COUNT (bb2->preds) > 1
4ee9c684 310 && can_duplicate_block_p (bb2))
fa99ab3d 311 {
cd665a06 312 edge e;
3ddccd57 313 basic_block copy;
314
315 nduplicated += counts [bb2->index];
fa99ab3d 316
c6356c17 317 e = find_edge (bb, bb2);
48e1416a 318
3ddccd57 319 copy = duplicate_block (bb2, e, bb);
320 flush_pending_stmts (e);
cd665a06 321
28c92cbb 322 add_phi_args_after_copy (&copy, 1, NULL);
fa99ab3d 323
324 /* Reconsider the original copy of block we've duplicated.
de132707 325 Removing the most common predecessor may make it to be
fa99ab3d 326 head. */
3ddccd57 327 blocks[bb2->index] =
328 fibheap_insert (heap, -bb2->frequency, bb2);
fa99ab3d 329
450d042a 330 if (dump_file)
331 fprintf (dump_file, "Duplicated %i as %i [%i]\n",
3ddccd57 332 bb2->index, copy->index, copy->frequency);
333
334 bb2 = copy;
35c67c83 335 changed = true;
fa99ab3d 336 }
3ddccd57 337 mark_bb_seen (bb2);
fa99ab3d 338 bb = bb2;
339 /* In case the trace became infrequent, stop duplicating. */
340 if (ignore_bb_p (bb))
341 break;
342 }
450d042a 343 if (dump_file)
344 fprintf (dump_file, " covered now %.1f\n\n",
fa99ab3d 345 traced_insns * 100.0 / weighted_insns);
346 }
450d042a 347 if (dump_file)
348 fprintf (dump_file, "Duplicated %i insns (%i%%)\n", nduplicated,
fa99ab3d 349 nduplicated * 100 / ninsns);
350
3ddccd57 351 free_original_copy_tables ();
352 sbitmap_free (bb_seen);
fa99ab3d 353 free (blocks);
354 free (trace);
355 free (counts);
356 fibheap_delete (heap);
35c67c83 357
358 return changed;
fa99ab3d 359}
360
207c7ab2 361/* Main entry point to this file. */
fa99ab3d 362
3ddccd57 363static unsigned int
207c7ab2 364tracer (void)
fa99ab3d 365{
35c67c83 366 bool changed;
367
3ddccd57 368 gcc_assert (current_ir_type () == IR_GIMPLE);
207c7ab2 369
4d2e5d52 370 if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1)
3ddccd57 371 return 0;
e7f8f0eb 372
fa99ab3d 373 mark_dfs_back_edges ();
450d042a 374 if (dump_file)
562d71e8 375 dump_flow_info (dump_file, dump_flags);
3ddccd57 376
377 /* Trace formation is done on the fly inside tail_duplicate */
35c67c83 378 changed = tail_duplicate ();
379 if (changed)
380 free_dominance_info (CDI_DOMINATORS);
3ddccd57 381
450d042a 382 if (dump_file)
562d71e8 383 dump_flow_info (dump_file, dump_flags);
e7f8f0eb 384
35c67c83 385 return changed ? TODO_cleanup_cfg : 0;
77fce4cd 386}
387\f
388static bool
3ddccd57 389gate_tracer (void)
77fce4cd 390{
3ddccd57 391 return (optimize > 0 && flag_tracer && flag_reorder_blocks);
fa99ab3d 392}
77fce4cd 393
20099e35 394struct gimple_opt_pass pass_tracer =
77fce4cd 395{
20099e35 396 {
397 GIMPLE_PASS,
77fce4cd 398 "tracer", /* name */
3ddccd57 399 gate_tracer, /* gate */
400 tracer, /* execute */
77fce4cd 401 NULL, /* sub */
402 NULL, /* next */
403 0, /* static_pass_number */
404 TV_TRACER, /* tv_id */
405 0, /* properties_required */
406 0, /* properties_provided */
407 0, /* properties_destroyed */
408 0, /* todo_flags_start */
771e2890 409 TODO_update_ssa
20099e35 410 | TODO_verify_ssa /* todo_flags_finish */
411 }
77fce4cd 412};