00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "system.h"
00023 #include "coretypes.h"
00024 #include "tm.h"
00025 #include "rtl.h"
00026 #include "hard-reg-set.h"
00027 #include "obstack.h"
00028 #include "basic-block.h"
00029 #include "cfgloop.h"
00030 #include "expr.h"
00031 #include "output.h"
00032
00033
00034
00035 bool
00036 just_once_each_iteration_p (struct loop *loop, basic_block bb)
00037 {
00038
00039 if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb))
00040 return false;
00041
00042
00043 if (bb->loop_father != loop)
00044 return false;
00045
00046
00047 if (bb->flags & BB_IRREDUCIBLE_LOOP)
00048 return false;
00049
00050 return true;
00051 }
00052
00053
00054
00055 struct edge
00056 {
00057 int src, dest;
00058 struct edge *pred_next, *succ_next;
00059
00060 void *data;
00061 };
00062
00063
00064
00065 struct vertex
00066 {
00067 struct edge *pred, *succ;
00068
00069 int component;
00070
00071 int post;
00072 };
00073
00074
00075
00076 struct graph
00077 {
00078 int n_vertices;
00079 struct vertex *vertices;
00080
00081 };
00082
00083
00084
00085 extern void dump_graph (FILE *, struct graph *);
00086 void dump_graph (FILE *f, struct graph *g)
00087 {
00088 int i;
00089 struct edge *e;
00090
00091 for (i = 0; i < g->n_vertices; i++)
00092 {
00093 if (!g->vertices[i].pred
00094 && !g->vertices[i].succ)
00095 continue;
00096
00097 fprintf (f, "%d (%d)\t<-", i, g->vertices[i].component);
00098 for (e = g->vertices[i].pred; e; e = e->pred_next)
00099 fprintf (f, " %d", e->src);
00100 fprintf (f, "\n");
00101
00102 fprintf (f, "\t->");
00103 for (e = g->vertices[i].succ; e; e = e->succ_next)
00104 fprintf (f, " %d", e->dest);
00105 fprintf (f, "\n");
00106 }
00107 }
00108
00109
00110
00111 static struct graph *
00112 new_graph (int n_vertices)
00113 {
00114 struct graph *g = xmalloc (sizeof (struct graph));
00115
00116 g->n_vertices = n_vertices;
00117 g->vertices = xcalloc (n_vertices, sizeof (struct vertex));
00118
00119 return g;
00120 }
00121
00122
00123
00124 static void
00125 add_edge (struct graph *g, int f, int t, void *data)
00126 {
00127 struct edge *e = xmalloc (sizeof (struct edge));
00128
00129 e->src = f;
00130 e->dest = t;
00131 e->data = data;
00132
00133 e->pred_next = g->vertices[t].pred;
00134 g->vertices[t].pred = e;
00135
00136 e->succ_next = g->vertices[f].succ;
00137 g->vertices[f].succ = e;
00138 }
00139
00140
00141
00142
00143
00144 static void
00145 dfs (struct graph *g, int *qs, int nq, int *qt, bool forward)
00146 {
00147 int i, tick = 0, v, comp = 0, top;
00148 struct edge *e;
00149 struct edge **stack = xmalloc (sizeof (struct edge *) * g->n_vertices);
00150
00151 for (i = 0; i < g->n_vertices; i++)
00152 {
00153 g->vertices[i].component = -1;
00154 g->vertices[i].post = -1;
00155 }
00156
00157 #define FST_EDGE(V) (forward ? g->vertices[(V)].succ : g->vertices[(V)].pred)
00158 #define NEXT_EDGE(E) (forward ? (E)->succ_next : (E)->pred_next)
00159 #define EDGE_SRC(E) (forward ? (E)->src : (E)->dest)
00160 #define EDGE_DEST(E) (forward ? (E)->dest : (E)->src)
00161
00162 for (i = 0; i < nq; i++)
00163 {
00164 v = qs[i];
00165 if (g->vertices[v].post != -1)
00166 continue;
00167
00168 g->vertices[v].component = comp++;
00169 e = FST_EDGE (v);
00170 top = 0;
00171
00172 while (1)
00173 {
00174 while (e && g->vertices[EDGE_DEST (e)].component != -1)
00175 e = NEXT_EDGE (e);
00176
00177 if (!e)
00178 {
00179 if (qt)
00180 qt[tick] = v;
00181 g->vertices[v].post = tick++;
00182
00183 if (!top)
00184 break;
00185
00186 e = stack[--top];
00187 v = EDGE_SRC (e);
00188 e = NEXT_EDGE (e);
00189 continue;
00190 }
00191
00192 stack[top++] = e;
00193 v = EDGE_DEST (e);
00194 e = FST_EDGE (v);
00195 g->vertices[v].component = comp - 1;
00196 }
00197 }
00198
00199 free (stack);
00200 }
00201
00202
00203
00204
00205 static void
00206 check_irred (struct graph *g, struct edge *e)
00207 {
00208 edge real = e->data;
00209
00210
00211
00212 gcc_assert (g->vertices[e->src].component >= g->vertices[e->dest].component);
00213
00214 if (g->vertices[e->src].component != g->vertices[e->dest].component)
00215 return;
00216
00217 real->flags |= EDGE_IRREDUCIBLE_LOOP;
00218 if (flow_bb_inside_loop_p (real->src->loop_father, real->dest))
00219 real->src->flags |= BB_IRREDUCIBLE_LOOP;
00220 }
00221
00222
00223
00224 static void
00225 for_each_edge (struct graph *g,
00226 void (callback) (struct graph *, struct edge *))
00227 {
00228 struct edge *e;
00229 int i;
00230
00231 for (i = 0; i < g->n_vertices; i++)
00232 for (e = g->vertices[i].succ; e; e = e->succ_next)
00233 callback (g, e);
00234 }
00235
00236
00237
00238 static void
00239 free_graph (struct graph *g)
00240 {
00241 struct edge *e, *n;
00242 int i;
00243
00244 for (i = 0; i < g->n_vertices; i++)
00245 for (e = g->vertices[i].succ; e; e = n)
00246 {
00247 n = e->succ_next;
00248 free (e);
00249 }
00250 free (g->vertices);
00251 free (g);
00252 }
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263 #define LOOP_REPR(LOOP) ((LOOP)->num + last_basic_block)
00264 #define BB_REPR(BB) ((BB)->index + 1)
00265
00266 void
00267 mark_irreducible_loops (struct loops *loops)
00268 {
00269 basic_block act;
00270 edge e;
00271 edge_iterator ei;
00272 int i, src, dest;
00273 struct graph *g;
00274 int *queue1 = xmalloc ((last_basic_block + loops->num) * sizeof (int));
00275 int *queue2 = xmalloc ((last_basic_block + loops->num) * sizeof (int));
00276 int nq, depth;
00277 struct loop *cloop;
00278
00279
00280 FOR_BB_BETWEEN (act, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
00281 {
00282 act->flags &= ~BB_IRREDUCIBLE_LOOP;
00283 FOR_EACH_EDGE (e, ei, act->succs)
00284 e->flags &= ~EDGE_IRREDUCIBLE_LOOP;
00285 }
00286
00287
00288 g = new_graph (last_basic_block + loops->num);
00289
00290 FOR_BB_BETWEEN (act, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
00291 FOR_EACH_EDGE (e, ei, act->succs)
00292 {
00293
00294 if (e->dest == EXIT_BLOCK_PTR)
00295 continue;
00296
00297
00298 if (e->dest->loop_father->header == e->dest
00299 && e->dest->loop_father->latch == act)
00300 continue;
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310 src = BB_REPR (act);
00311 dest = BB_REPR (e->dest);
00312
00313 if (e->dest->loop_father->header == e->dest)
00314 dest = LOOP_REPR (e->dest->loop_father);
00315
00316 if (!flow_bb_inside_loop_p (act->loop_father, e->dest))
00317 {
00318 depth = find_common_loop (act->loop_father,
00319 e->dest->loop_father)->depth + 1;
00320 if (depth == act->loop_father->depth)
00321 cloop = act->loop_father;
00322 else
00323 cloop = act->loop_father->pred[depth];
00324
00325 src = LOOP_REPR (cloop);
00326 }
00327
00328 add_edge (g, src, dest, e);
00329 }
00330
00331
00332
00333
00334
00335 nq = 0;
00336 FOR_BB_BETWEEN (act, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
00337 {
00338 queue1[nq++] = BB_REPR (act);
00339 }
00340 for (i = 1; i < (int) loops->num; i++)
00341 if (loops->parray[i])
00342 queue1[nq++] = LOOP_REPR (loops->parray[i]);
00343 dfs (g, queue1, nq, queue2, false);
00344 for (i = 0; i < nq; i++)
00345 queue1[i] = queue2[nq - i - 1];
00346 dfs (g, queue1, nq, NULL, true);
00347
00348
00349 for_each_edge (g, check_irred);
00350
00351 free_graph (g);
00352 free (queue1);
00353 free (queue2);
00354
00355 loops->state |= LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS;
00356 }
00357
00358
00359 int
00360 num_loop_insns (struct loop *loop)
00361 {
00362 basic_block *bbs, bb;
00363 unsigned i, ninsns = 0;
00364 rtx insn;
00365
00366 bbs = get_loop_body (loop);
00367 for (i = 0; i < loop->num_nodes; i++)
00368 {
00369 bb = bbs[i];
00370 ninsns++;
00371 for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = NEXT_INSN (insn))
00372 if (INSN_P (insn))
00373 ninsns++;
00374 }
00375 free(bbs);
00376
00377 return ninsns;
00378 }
00379
00380
00381 int
00382 average_num_loop_insns (struct loop *loop)
00383 {
00384 basic_block *bbs, bb;
00385 unsigned i, binsns, ninsns, ratio;
00386 rtx insn;
00387
00388 ninsns = 0;
00389 bbs = get_loop_body (loop);
00390 for (i = 0; i < loop->num_nodes; i++)
00391 {
00392 bb = bbs[i];
00393
00394 binsns = 1;
00395 for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = NEXT_INSN (insn))
00396 if (INSN_P (insn))
00397 binsns++;
00398
00399 ratio = loop->header->frequency == 0
00400 ? BB_FREQ_MAX
00401 : (bb->frequency * BB_FREQ_MAX) / loop->header->frequency;
00402 ninsns += binsns * ratio;
00403 }
00404 free(bbs);
00405
00406 ninsns /= BB_FREQ_MAX;
00407 if (!ninsns)
00408 ninsns = 1;
00409
00410 return ninsns;
00411 }
00412
00413
00414
00415
00416 unsigned
00417 expected_loop_iterations (const struct loop *loop)
00418 {
00419 edge e;
00420 edge_iterator ei;
00421
00422 if (loop->header->count)
00423 {
00424 gcov_type count_in, count_latch, expected;
00425
00426 count_in = 0;
00427 count_latch = 0;
00428
00429 FOR_EACH_EDGE (e, ei, loop->header->preds)
00430 if (e->src == loop->latch)
00431 count_latch = e->count;
00432 else
00433 count_in += e->count;
00434
00435 if (count_in == 0)
00436 expected = count_latch * 2;
00437 else
00438 expected = (count_latch + count_in - 1) / count_in;
00439
00440
00441 return (expected > REG_BR_PROB_BASE ? REG_BR_PROB_BASE : expected);
00442 }
00443 else
00444 {
00445 int freq_in, freq_latch;
00446
00447 freq_in = 0;
00448 freq_latch = 0;
00449
00450 FOR_EACH_EDGE (e, ei, loop->header->preds)
00451 if (e->src == loop->latch)
00452 freq_latch = EDGE_FREQUENCY (e);
00453 else
00454 freq_in += EDGE_FREQUENCY (e);
00455
00456 if (freq_in == 0)
00457 return freq_latch * 2;
00458
00459 return (freq_latch + freq_in - 1) / freq_in;
00460 }
00461 }
00462
00463
00464
00465 unsigned
00466 get_loop_level (const struct loop *loop)
00467 {
00468 const struct loop *ploop;
00469 unsigned mx = 0, l;
00470
00471 for (ploop = loop->inner; ploop; ploop = ploop->next)
00472 {
00473 l = get_loop_level (ploop);
00474 if (l >= mx)
00475 mx = l + 1;
00476 }
00477 return mx;
00478 }
00479
00480
00481
00482 static unsigned
00483 seq_cost (rtx seq)
00484 {
00485 unsigned cost = 0;
00486 rtx set;
00487
00488 for (; seq; seq = NEXT_INSN (seq))
00489 {
00490 set = single_set (seq);
00491 if (set)
00492 cost += rtx_cost (set, SET);
00493 else
00494 cost++;
00495 }
00496
00497 return cost;
00498 }
00499
00500
00501
00502 unsigned target_avail_regs;
00503 unsigned target_res_regs;
00504 unsigned target_small_cost;
00505 unsigned target_pres_cost;
00506
00507 unsigned target_spill_cost;
00508
00509
00510
00511 void
00512 init_set_costs (void)
00513 {
00514 rtx seq;
00515 rtx reg1 = gen_raw_REG (SImode, FIRST_PSEUDO_REGISTER);
00516 rtx reg2 = gen_raw_REG (SImode, FIRST_PSEUDO_REGISTER + 1);
00517 rtx addr = gen_raw_REG (Pmode, FIRST_PSEUDO_REGISTER + 2);
00518 rtx mem = validize_mem (gen_rtx_MEM (SImode, addr));
00519 unsigned i;
00520
00521 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
00522 if (TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], i)
00523 && !fixed_regs[i])
00524 target_avail_regs++;
00525
00526 target_res_regs = 3;
00527
00528
00529
00530 start_sequence ();
00531 emit_move_insn (reg1, reg2);
00532 seq = get_insns ();
00533 end_sequence ();
00534 target_small_cost = seq_cost (seq);
00535 target_pres_cost = 2 * target_small_cost;
00536
00537 start_sequence ();
00538 emit_move_insn (mem, reg1);
00539 emit_move_insn (reg2, mem);
00540 seq = get_insns ();
00541 end_sequence ();
00542 target_spill_cost = seq_cost (seq);
00543 }
00544
00545
00546
00547
00548
00549 unsigned
00550 global_cost_for_size (unsigned size, unsigned regs_used, unsigned n_uses)
00551 {
00552 unsigned regs_needed = regs_used + size;
00553 unsigned cost = 0;
00554
00555 if (regs_needed + target_res_regs <= target_avail_regs)
00556 cost += target_small_cost * size;
00557 else if (regs_needed <= target_avail_regs)
00558 cost += target_pres_cost * size;
00559 else
00560 {
00561 cost += target_pres_cost * size;
00562 cost += target_spill_cost * n_uses * (regs_needed - target_avail_regs) / regs_needed;
00563 }
00564
00565 return cost;
00566 }
00567