]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/tracer.c
i386.c (make_resolver_func): Update.
[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.
cbe34bb5 4 Copyright (C) 2001-2017 Free Software Foundation, Inc.
5c856b23
JH
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
9dcd6f09 10 the Free Software Foundation; either version 3, or (at your option)
5c856b23
JH
11 any later version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 License for more details.
17
18 You should have received a copy of the GNU General Public License
9dcd6f09
NC
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
5c856b23
JH
21
22/* This pass performs the tail duplication needed for superblock formation.
23 For more information see:
24
25 Design and Analysis of Profile-Based Optimization in Compaq's
26 Compilation Tools for Alpha; Journal of Instruction-Level
27 Parallelism 3 (2000) 1-25
28
29 Unlike Compaq's implementation we don't do the loop peeling as most
30 probably a better job can be done by a special pass and we don't
31 need to worry too much about the code size implications as the tail
32 duplicates are crossjumped again if optimizations are not
33 performed. */
34
35
36#include "config.h"
37#include "system.h"
4977bab6 38#include "coretypes.h"
c7131fb2 39#include "backend.h"
957060b5 40#include "rtl.h"
5c856b23 41#include "tree.h"
c7131fb2 42#include "gimple.h"
957060b5
AM
43#include "cfghooks.h"
44#include "tree-pass.h"
59f2e9d8 45#include "profile.h"
60393bbc 46#include "cfganal.h"
5c856b23 47#include "params.h"
5be5c238 48#include "gimple-iterator.h"
442b4905 49#include "tree-cfg.h"
7a300452 50#include "tree-ssa.h"
232abc3f 51#include "tree-inline.h"
0b9066cf 52#include "cfgloop.h"
dd7bda5e 53#include "fibonacci_heap.h"
8fe17e23 54#include "tracer.h"
5c856b23 55
232abc3f 56static int count_insns (basic_block);
ed7a4b4b 57static bool better_p (const_edge, const_edge);
46c5ad27
AJ
58static edge find_best_successor (basic_block);
59static edge find_best_predecessor (basic_block);
60static int find_trace (basic_block, basic_block *);
5c856b23
JH
61
62/* Minimal outgoing edge probability considered for superblock formation. */
63static int probability_cutoff;
64static int branch_ratio_cutoff;
65
232abc3f
RK
66/* A bit BB->index is set if BB has already been seen, i.e. it is
67 connected to some trace already. */
7ff75c49 68static sbitmap bb_seen;
5c856b23 69
232abc3f
RK
70static inline void
71mark_bb_seen (basic_block bb)
72{
131db6b8 73 unsigned int size = SBITMAP_SIZE (bb_seen);
232abc3f
RK
74
75 if ((unsigned int)bb->index >= size)
76 bb_seen = sbitmap_resize (bb_seen, size * 2, 0);
77
d7c028c0 78 bitmap_set_bit (bb_seen, bb->index);
232abc3f
RK
79}
80
81static inline bool
82bb_seen_p (basic_block bb)
83{
d7c028c0 84 return bitmap_bit_p (bb_seen, bb->index);
232abc3f 85}
5c856b23 86
4b7e68e7 87/* Return true if we should ignore the basic block for purposes of tracing. */
8fe17e23 88bool
ed7a4b4b 89ignore_bb_p (const_basic_block bb)
5c856b23 90{
24bd1a0b 91 if (bb->index < NUM_FIXED_BLOCKS)
5c856b23 92 return true;
efd8f750 93 if (optimize_bb_for_size_p (bb))
5c856b23 94 return true;
2e85d5e2 95
8ab78162
NS
96 if (gimple *g = last_stmt (CONST_CAST_BB (bb)))
97 {
98 /* A transaction is a single entry multiple exit region. It
99 must be duplicated in its entirety or not at all. */
100 if (gimple_code (g) == GIMPLE_TRANSACTION)
101 return true;
102
103 /* An IFN_UNIQUE call must be duplicated as part of its group,
104 or not at all. */
105 if (is_gimple_call (g)
106 && gimple_call_internal_p (g)
107 && gimple_call_internal_unique_p (g))
108 return true;
109 }
2e85d5e2 110
5c856b23
JH
111 return false;
112}
113
114/* Return number of instructions in the block. */
115
116static int
232abc3f 117count_insns (basic_block bb)
5c856b23 118{
726a989a 119 gimple_stmt_iterator gsi;
355fe088 120 gimple *stmt;
5c856b23
JH
121 int n = 0;
122
726a989a 123 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
232abc3f 124 {
726a989a 125 stmt = gsi_stmt (gsi);
232abc3f
RK
126 n += estimate_num_insns (stmt, &eni_size_weights);
127 }
5c856b23
JH
128 return n;
129}
130
131/* Return true if E1 is more frequent than E2. */
132static bool
ed7a4b4b 133better_p (const_edge e1, const_edge e2)
5c856b23 134{
3995f3a2
JH
135 if (e1->count.initialized_p () && e2->count.initialized_p ()
136 && !(e1->count == e2->count))
5c856b23
JH
137 return e1->count > e2->count;
138 if (e1->src->frequency * e1->probability !=
139 e2->src->frequency * e2->probability)
140 return (e1->src->frequency * e1->probability
141 > e2->src->frequency * e2->probability);
142 /* This is needed to avoid changes in the decision after
143 CFG is modified. */
144 if (e1->src != e2->src)
145 return e1->src->index > e2->src->index;
146 return e1->dest->index > e2->dest->index;
147}
148
149/* Return most frequent successor of basic block BB. */
150
151static edge
46c5ad27 152find_best_successor (basic_block bb)
5c856b23
JH
153{
154 edge e;
155 edge best = NULL;
628f6a4e 156 edge_iterator ei;
5c856b23 157
628f6a4e 158 FOR_EACH_EDGE (e, ei, bb->succs)
5c856b23
JH
159 if (!best || better_p (e, best))
160 best = e;
161 if (!best || ignore_bb_p (best->dest))
162 return NULL;
163 if (best->probability <= probability_cutoff)
164 return NULL;
165 return best;
166}
167
168/* Return most frequent predecessor of basic block BB. */
169
170static edge
46c5ad27 171find_best_predecessor (basic_block bb)
5c856b23
JH
172{
173 edge e;
174 edge best = NULL;
628f6a4e 175 edge_iterator ei;
5c856b23 176
628f6a4e 177 FOR_EACH_EDGE (e, ei, bb->preds)
5c856b23
JH
178 if (!best || better_p (e, best))
179 best = e;
180 if (!best || ignore_bb_p (best->src))
181 return NULL;
182 if (EDGE_FREQUENCY (best) * REG_BR_PROB_BASE
183 < bb->frequency * branch_ratio_cutoff)
184 return NULL;
185 return best;
186}
187
188/* Find the trace using bb and record it in the TRACE array.
189 Return number of basic blocks recorded. */
190
191static int
46c5ad27 192find_trace (basic_block bb, basic_block *trace)
5c856b23
JH
193{
194 int i = 0;
195 edge e;
196
c263766c
RH
197 if (dump_file)
198 fprintf (dump_file, "Trace seed %i [%i]", bb->index, bb->frequency);
5c856b23
JH
199
200 while ((e = find_best_predecessor (bb)) != NULL)
201 {
202 basic_block bb2 = e->src;
232abc3f 203 if (bb_seen_p (bb2) || (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX))
5c856b23
JH
204 || find_best_successor (bb2) != e)
205 break;
c263766c
RH
206 if (dump_file)
207 fprintf (dump_file, ",%i [%i]", bb->index, bb->frequency);
5c856b23
JH
208 bb = bb2;
209 }
c263766c
RH
210 if (dump_file)
211 fprintf (dump_file, " forward %i [%i]", bb->index, bb->frequency);
5c856b23
JH
212 trace[i++] = bb;
213
214 /* Follow the trace in forward direction. */
215 while ((e = find_best_successor (bb)) != NULL)
216 {
217 bb = e->dest;
232abc3f 218 if (bb_seen_p (bb) || (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX))
5c856b23
JH
219 || find_best_predecessor (bb) != e)
220 break;
c263766c
RH
221 if (dump_file)
222 fprintf (dump_file, ",%i [%i]", bb->index, bb->frequency);
5c856b23
JH
223 trace[i++] = bb;
224 }
c263766c
RH
225 if (dump_file)
226 fprintf (dump_file, "\n");
5c856b23
JH
227 return i;
228}
229
8fe17e23
AA
230/* Duplicate block BB2, placing it after BB in the CFG. Return the
231 newly created block. */
232basic_block
233transform_duplicate (basic_block bb, basic_block bb2)
234{
235 edge e;
236 basic_block copy;
237
238 e = find_edge (bb, bb2);
239
240 copy = duplicate_block (bb2, e, bb);
241 flush_pending_stmts (e);
242
243 add_phi_args_after_copy (&copy, 1, NULL);
244
245 return (copy);
246}
247
5c856b23
JH
248/* Look for basic blocks in frequency order, construct traces and tail duplicate
249 if profitable. */
250
07b1bf20 251static bool
46c5ad27 252tail_duplicate (void)
5c856b23 253{
dd7bda5e
ML
254 auto_vec<fibonacci_node<long, basic_block_def>*> blocks;
255 blocks.safe_grow_cleared (last_basic_block_for_fn (cfun));
256
0cae8d31 257 basic_block *trace = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun));
8b1c6fd7 258 int *counts = XNEWVEC (int, last_basic_block_for_fn (cfun));
5c856b23
JH
259 int ninsns = 0, nduplicated = 0;
260 gcov_type weighted_insns = 0, traced_insns = 0;
dd7bda5e 261 fibonacci_heap<long, basic_block_def> heap (LONG_MIN);
5c856b23
JH
262 gcov_type cover_insns;
263 int max_dup_insns;
264 basic_block bb;
07b1bf20 265 bool changed = false;
5c856b23 266
232abc3f
RK
267 /* Create an oversized sbitmap to reduce the chance that we need to
268 resize it. */
8b1c6fd7 269 bb_seen = sbitmap_alloc (last_basic_block_for_fn (cfun) * 2);
f61e445a 270 bitmap_clear (bb_seen);
232abc3f
RK
271 initialize_original_copy_tables ();
272
cdb23767 273 if (profile_info && flag_branch_probabilities)
5c856b23
JH
274 probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY_FEEDBACK);
275 else
276 probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY);
277 probability_cutoff = REG_BR_PROB_BASE / 100 * probability_cutoff;
278
279 branch_ratio_cutoff =
280 (REG_BR_PROB_BASE / 100 * PARAM_VALUE (TRACER_MIN_BRANCH_RATIO));
281
11cd3bed 282 FOR_EACH_BB_FN (bb, cfun)
5c856b23
JH
283 {
284 int n = count_insns (bb);
285 if (!ignore_bb_p (bb))
dd7bda5e 286 blocks[bb->index] = heap.insert (-bb->frequency, bb);
5c856b23
JH
287
288 counts [bb->index] = n;
289 ninsns += n;
290 weighted_insns += n * bb->frequency;
291 }
292
cdb23767 293 if (profile_info && flag_branch_probabilities)
5c856b23
JH
294 cover_insns = PARAM_VALUE (TRACER_DYNAMIC_COVERAGE_FEEDBACK);
295 else
296 cover_insns = PARAM_VALUE (TRACER_DYNAMIC_COVERAGE);
297 cover_insns = (weighted_insns * cover_insns + 50) / 100;
298 max_dup_insns = (ninsns * PARAM_VALUE (TRACER_MAX_CODE_GROWTH) + 50) / 100;
299
300 while (traced_insns < cover_insns && nduplicated < max_dup_insns
dd7bda5e 301 && !heap.empty ())
5c856b23 302 {
dd7bda5e 303 basic_block bb = heap.extract_min ();
5c856b23
JH
304 int n, pos;
305
306 if (!bb)
307 break;
308
309 blocks[bb->index] = NULL;
310
311 if (ignore_bb_p (bb))
312 continue;
232abc3f 313 gcc_assert (!bb_seen_p (bb));
5c856b23
JH
314
315 n = find_trace (bb, trace);
316
317 bb = trace[0];
318 traced_insns += bb->frequency * counts [bb->index];
319 if (blocks[bb->index])
320 {
dd7bda5e 321 heap.delete_node (blocks[bb->index]);
5c856b23
JH
322 blocks[bb->index] = NULL;
323 }
324
325 for (pos = 1; pos < n; pos++)
326 {
327 basic_block bb2 = trace[pos];
328
329 if (blocks[bb2->index])
330 {
dd7bda5e 331 heap.delete_node (blocks[bb2->index]);
5c856b23
JH
332 blocks[bb2->index] = NULL;
333 }
334 traced_insns += bb2->frequency * counts [bb2->index];
628f6a4e 335 if (EDGE_COUNT (bb2->preds) > 1
0b9066cf
RG
336 && can_duplicate_block_p (bb2)
337 /* We have the tendency to duplicate the loop header
338 of all do { } while loops. Do not do that - it is
339 not profitable and it might create a loop with multiple
340 entries or at least rotate the loop. */
726338f4 341 && bb2->loop_father->header != bb2)
5c856b23 342 {
232abc3f 343 nduplicated += counts [bb2->index];
8fe17e23 344 basic_block copy = transform_duplicate (bb, bb2);
5c856b23
JH
345
346 /* Reconsider the original copy of block we've duplicated.
14b493d6 347 Removing the most common predecessor may make it to be
5c856b23 348 head. */
dd7bda5e 349 blocks[bb2->index] = heap.insert (-bb2->frequency, bb2);
5c856b23 350
c263766c
RH
351 if (dump_file)
352 fprintf (dump_file, "Duplicated %i as %i [%i]\n",
232abc3f
RK
353 bb2->index, copy->index, copy->frequency);
354
355 bb2 = copy;
07b1bf20 356 changed = true;
5c856b23 357 }
232abc3f 358 mark_bb_seen (bb2);
5c856b23
JH
359 bb = bb2;
360 /* In case the trace became infrequent, stop duplicating. */
361 if (ignore_bb_p (bb))
362 break;
363 }
c263766c
RH
364 if (dump_file)
365 fprintf (dump_file, " covered now %.1f\n\n",
5c856b23
JH
366 traced_insns * 100.0 / weighted_insns);
367 }
c263766c
RH
368 if (dump_file)
369 fprintf (dump_file, "Duplicated %i insns (%i%%)\n", nduplicated,
5c856b23
JH
370 nduplicated * 100 / ninsns);
371
232abc3f
RK
372 free_original_copy_tables ();
373 sbitmap_free (bb_seen);
5c856b23
JH
374 free (trace);
375 free (counts);
07b1bf20
RG
376
377 return changed;
5c856b23 378}
ef330312 379\f
27a4cd48
DM
380namespace {
381
382const pass_data pass_data_tracer =
ef330312 383{
27a4cd48
DM
384 GIMPLE_PASS, /* type */
385 "tracer", /* name */
386 OPTGROUP_NONE, /* optinfo_flags */
27a4cd48
DM
387 TV_TRACER, /* tv_id */
388 0, /* properties_required */
389 0, /* properties_provided */
390 0, /* properties_destroyed */
391 0, /* todo_flags_start */
3bea341f 392 TODO_update_ssa, /* todo_flags_finish */
ef330312 393};
27a4cd48
DM
394
395class pass_tracer : public gimple_opt_pass
396{
397public:
c3284718
RS
398 pass_tracer (gcc::context *ctxt)
399 : gimple_opt_pass (pass_data_tracer, ctxt)
27a4cd48
DM
400 {}
401
402 /* opt_pass methods: */
1a3d085c
TS
403 virtual bool gate (function *)
404 {
405 return (optimize > 0 && flag_tracer && flag_reorder_blocks);
406 }
407
be55bfe6 408 virtual unsigned int execute (function *);
27a4cd48
DM
409
410}; // class pass_tracer
411
be55bfe6
TS
412unsigned int
413pass_tracer::execute (function *fun)
414{
415 bool changed;
416
417 if (n_basic_blocks_for_fn (fun) <= NUM_FIXED_BLOCKS + 1)
418 return 0;
419
420 mark_dfs_back_edges ();
421 if (dump_file)
422 brief_dump_cfg (dump_file, dump_flags);
423
424 /* Trace formation is done on the fly inside tail_duplicate */
425 changed = tail_duplicate ();
426 if (changed)
427 {
428 free_dominance_info (CDI_DOMINATORS);
429 /* If we changed the CFG schedule loops for fixup by cleanup_cfg. */
726338f4 430 loops_state_set (LOOPS_NEED_FIXUP);
be55bfe6
TS
431 }
432
433 if (dump_file)
434 brief_dump_cfg (dump_file, dump_flags);
435
436 return changed ? TODO_cleanup_cfg : 0;
437}
27a4cd48
DM
438} // anon namespace
439
440gimple_opt_pass *
441make_pass_tracer (gcc::context *ctxt)
442{
443 return new pass_tracer (ctxt);
444}