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 "tree.h"
00039 #include "rtl.h"
00040 #include "hard-reg-set.h"
00041 #include "basic-block.h"
00042 #include "output.h"
00043 #include "cfglayout.h"
00044 #include "fibheap.h"
00045 #include "flags.h"
00046 #include "params.h"
00047 #include "profile.h"
00048
00049 static int count_insns PARAMS ((basic_block));
00050 static bool ignore_bb_p PARAMS ((basic_block));
00051 static bool better_p PARAMS ((edge, edge));
00052 static edge find_best_successor PARAMS ((basic_block));
00053 static edge find_best_predecessor PARAMS ((basic_block));
00054 static int find_trace PARAMS ((basic_block, basic_block *));
00055 static void tail_duplicate PARAMS ((void));
00056 static void layout_superblocks PARAMS ((void));
00057 static bool ignore_bb_p PARAMS ((basic_block));
00058
00059
00060 static int probability_cutoff;
00061 static int branch_ratio_cutoff;
00062
00063
00064
00065
00066 #define seen(bb) (RBI (bb)->visited || RBI (bb)->next)
00067
00068
00069 static bool
00070 ignore_bb_p (bb)
00071 basic_block bb;
00072 {
00073 if (bb->index < 0)
00074 return true;
00075 if (!maybe_hot_bb_p (bb))
00076 return true;
00077 return false;
00078 }
00079
00080
00081
00082 static int
00083 count_insns (bb)
00084 basic_block bb;
00085 {
00086 rtx insn;
00087 int n = 0;
00088
00089 for (insn = bb->head; insn != NEXT_INSN (bb->end); insn = NEXT_INSN (insn))
00090 if (active_insn_p (insn))
00091 n++;
00092 return n;
00093 }
00094
00095
00096 static bool
00097 better_p (e1, e2)
00098 edge e1, e2;
00099 {
00100 if (e1->count != e2->count)
00101 return e1->count > e2->count;
00102 if (e1->src->frequency * e1->probability !=
00103 e2->src->frequency * e2->probability)
00104 return (e1->src->frequency * e1->probability
00105 > e2->src->frequency * e2->probability);
00106
00107
00108 if (e1->src != e2->src)
00109 return e1->src->index > e2->src->index;
00110 return e1->dest->index > e2->dest->index;
00111 }
00112
00113
00114
00115 static edge
00116 find_best_successor (bb)
00117 basic_block bb;
00118 {
00119 edge e;
00120 edge best = NULL;
00121
00122 for (e = bb->succ; e; e = e->succ_next)
00123 if (!best || better_p (e, best))
00124 best = e;
00125 if (!best || ignore_bb_p (best->dest))
00126 return NULL;
00127 if (best->probability <= probability_cutoff)
00128 return NULL;
00129 return best;
00130 }
00131
00132
00133
00134 static edge
00135 find_best_predecessor (bb)
00136 basic_block bb;
00137 {
00138 edge e;
00139 edge best = NULL;
00140
00141 for (e = bb->pred; e; e = e->pred_next)
00142 if (!best || better_p (e, best))
00143 best = e;
00144 if (!best || ignore_bb_p (best->src))
00145 return NULL;
00146 if (EDGE_FREQUENCY (best) * REG_BR_PROB_BASE
00147 < bb->frequency * branch_ratio_cutoff)
00148 return NULL;
00149 return best;
00150 }
00151
00152
00153
00154
00155 static int
00156 find_trace (bb, trace)
00157 basic_block bb;
00158 basic_block *trace;
00159 {
00160 int i = 0;
00161 edge e;
00162
00163 if (rtl_dump_file)
00164 fprintf (rtl_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 (rtl_dump_file)
00173 fprintf (rtl_dump_file, ",%i [%i]", bb->index, bb->frequency);
00174 bb = bb2;
00175 }
00176 if (rtl_dump_file)
00177 fprintf (rtl_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 (rtl_dump_file)
00188 fprintf (rtl_dump_file, ",%i [%i]", bb->index, bb->frequency);
00189 trace[i++] = bb;
00190 }
00191 if (rtl_dump_file)
00192 fprintf (rtl_dump_file, "\n");
00193 return i;
00194 }
00195
00196
00197
00198
00199 static void
00200 tail_duplicate ()
00201 {
00202 fibnode_t *blocks = xcalloc (last_basic_block, sizeof (fibnode_t));
00203 basic_block *trace = xmalloc (sizeof (basic_block) * n_basic_blocks);
00204 int *counts = xmalloc (sizeof (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.count_profiles_merged && 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.count_profiles_merged && 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 if (seen (bb))
00254 abort ();
00255
00256 n = find_trace (bb, trace);
00257
00258 bb = trace[0];
00259 traced_insns += bb->frequency * counts [bb->index];
00260 if (blocks[bb->index])
00261 {
00262 fibheap_delete_node (heap, blocks[bb->index]);
00263 blocks[bb->index] = NULL;
00264 }
00265
00266 for (pos = 1; pos < n; pos++)
00267 {
00268 basic_block bb2 = trace[pos];
00269
00270 if (blocks[bb2->index])
00271 {
00272 fibheap_delete_node (heap, blocks[bb2->index]);
00273 blocks[bb2->index] = NULL;
00274 }
00275 traced_insns += bb2->frequency * counts [bb2->index];
00276 if (bb2->pred && bb2->pred->pred_next
00277 && cfg_layout_can_duplicate_bb_p (bb2))
00278 {
00279 edge e = bb2->pred;
00280 basic_block old = bb2;
00281
00282 while (e->src != bb)
00283 e = e->pred_next;
00284 nduplicated += counts [bb2->index];
00285 bb2 = cfg_layout_duplicate_bb (bb2, e);
00286
00287
00288
00289
00290 blocks[old->index] =
00291 fibheap_insert (heap, -old->frequency, old);
00292
00293 if (rtl_dump_file)
00294 fprintf (rtl_dump_file, "Duplicated %i as %i [%i]\n",
00295 old->index, bb2->index, bb2->frequency);
00296 }
00297 RBI (bb)->next = bb2;
00298 RBI (bb2)->visited = 1;
00299 bb = bb2;
00300
00301 if (ignore_bb_p (bb))
00302 break;
00303 }
00304 if (rtl_dump_file)
00305 fprintf (rtl_dump_file, " covered now %.1f\n\n",
00306 traced_insns * 100.0 / weighted_insns);
00307 }
00308 if (rtl_dump_file)
00309 fprintf (rtl_dump_file, "Duplicated %i insns (%i%%)\n", nduplicated,
00310 nduplicated * 100 / ninsns);
00311
00312 free (blocks);
00313 free (trace);
00314 free (counts);
00315 fibheap_delete (heap);
00316 }
00317
00318
00319
00320
00321
00322
00323 static void
00324 layout_superblocks ()
00325 {
00326 basic_block end = ENTRY_BLOCK_PTR->succ->dest;
00327 basic_block bb = ENTRY_BLOCK_PTR->succ->dest->next_bb;
00328
00329 while (bb != EXIT_BLOCK_PTR)
00330 {
00331 edge e, best = NULL;
00332 while (RBI (end)->next)
00333 end = RBI (end)->next;
00334
00335 for (e = end->succ; e; e = e->succ_next)
00336 if (e->dest != EXIT_BLOCK_PTR
00337 && e->dest != ENTRY_BLOCK_PTR->succ->dest
00338 && !RBI (e->dest)->visited
00339 && (!best || EDGE_FREQUENCY (e) > EDGE_FREQUENCY (best)))
00340 best = e;
00341
00342 if (best)
00343 {
00344 RBI (end)->next = best->dest;
00345 RBI (best->dest)->visited = 1;
00346 }
00347 else
00348 for (; bb != EXIT_BLOCK_PTR; bb=bb->next_bb)
00349 {
00350 if (!RBI (bb)->visited)
00351 {
00352 RBI (end)->next = bb;
00353 RBI (bb)->visited = 1;
00354 break;
00355 }
00356 }
00357 }
00358 }
00359
00360
00361
00362 void
00363 tracer ()
00364 {
00365 if (n_basic_blocks <= 1)
00366 return;
00367 cfg_layout_initialize ();
00368 mark_dfs_back_edges ();
00369 if (rtl_dump_file)
00370 dump_flow_info (rtl_dump_file);
00371 tail_duplicate ();
00372 layout_superblocks ();
00373 if (rtl_dump_file)
00374 dump_flow_info (rtl_dump_file);
00375 cfg_layout_finalize ();
00376
00377 cleanup_cfg (CLEANUP_EXPENSIVE);
00378 }