* recog.c (asm_operand_ok): Allow float CONST_VECTORs for 'F'.
[official-gcc.git] / gcc / tracer.c
blobc0fbe21ad84a1cdb739cceadf26e194363b74c2e
1 /* The tracer pass for the GNU compiler.
2 Contributed by Jan Hubicka, SuSE Labs.
3 Copyright (C) 2001, 2002 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
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
33 performed. */
36 #include "config.h"
37 #include "system.h"
38 #include "tree.h"
39 #include "rtl.h"
40 #include "hard-reg-set.h"
41 #include "basic-block.h"
42 #include "output.h"
43 #include "cfglayout.h"
44 #include "fibheap.h"
45 #include "flags.h"
46 #include "params.h"
47 #include "profile.h"
49 static int count_insns PARAMS ((basic_block));
50 static bool ignore_bb_p PARAMS ((basic_block));
51 static bool better_p PARAMS ((edge, edge));
52 static edge find_best_successor PARAMS ((basic_block));
53 static edge find_best_predecessor PARAMS ((basic_block));
54 static int find_trace PARAMS ((basic_block, basic_block *));
55 static void tail_duplicate PARAMS ((void));
56 static void layout_superblocks PARAMS ((void));
57 static bool ignore_bb_p PARAMS ((basic_block));
59 /* Minimal outgoing edge probability considered for superblock formation. */
60 static int probability_cutoff;
61 static int branch_ratio_cutoff;
63 /* Return true if BB has been seen - it is connected to some trace
64 already. */
66 #define seen(bb) (RBI (bb)->visited || RBI (bb)->next)
68 /* Return true if we should ignore the basic block for purposes of tracing. */
69 static bool
70 ignore_bb_p (bb)
71 basic_block bb;
73 if (bb->index < 0)
74 return true;
75 if (!maybe_hot_bb_p (bb))
76 return true;
77 return false;
80 /* Return number of instructions in the block. */
82 static int
83 count_insns (bb)
84 basic_block bb;
86 rtx insn;
87 int n = 0;
89 for (insn = bb->head; insn != NEXT_INSN (bb->end); insn = NEXT_INSN (insn))
90 if (active_insn_p (insn))
91 n++;
92 return n;
95 /* Return true if E1 is more frequent than E2. */
96 static bool
97 better_p (e1, e2)
98 edge e1, e2;
100 if (e1->count != e2->count)
101 return e1->count > e2->count;
102 if (e1->src->frequency * e1->probability !=
103 e2->src->frequency * e2->probability)
104 return (e1->src->frequency * e1->probability
105 > e2->src->frequency * e2->probability);
106 /* This is needed to avoid changes in the decision after
107 CFG is modified. */
108 if (e1->src != e2->src)
109 return e1->src->index > e2->src->index;
110 return e1->dest->index > e2->dest->index;
113 /* Return most frequent successor of basic block BB. */
115 static edge
116 find_best_successor (bb)
117 basic_block bb;
119 edge e;
120 edge best = NULL;
122 for (e = bb->succ; e; e = e->succ_next)
123 if (!best || better_p (e, best))
124 best = e;
125 if (!best || ignore_bb_p (best->dest))
126 return NULL;
127 if (best->probability <= probability_cutoff)
128 return NULL;
129 return best;
132 /* Return most frequent predecessor of basic block BB. */
134 static edge
135 find_best_predecessor (bb)
136 basic_block bb;
138 edge e;
139 edge best = NULL;
141 for (e = bb->pred; e; e = e->pred_next)
142 if (!best || better_p (e, best))
143 best = e;
144 if (!best || ignore_bb_p (best->src))
145 return NULL;
146 if (EDGE_FREQUENCY (best) * REG_BR_PROB_BASE
147 < bb->frequency * branch_ratio_cutoff)
148 return NULL;
149 return best;
152 /* Find the trace using bb and record it in the TRACE array.
153 Return number of basic blocks recorded. */
155 static int
156 find_trace (bb, trace)
157 basic_block bb;
158 basic_block *trace;
160 int i = 0;
161 edge e;
163 if (rtl_dump_file)
164 fprintf (rtl_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)
171 break;
172 if (rtl_dump_file)
173 fprintf (rtl_dump_file, ",%i [%i]", bb->index, bb->frequency);
174 bb = bb2;
176 if (rtl_dump_file)
177 fprintf (rtl_dump_file, " forward %i [%i]", bb->index, bb->frequency);
178 trace[i++] = bb;
180 /* Follow the trace in forward direction. */
181 while ((e = find_best_successor (bb)) != NULL)
183 bb = e->dest;
184 if (seen (bb) || (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX))
185 || find_best_predecessor (bb) != e)
186 break;
187 if (rtl_dump_file)
188 fprintf (rtl_dump_file, ",%i [%i]", bb->index, bb->frequency);
189 trace[i++] = bb;
191 if (rtl_dump_file)
192 fprintf (rtl_dump_file, "\n");
193 return i;
196 /* Look for basic blocks in frequency order, construct traces and tail duplicate
197 if profitable. */
199 static void
200 tail_duplicate ()
202 fibnode_t *blocks = xcalloc (last_basic_block, sizeof (fibnode_t));
203 basic_block *trace = xmalloc (sizeof (basic_block) * n_basic_blocks);
204 int *counts = xmalloc (sizeof (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;
209 int max_dup_insns;
210 basic_block bb;
212 if (profile_info.count_profiles_merged && flag_branch_probabilities)
213 probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY_FEEDBACK);
214 else
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));
221 FOR_EACH_BB (bb)
223 int n = count_insns (bb);
224 if (!ignore_bb_p (bb))
225 blocks[bb->index] = fibheap_insert (heap, -bb->frequency,
226 bb);
228 counts [bb->index] = n;
229 ninsns += n;
230 weighted_insns += n * bb->frequency;
233 if (profile_info.count_profiles_merged && flag_branch_probabilities)
234 cover_insns = PARAM_VALUE (TRACER_DYNAMIC_COVERAGE_FEEDBACK);
235 else
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);
244 int n, pos;
246 if (!bb)
247 break;
249 blocks[bb->index] = NULL;
251 if (ignore_bb_p (bb))
252 continue;
253 if (seen (bb))
254 abort ();
256 n = find_trace (bb, trace);
258 bb = trace[0];
259 traced_insns += bb->frequency * counts [bb->index];
260 if (blocks[bb->index])
262 fibheap_delete_node (heap, blocks[bb->index]);
263 blocks[bb->index] = NULL;
266 for (pos = 1; pos < n; pos++)
268 basic_block bb2 = trace[pos];
270 if (blocks[bb2->index])
272 fibheap_delete_node (heap, blocks[bb2->index]);
273 blocks[bb2->index] = NULL;
275 traced_insns += bb2->frequency * counts [bb2->index];
276 if (bb2->pred && bb2->pred->pred_next
277 && cfg_layout_can_duplicate_bb_p (bb2))
279 edge e = bb2->pred;
280 basic_block old = bb2;
282 while (e->src != bb)
283 e = e->pred_next;
284 nduplicated += counts [bb2->index];
285 bb2 = cfg_layout_duplicate_bb (bb2, e);
287 /* Reconsider the original copy of block we've duplicated.
288 Removing the most common predecesor may make it to be
289 head. */
290 blocks[old->index] =
291 fibheap_insert (heap, -old->frequency, old);
293 if (rtl_dump_file)
294 fprintf (rtl_dump_file, "Duplicated %i as %i [%i]\n",
295 old->index, bb2->index, bb2->frequency);
297 RBI (bb)->next = bb2;
298 RBI (bb2)->visited = 1;
299 bb = bb2;
300 /* In case the trace became infrequent, stop duplicating. */
301 if (ignore_bb_p (bb))
302 break;
304 if (rtl_dump_file)
305 fprintf (rtl_dump_file, " covered now %.1f\n\n",
306 traced_insns * 100.0 / weighted_insns);
308 if (rtl_dump_file)
309 fprintf (rtl_dump_file, "Duplicated %i insns (%i%%)\n", nduplicated,
310 nduplicated * 100 / ninsns);
312 free (blocks);
313 free (trace);
314 free (counts);
315 fibheap_delete (heap);
318 /* Connect the superblocks into linear seuqence. At the moment we attempt to keep
319 the original order as much as possible, but the algorithm may be made smarter
320 later if needed. BB reordering pass should void most of the benefits of such
321 change though. */
323 static void
324 layout_superblocks ()
326 basic_block end = ENTRY_BLOCK_PTR->succ->dest;
327 basic_block bb = ENTRY_BLOCK_PTR->succ->dest->next_bb;
329 while (bb != EXIT_BLOCK_PTR)
331 edge e, best = NULL;
332 while (RBI (end)->next)
333 end = RBI (end)->next;
335 for (e = end->succ; e; e = e->succ_next)
336 if (e->dest != EXIT_BLOCK_PTR
337 && e->dest != ENTRY_BLOCK_PTR->succ->dest
338 && !RBI (e->dest)->visited
339 && (!best || EDGE_FREQUENCY (e) > EDGE_FREQUENCY (best)))
340 best = e;
342 if (best)
344 RBI (end)->next = best->dest;
345 RBI (best->dest)->visited = 1;
347 else
348 for (; bb != EXIT_BLOCK_PTR; bb=bb->next_bb)
350 if (!RBI (bb)->visited)
352 RBI (end)->next = bb;
353 RBI (bb)->visited = 1;
354 break;
360 /* Main entry point to this file. */
362 void
363 tracer ()
365 if (n_basic_blocks <= 1)
366 return;
367 cfg_layout_initialize ();
368 mark_dfs_back_edges ();
369 if (rtl_dump_file)
370 dump_flow_info (rtl_dump_file);
371 tail_duplicate ();
372 layout_superblocks ();
373 if (rtl_dump_file)
374 dump_flow_info (rtl_dump_file);
375 cfg_layout_finalize ();
376 /* Merge basic blocks in duplicated traces. */
377 cleanup_cfg (CLEANUP_EXPENSIVE);