]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/tracer.c
fix PR68343: disable fuse-*.c tests for isl 0.14 or earlier
[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.
818ab71a 4 Copyright (C) 2001-2016 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. */
68sbitmap 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
JH
134{
135 if (e1->count != e2->count)
136 return e1->count > e2->count;
137 if (e1->src->frequency * e1->probability !=
138 e2->src->frequency * e2->probability)
139 return (e1->src->frequency * e1->probability
140 > e2->src->frequency * e2->probability);
141 /* This is needed to avoid changes in the decision after
142 CFG is modified. */
143 if (e1->src != e2->src)
144 return e1->src->index > e2->src->index;
145 return e1->dest->index > e2->dest->index;
146}
147
148/* Return most frequent successor of basic block BB. */
149
150static edge
46c5ad27 151find_best_successor (basic_block bb)
5c856b23
JH
152{
153 edge e;
154 edge best = NULL;
628f6a4e 155 edge_iterator ei;
5c856b23 156
628f6a4e 157 FOR_EACH_EDGE (e, ei, bb->succs)
5c856b23
JH
158 if (!best || better_p (e, best))
159 best = e;
160 if (!best || ignore_bb_p (best->dest))
161 return NULL;
162 if (best->probability <= probability_cutoff)
163 return NULL;
164 return best;
165}
166
167/* Return most frequent predecessor of basic block BB. */
168
169static edge
46c5ad27 170find_best_predecessor (basic_block bb)
5c856b23
JH
171{
172 edge e;
173 edge best = NULL;
628f6a4e 174 edge_iterator ei;
5c856b23 175
628f6a4e 176 FOR_EACH_EDGE (e, ei, bb->preds)
5c856b23
JH
177 if (!best || better_p (e, best))
178 best = e;
179 if (!best || ignore_bb_p (best->src))
180 return NULL;
181 if (EDGE_FREQUENCY (best) * REG_BR_PROB_BASE
182 < bb->frequency * branch_ratio_cutoff)
183 return NULL;
184 return best;
185}
186
187/* Find the trace using bb and record it in the TRACE array.
188 Return number of basic blocks recorded. */
189
190static int
46c5ad27 191find_trace (basic_block bb, basic_block *trace)
5c856b23
JH
192{
193 int i = 0;
194 edge e;
195
c263766c
RH
196 if (dump_file)
197 fprintf (dump_file, "Trace seed %i [%i]", bb->index, bb->frequency);
5c856b23
JH
198
199 while ((e = find_best_predecessor (bb)) != NULL)
200 {
201 basic_block bb2 = e->src;
232abc3f 202 if (bb_seen_p (bb2) || (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX))
5c856b23
JH
203 || find_best_successor (bb2) != e)
204 break;
c263766c
RH
205 if (dump_file)
206 fprintf (dump_file, ",%i [%i]", bb->index, bb->frequency);
5c856b23
JH
207 bb = bb2;
208 }
c263766c
RH
209 if (dump_file)
210 fprintf (dump_file, " forward %i [%i]", bb->index, bb->frequency);
5c856b23
JH
211 trace[i++] = bb;
212
213 /* Follow the trace in forward direction. */
214 while ((e = find_best_successor (bb)) != NULL)
215 {
216 bb = e->dest;
232abc3f 217 if (bb_seen_p (bb) || (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX))
5c856b23
JH
218 || find_best_predecessor (bb) != e)
219 break;
c263766c
RH
220 if (dump_file)
221 fprintf (dump_file, ",%i [%i]", bb->index, bb->frequency);
5c856b23
JH
222 trace[i++] = bb;
223 }
c263766c
RH
224 if (dump_file)
225 fprintf (dump_file, "\n");
5c856b23
JH
226 return i;
227}
228
8fe17e23
AA
229/* Duplicate block BB2, placing it after BB in the CFG. Return the
230 newly created block. */
231basic_block
232transform_duplicate (basic_block bb, basic_block bb2)
233{
234 edge e;
235 basic_block copy;
236
237 e = find_edge (bb, bb2);
238
239 copy = duplicate_block (bb2, e, bb);
240 flush_pending_stmts (e);
241
242 add_phi_args_after_copy (&copy, 1, NULL);
243
244 return (copy);
245}
246
5c856b23
JH
247/* Look for basic blocks in frequency order, construct traces and tail duplicate
248 if profitable. */
249
07b1bf20 250static bool
46c5ad27 251tail_duplicate (void)
5c856b23 252{
dd7bda5e
ML
253 auto_vec<fibonacci_node<long, basic_block_def>*> blocks;
254 blocks.safe_grow_cleared (last_basic_block_for_fn (cfun));
255
0cae8d31 256 basic_block *trace = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun));
8b1c6fd7 257 int *counts = XNEWVEC (int, last_basic_block_for_fn (cfun));
5c856b23
JH
258 int ninsns = 0, nduplicated = 0;
259 gcov_type weighted_insns = 0, traced_insns = 0;
dd7bda5e 260 fibonacci_heap<long, basic_block_def> heap (LONG_MIN);
5c856b23
JH
261 gcov_type cover_insns;
262 int max_dup_insns;
263 basic_block bb;
07b1bf20 264 bool changed = false;
5c856b23 265
232abc3f
RK
266 /* Create an oversized sbitmap to reduce the chance that we need to
267 resize it. */
8b1c6fd7 268 bb_seen = sbitmap_alloc (last_basic_block_for_fn (cfun) * 2);
f61e445a 269 bitmap_clear (bb_seen);
232abc3f
RK
270 initialize_original_copy_tables ();
271
cdb23767 272 if (profile_info && flag_branch_probabilities)
5c856b23
JH
273 probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY_FEEDBACK);
274 else
275 probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY);
276 probability_cutoff = REG_BR_PROB_BASE / 100 * probability_cutoff;
277
278 branch_ratio_cutoff =
279 (REG_BR_PROB_BASE / 100 * PARAM_VALUE (TRACER_MIN_BRANCH_RATIO));
280
11cd3bed 281 FOR_EACH_BB_FN (bb, cfun)
5c856b23
JH
282 {
283 int n = count_insns (bb);
284 if (!ignore_bb_p (bb))
dd7bda5e 285 blocks[bb->index] = heap.insert (-bb->frequency, bb);
5c856b23
JH
286
287 counts [bb->index] = n;
288 ninsns += n;
289 weighted_insns += n * bb->frequency;
290 }
291
cdb23767 292 if (profile_info && flag_branch_probabilities)
5c856b23
JH
293 cover_insns = PARAM_VALUE (TRACER_DYNAMIC_COVERAGE_FEEDBACK);
294 else
295 cover_insns = PARAM_VALUE (TRACER_DYNAMIC_COVERAGE);
296 cover_insns = (weighted_insns * cover_insns + 50) / 100;
297 max_dup_insns = (ninsns * PARAM_VALUE (TRACER_MAX_CODE_GROWTH) + 50) / 100;
298
299 while (traced_insns < cover_insns && nduplicated < max_dup_insns
dd7bda5e 300 && !heap.empty ())
5c856b23 301 {
dd7bda5e 302 basic_block bb = heap.extract_min ();
5c856b23
JH
303 int n, pos;
304
305 if (!bb)
306 break;
307
308 blocks[bb->index] = NULL;
309
310 if (ignore_bb_p (bb))
311 continue;
232abc3f 312 gcc_assert (!bb_seen_p (bb));
5c856b23
JH
313
314 n = find_trace (bb, trace);
315
316 bb = trace[0];
317 traced_insns += bb->frequency * counts [bb->index];
318 if (blocks[bb->index])
319 {
dd7bda5e 320 heap.delete_node (blocks[bb->index]);
5c856b23
JH
321 blocks[bb->index] = NULL;
322 }
323
324 for (pos = 1; pos < n; pos++)
325 {
326 basic_block bb2 = trace[pos];
327
328 if (blocks[bb2->index])
329 {
dd7bda5e 330 heap.delete_node (blocks[bb2->index]);
5c856b23
JH
331 blocks[bb2->index] = NULL;
332 }
333 traced_insns += bb2->frequency * counts [bb2->index];
628f6a4e 334 if (EDGE_COUNT (bb2->preds) > 1
0b9066cf
RG
335 && can_duplicate_block_p (bb2)
336 /* We have the tendency to duplicate the loop header
337 of all do { } while loops. Do not do that - it is
338 not profitable and it might create a loop with multiple
339 entries or at least rotate the loop. */
726338f4 340 && bb2->loop_father->header != bb2)
5c856b23 341 {
232abc3f 342 nduplicated += counts [bb2->index];
8fe17e23 343 basic_block copy = transform_duplicate (bb, bb2);
5c856b23
JH
344
345 /* Reconsider the original copy of block we've duplicated.
14b493d6 346 Removing the most common predecessor may make it to be
5c856b23 347 head. */
dd7bda5e 348 blocks[bb2->index] = heap.insert (-bb2->frequency, bb2);
5c856b23 349
c263766c
RH
350 if (dump_file)
351 fprintf (dump_file, "Duplicated %i as %i [%i]\n",
232abc3f
RK
352 bb2->index, copy->index, copy->frequency);
353
354 bb2 = copy;
07b1bf20 355 changed = true;
5c856b23 356 }
232abc3f 357 mark_bb_seen (bb2);
5c856b23
JH
358 bb = bb2;
359 /* In case the trace became infrequent, stop duplicating. */
360 if (ignore_bb_p (bb))
361 break;
362 }
c263766c
RH
363 if (dump_file)
364 fprintf (dump_file, " covered now %.1f\n\n",
5c856b23
JH
365 traced_insns * 100.0 / weighted_insns);
366 }
c263766c
RH
367 if (dump_file)
368 fprintf (dump_file, "Duplicated %i insns (%i%%)\n", nduplicated,
5c856b23
JH
369 nduplicated * 100 / ninsns);
370
232abc3f
RK
371 free_original_copy_tables ();
372 sbitmap_free (bb_seen);
5c856b23
JH
373 free (trace);
374 free (counts);
07b1bf20
RG
375
376 return changed;
5c856b23 377}
ef330312 378\f
27a4cd48
DM
379namespace {
380
381const pass_data pass_data_tracer =
ef330312 382{
27a4cd48
DM
383 GIMPLE_PASS, /* type */
384 "tracer", /* name */
385 OPTGROUP_NONE, /* optinfo_flags */
27a4cd48
DM
386 TV_TRACER, /* tv_id */
387 0, /* properties_required */
388 0, /* properties_provided */
389 0, /* properties_destroyed */
390 0, /* todo_flags_start */
3bea341f 391 TODO_update_ssa, /* todo_flags_finish */
ef330312 392};
27a4cd48
DM
393
394class pass_tracer : public gimple_opt_pass
395{
396public:
c3284718
RS
397 pass_tracer (gcc::context *ctxt)
398 : gimple_opt_pass (pass_data_tracer, ctxt)
27a4cd48
DM
399 {}
400
401 /* opt_pass methods: */
1a3d085c
TS
402 virtual bool gate (function *)
403 {
404 return (optimize > 0 && flag_tracer && flag_reorder_blocks);
405 }
406
be55bfe6 407 virtual unsigned int execute (function *);
27a4cd48
DM
408
409}; // class pass_tracer
410
be55bfe6
TS
411unsigned int
412pass_tracer::execute (function *fun)
413{
414 bool changed;
415
416 if (n_basic_blocks_for_fn (fun) <= NUM_FIXED_BLOCKS + 1)
417 return 0;
418
419 mark_dfs_back_edges ();
420 if (dump_file)
421 brief_dump_cfg (dump_file, dump_flags);
422
423 /* Trace formation is done on the fly inside tail_duplicate */
424 changed = tail_duplicate ();
425 if (changed)
426 {
427 free_dominance_info (CDI_DOMINATORS);
428 /* If we changed the CFG schedule loops for fixup by cleanup_cfg. */
726338f4 429 loops_state_set (LOOPS_NEED_FIXUP);
be55bfe6
TS
430 }
431
432 if (dump_file)
433 brief_dump_cfg (dump_file, dump_flags);
434
435 return changed ? TODO_cleanup_cfg : 0;
436}
27a4cd48
DM
437} // anon namespace
438
439gimple_opt_pass *
440make_pass_tracer (gcc::context *ctxt)
441{
442 return new pass_tracer (ctxt);
443}