1 /* The tracer pass for the GNU compiler.
2 Contributed by Jan Hubicka, SuSE Labs.
3 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007
4 Free Software Foundation, Inc.
6 This file is part of GCC.
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
10 the Free Software Foundation; either version 3, or (at your option)
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.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 /* This pass performs the tail duplication needed for superblock formation.
23 For more information see:
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
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
38 #include "coretypes.h"
42 #include "hard-reg-set.h"
43 #include "basic-block.h"
45 #include "cfglayout.h"
51 #include "tree-pass.h"
53 static int count_insns (basic_block
);
54 static bool ignore_bb_p (basic_block
);
55 static bool better_p (edge
, edge
);
56 static edge
find_best_successor (basic_block
);
57 static edge
find_best_predecessor (basic_block
);
58 static int find_trace (basic_block
, basic_block
*);
59 static void tail_duplicate (void);
60 static void layout_superblocks (void);
62 /* Minimal outgoing edge probability considered for superblock formation. */
63 static int probability_cutoff
;
64 static int branch_ratio_cutoff
;
66 /* Return true if BB has been seen - it is connected to some trace
69 #define seen(bb) (bb->il.rtl->visited || bb->aux)
71 /* Return true if we should ignore the basic block for purposes of tracing. */
73 ignore_bb_p (basic_block bb
)
75 if (bb
->index
< NUM_FIXED_BLOCKS
)
77 if (!maybe_hot_bb_p (bb
))
82 /* Return number of instructions in the block. */
85 count_insns (basic_block bb
)
90 for (insn
= BB_HEAD (bb
);
91 insn
!= NEXT_INSN (BB_END (bb
));
92 insn
= NEXT_INSN (insn
))
93 if (active_insn_p (insn
))
98 /* Return true if E1 is more frequent than E2. */
100 better_p (edge e1
, edge e2
)
102 if (e1
->count
!= e2
->count
)
103 return e1
->count
> e2
->count
;
104 if (e1
->src
->frequency
* e1
->probability
!=
105 e2
->src
->frequency
* e2
->probability
)
106 return (e1
->src
->frequency
* e1
->probability
107 > e2
->src
->frequency
* e2
->probability
);
108 /* This is needed to avoid changes in the decision after
110 if (e1
->src
!= e2
->src
)
111 return e1
->src
->index
> e2
->src
->index
;
112 return e1
->dest
->index
> e2
->dest
->index
;
115 /* Return most frequent successor of basic block BB. */
118 find_best_successor (basic_block bb
)
124 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
125 if (!best
|| better_p (e
, best
))
127 if (!best
|| ignore_bb_p (best
->dest
))
129 if (best
->probability
<= probability_cutoff
)
134 /* Return most frequent predecessor of basic block BB. */
137 find_best_predecessor (basic_block bb
)
143 FOR_EACH_EDGE (e
, ei
, bb
->preds
)
144 if (!best
|| better_p (e
, best
))
146 if (!best
|| ignore_bb_p (best
->src
))
148 if (EDGE_FREQUENCY (best
) * REG_BR_PROB_BASE
149 < bb
->frequency
* branch_ratio_cutoff
)
154 /* Find the trace using bb and record it in the TRACE array.
155 Return number of basic blocks recorded. */
158 find_trace (basic_block bb
, basic_block
*trace
)
164 fprintf (dump_file
, "Trace seed %i [%i]", bb
->index
, bb
->frequency
);
166 while ((e
= find_best_predecessor (bb
)) != NULL
)
168 basic_block bb2
= e
->src
;
169 if (seen (bb2
) || (e
->flags
& (EDGE_DFS_BACK
| EDGE_COMPLEX
))
170 || find_best_successor (bb2
) != e
)
173 fprintf (dump_file
, ",%i [%i]", bb
->index
, bb
->frequency
);
177 fprintf (dump_file
, " forward %i [%i]", bb
->index
, bb
->frequency
);
180 /* Follow the trace in forward direction. */
181 while ((e
= find_best_successor (bb
)) != NULL
)
184 if (seen (bb
) || (e
->flags
& (EDGE_DFS_BACK
| EDGE_COMPLEX
))
185 || find_best_predecessor (bb
) != e
)
188 fprintf (dump_file
, ",%i [%i]", bb
->index
, bb
->frequency
);
192 fprintf (dump_file
, "\n");
196 /* Look for basic blocks in frequency order, construct traces and tail duplicate
200 tail_duplicate (void)
202 fibnode_t
*blocks
= XCNEWVEC (fibnode_t
, last_basic_block
);
203 basic_block
*trace
= XNEWVEC (basic_block
, n_basic_blocks
);
204 int *counts
= XNEWVEC (int, last_basic_block
);
205 int ninsns
= 0, nduplicated
= 0;
206 gcov_type weighted_insns
= 0, traced_insns
= 0;
207 fibheap_t heap
= fibheap_new ();
208 gcov_type cover_insns
;
212 if (profile_info
&& flag_branch_probabilities
)
213 probability_cutoff
= PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY_FEEDBACK
);
215 probability_cutoff
= PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY
);
216 probability_cutoff
= REG_BR_PROB_BASE
/ 100 * probability_cutoff
;
218 branch_ratio_cutoff
=
219 (REG_BR_PROB_BASE
/ 100 * PARAM_VALUE (TRACER_MIN_BRANCH_RATIO
));
223 int n
= count_insns (bb
);
224 if (!ignore_bb_p (bb
))
225 blocks
[bb
->index
] = fibheap_insert (heap
, -bb
->frequency
,
228 counts
[bb
->index
] = n
;
230 weighted_insns
+= n
* bb
->frequency
;
233 if (profile_info
&& flag_branch_probabilities
)
234 cover_insns
= PARAM_VALUE (TRACER_DYNAMIC_COVERAGE_FEEDBACK
);
236 cover_insns
= PARAM_VALUE (TRACER_DYNAMIC_COVERAGE
);
237 cover_insns
= (weighted_insns
* cover_insns
+ 50) / 100;
238 max_dup_insns
= (ninsns
* PARAM_VALUE (TRACER_MAX_CODE_GROWTH
) + 50) / 100;
240 while (traced_insns
< cover_insns
&& nduplicated
< max_dup_insns
241 && !fibheap_empty (heap
))
243 basic_block bb
= fibheap_extract_min (heap
);
249 blocks
[bb
->index
] = NULL
;
251 if (ignore_bb_p (bb
))
253 gcc_assert (!seen (bb
));
255 n
= find_trace (bb
, trace
);
258 traced_insns
+= bb
->frequency
* counts
[bb
->index
];
259 if (blocks
[bb
->index
])
261 fibheap_delete_node (heap
, blocks
[bb
->index
]);
262 blocks
[bb
->index
] = NULL
;
265 for (pos
= 1; pos
< n
; pos
++)
267 basic_block bb2
= trace
[pos
];
269 if (blocks
[bb2
->index
])
271 fibheap_delete_node (heap
, blocks
[bb2
->index
]);
272 blocks
[bb2
->index
] = NULL
;
274 traced_insns
+= bb2
->frequency
* counts
[bb2
->index
];
275 if (EDGE_COUNT (bb2
->preds
) > 1
276 && can_duplicate_block_p (bb2
))
279 basic_block old
= bb2
;
281 e
= find_edge (bb
, bb2
);
283 nduplicated
+= counts
[bb2
->index
];
284 bb2
= duplicate_block (bb2
, e
, bb
);
286 /* Reconsider the original copy of block we've duplicated.
287 Removing the most common predecessor may make it to be
290 fibheap_insert (heap
, -old
->frequency
, old
);
293 fprintf (dump_file
, "Duplicated %i as %i [%i]\n",
294 old
->index
, bb2
->index
, bb2
->frequency
);
297 bb2
->il
.rtl
->visited
= 1;
299 /* In case the trace became infrequent, stop duplicating. */
300 if (ignore_bb_p (bb
))
304 fprintf (dump_file
, " covered now %.1f\n\n",
305 traced_insns
* 100.0 / weighted_insns
);
308 fprintf (dump_file
, "Duplicated %i insns (%i%%)\n", nduplicated
,
309 nduplicated
* 100 / ninsns
);
314 fibheap_delete (heap
);
317 /* Connect the superblocks into linear sequence. At the moment we attempt to keep
318 the original order as much as possible, but the algorithm may be made smarter
319 later if needed. BB reordering pass should void most of the benefits of such
323 layout_superblocks (void)
325 basic_block end
= single_succ (ENTRY_BLOCK_PTR
);
326 basic_block bb
= end
->next_bb
;
328 while (bb
!= EXIT_BLOCK_PTR
)
335 FOR_EACH_EDGE (e
, ei
, end
->succs
)
336 if (e
->dest
!= EXIT_BLOCK_PTR
337 && e
->dest
!= single_succ (ENTRY_BLOCK_PTR
)
338 && !e
->dest
->il
.rtl
->visited
339 && (!best
|| EDGE_FREQUENCY (e
) > EDGE_FREQUENCY (best
)))
344 end
->aux
= best
->dest
;
345 best
->dest
->il
.rtl
->visited
= 1;
348 for (; bb
!= EXIT_BLOCK_PTR
; bb
= bb
->next_bb
)
350 if (!bb
->il
.rtl
->visited
)
353 bb
->il
.rtl
->visited
= 1;
360 /* Main entry point to this file. FLAGS is the set of flags to pass
361 to cfg_layout_initialize(). */
364 tracer (unsigned int flags
)
366 if (n_basic_blocks
<= NUM_FIXED_BLOCKS
+ 1)
369 cfg_layout_initialize (flags
);
370 mark_dfs_back_edges ();
372 dump_flow_info (dump_file
, dump_flags
);
374 layout_superblocks ();
376 dump_flow_info (dump_file
, dump_flags
);
377 cfg_layout_finalize ();
379 /* Merge basic blocks in duplicated traces. */
380 cleanup_cfg (CLEANUP_EXPENSIVE
);
384 gate_handle_tracer (void)
386 return (optimize
> 0 && flag_tracer
);
391 rest_of_handle_tracer (void)
394 dump_flow_info (dump_file
, dump_flags
);
396 cleanup_cfg (CLEANUP_EXPENSIVE
);
397 reg_scan (get_insns (), max_reg_num ());
401 struct tree_opt_pass pass_tracer
=
404 gate_handle_tracer
, /* gate */
405 rest_of_handle_tracer
, /* execute */
408 0, /* static_pass_number */
409 TV_TRACER
, /* tv_id */
410 0, /* properties_required */
411 0, /* properties_provided */
412 0, /* properties_destroyed */
413 0, /* todo_flags_start */
414 TODO_dump_func
, /* todo_flags_finish */