00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "config.h"
00037 #include "system.h"
00038 #include "coretypes.h"
00039 #include "tm.h"
00040 #include "tree.h"
00041 #include "rtl.h"
00042 #include "hard-reg-set.h"
00043 #include "basic-block.h"
00044 #include "output.h"
00045 #include "cfglayout.h"
00046 #include "fibheap.h"
00047 #include "flags.h"
00048 #include "timevar.h"
00049 #include "params.h"
00050 #include "coverage.h"
00051 #include "tree-pass.h"
00052
00053 static int count_insns (basic_block);
00054 static bool ignore_bb_p (basic_block);
00055 static bool better_p (edge, edge);
00056 static edge find_best_successor (basic_block);
00057 static edge find_best_predecessor (basic_block);
00058 static int find_trace (basic_block, basic_block *);
00059 static void tail_duplicate (void);
00060 static void layout_superblocks (void);
00061
00062
00063 static int probability_cutoff;
00064 static int branch_ratio_cutoff;
00065
00066
00067
00068
00069 #define seen(bb) (bb->il.rtl->visited || bb->aux)
00070
00071
00072 static bool
00073 ignore_bb_p (basic_block bb)
00074 {
00075 if (bb->index < NUM_FIXED_BLOCKS)
00076 return true;
00077 if (!maybe_hot_bb_p (bb))
00078 return true;
00079 return false;
00080 }
00081
00082
00083
00084 static int
00085 count_insns (basic_block bb)
00086 {
00087 rtx insn;
00088 int n = 0;
00089
00090 for (insn = BB_HEAD (bb);
00091 insn != NEXT_INSN (BB_END (bb));
00092 insn = NEXT_INSN (insn))
00093 if (active_insn_p (insn))
00094 n++;
00095 return n;
00096 }
00097
00098
00099 static bool
00100 better_p (edge e1, edge e2)
00101 {
00102 if (e1->count != e2->count)
00103 return e1->count > e2->count;
00104 if (e1->src->frequency * e1->probability !=
00105 e2->src->frequency * e2->probability)
00106 return (e1->src->frequency * e1->probability
00107 > e2->src->frequency * e2->probability);
00108
00109
00110 if (e1->src != e2->src)
00111 return e1->src->index > e2->src->index;
00112 return e1->dest->index > e2->dest->index;
00113 }
00114
00115
00116
00117 static edge
00118 find_best_successor (basic_block bb)
00119 {
00120 edge e;
00121 edge best = NULL;
00122 edge_iterator ei;
00123
00124 FOR_EACH_EDGE (e, ei, bb->succs)
00125 if (!best || better_p (e, best))
00126 best = e;
00127 if (!best || ignore_bb_p (best->dest))
00128 return NULL;
00129 if (best->probability <= probability_cutoff)
00130 return NULL;
00131 return best;
00132 }
00133
00134
00135
00136 static edge
00137 find_best_predecessor (basic_block bb)
00138 {
00139 edge e;
00140 edge best = NULL;
00141 edge_iterator ei;
00142
00143 FOR_EACH_EDGE (e, ei, bb->preds)
00144 if (!best || better_p (e, best))
00145 best = e;
00146 if (!best || ignore_bb_p (best->src))
00147 return NULL;
00148 if (EDGE_FREQUENCY (best) * REG_BR_PROB_BASE
00149 < bb->frequency * branch_ratio_cutoff)
00150 return NULL;
00151 return best;
00152 }
00153
00154
00155
00156
00157 static int
00158 find_trace (basic_block bb, basic_block *trace)
00159 {
00160 int i = 0;
00161 edge e;
00162
00163 if (dump_file)
00164 fprintf (dump_file, "Trace seed %i [%i]", bb->index, bb->frequency);
00165
00166 while ((e = find_best_predecessor (bb)) != NULL)
00167 {
00168 basic_block bb2 = e->src;
00169 if (seen (bb2) || (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX))
00170 || find_best_successor (bb2) != e)
00171 break;
00172 if (dump_file)
00173 fprintf (dump_file, ",%i [%i]", bb->index, bb->frequency);
00174 bb = bb2;
00175 }
00176 if (dump_file)
00177 fprintf (dump_file, " forward %i [%i]", bb->index, bb->frequency);
00178 trace[i++] = bb;
00179
00180
00181 while ((e = find_best_successor (bb)) != NULL)
00182 {
00183 bb = e->dest;
00184 if (seen (bb) || (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX))
00185 || find_best_predecessor (bb) != e)
00186 break;
00187 if (dump_file)
00188 fprintf (dump_file, ",%i [%i]", bb->index, bb->frequency);
00189 trace[i++] = bb;
00190 }
00191 if (dump_file)
00192 fprintf (dump_file, "\n");
00193 return i;
00194 }
00195
00196
00197
00198
00199 static void
00200 tail_duplicate (void)
00201 {
00202 fibnode_t *blocks = XCNEWVEC (fibnode_t, last_basic_block);
00203 basic_block *trace = XNEWVEC (basic_block, n_basic_blocks);
00204 int *counts = XNEWVEC (int, last_basic_block);
00205 int ninsns = 0, nduplicated = 0;
00206 gcov_type weighted_insns = 0, traced_insns = 0;
00207 fibheap_t heap = fibheap_new ();
00208 gcov_type cover_insns;
00209 int max_dup_insns;
00210 basic_block bb;
00211
00212 if (profile_info && flag_branch_probabilities)
00213 probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY_FEEDBACK);
00214 else
00215 probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY);
00216 probability_cutoff = REG_BR_PROB_BASE / 100 * probability_cutoff;
00217
00218 branch_ratio_cutoff =
00219 (REG_BR_PROB_BASE / 100 * PARAM_VALUE (TRACER_MIN_BRANCH_RATIO));
00220
00221 FOR_EACH_BB (bb)
00222 {
00223 int n = count_insns (bb);
00224 if (!ignore_bb_p (bb))
00225 blocks[bb->index] = fibheap_insert (heap, -bb->frequency,
00226 bb);
00227
00228 counts [bb->index] = n;
00229 ninsns += n;
00230 weighted_insns += n * bb->frequency;
00231 }
00232
00233 if (profile_info && flag_branch_probabilities)
00234 cover_insns = PARAM_VALUE (TRACER_DYNAMIC_COVERAGE_FEEDBACK);
00235 else
00236 cover_insns = PARAM_VALUE (TRACER_DYNAMIC_COVERAGE);
00237 cover_insns = (weighted_insns * cover_insns + 50) / 100;
00238 max_dup_insns = (ninsns * PARAM_VALUE (TRACER_MAX_CODE_GROWTH) + 50) / 100;
00239
00240 while (traced_insns < cover_insns && nduplicated < max_dup_insns
00241 && !fibheap_empty (heap))
00242 {
00243 basic_block bb = fibheap_extract_min (heap);
00244 int n, pos;
00245
00246 if (!bb)
00247 break;
00248
00249 blocks[bb->index] = NULL;
00250
00251 if (ignore_bb_p (bb))
00252 continue;
00253 gcc_assert (!seen (bb));
00254
00255 n = find_trace (bb, trace);
00256
00257 bb = trace[0];
00258 traced_insns += bb->frequency * counts [bb->index];
00259 if (blocks[bb->index])
00260 {
00261 fibheap_delete_node (heap, blocks[bb->index]);
00262 blocks[bb->index] = NULL;
00263 }
00264
00265 for (pos = 1; pos < n; pos++)
00266 {
00267 basic_block bb2 = trace[pos];
00268
00269 if (blocks[bb2->index])
00270 {
00271 fibheap_delete_node (heap, blocks[bb2->index]);
00272 blocks[bb2->index] = NULL;
00273 }
00274 traced_insns += bb2->frequency * counts [bb2->index];
00275 if (EDGE_COUNT (bb2->preds) > 1
00276 && can_duplicate_block_p (bb2))
00277 {
00278 edge e;
00279 basic_block old = bb2;
00280
00281 e = find_edge (bb, bb2);
00282
00283 nduplicated += counts [bb2->index];
00284 bb2 = duplicate_block (bb2, e, bb);
00285
00286
00287
00288
00289 blocks[old->index] =
00290 fibheap_insert (heap, -old->frequency, old);
00291
00292 if (dump_file)
00293 fprintf (dump_file, "Duplicated %i as %i [%i]\n",
00294 old->index, bb2->index, bb2->frequency);
00295 }
00296 bb->aux = bb2;
00297 bb2->il.rtl->visited = 1;
00298 bb = bb2;
00299
00300 if (ignore_bb_p (bb))
00301 break;
00302 }
00303 if (dump_file)
00304 fprintf (dump_file, " covered now %.1f\n\n",
00305 traced_insns * 100.0 / weighted_insns);
00306 }
00307 if (dump_file)
00308 fprintf (dump_file, "Duplicated %i insns (%i%%)\n", nduplicated,
00309 nduplicated * 100 / ninsns);
00310
00311 free (blocks);
00312 free (trace);
00313 free (counts);
00314 fibheap_delete (heap);
00315 }
00316
00317
00318
00319
00320
00321
00322 static void
00323 layout_superblocks (void)
00324 {
00325 basic_block end = single_succ (ENTRY_BLOCK_PTR);
00326 basic_block bb = end->next_bb;
00327
00328 while (bb != EXIT_BLOCK_PTR)
00329 {
00330 edge_iterator ei;
00331 edge e, best = NULL;
00332 while (end->aux)
00333 end = end->aux;
00334
00335 FOR_EACH_EDGE (e, ei, end->succs)
00336 if (e->dest != EXIT_BLOCK_PTR
00337 && e->dest != single_succ (ENTRY_BLOCK_PTR)
00338 && !e->dest->il.rtl->visited
00339 && (!best || EDGE_FREQUENCY (e) > EDGE_FREQUENCY (best)))
00340 best = e;
00341
00342 if (best)
00343 {
00344 end->aux = best->dest;
00345 best->dest->il.rtl->visited = 1;
00346 }
00347 else
00348 for (; bb != EXIT_BLOCK_PTR; bb = bb->next_bb)
00349 {
00350 if (!bb->il.rtl->visited)
00351 {
00352 end->aux = bb;
00353 bb->il.rtl->visited = 1;
00354 break;
00355 }
00356 }
00357 }
00358 }
00359
00360
00361
00362
00363 void
00364 tracer (unsigned int flags)
00365 {
00366 if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1)
00367 return;
00368
00369 cfg_layout_initialize (flags);
00370 mark_dfs_back_edges ();
00371 if (dump_file)
00372 dump_flow_info (dump_file, dump_flags);
00373 tail_duplicate ();
00374 layout_superblocks ();
00375 if (dump_file)
00376 dump_flow_info (dump_file, dump_flags);
00377 cfg_layout_finalize ();
00378
00379
00380 cleanup_cfg (CLEANUP_EXPENSIVE);
00381 }
00382
00383 static bool
00384 gate_handle_tracer (void)
00385 {
00386 return (optimize > 0 && flag_tracer);
00387 }
00388
00389
00390 static unsigned int
00391 rest_of_handle_tracer (void)
00392 {
00393 if (dump_file)
00394 dump_flow_info (dump_file, dump_flags);
00395 tracer (0);
00396 cleanup_cfg (CLEANUP_EXPENSIVE);
00397 reg_scan (get_insns (), max_reg_num ());
00398 return 0;
00399 }
00400
00401 struct tree_opt_pass pass_tracer =
00402 {
00403 "tracer",
00404 gate_handle_tracer,
00405 rest_of_handle_tracer,
00406 NULL,
00407 NULL,
00408 0,
00409 TV_TRACER,
00410 0,
00411 0,
00412 0,
00413 0,
00414 TODO_dump_func,
00415 'T'
00416 };
00417