00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023 #include "system.h"
00024 #include "coretypes.h"
00025 #include "tm.h"
00026 #include "tree.h"
00027 #include "rtl.h"
00028 #include "basic-block.h"
00029 #include "tree-flow.h"
00030 #include "timevar.h"
00031 #include "toplev.h"
00032
00033
00034 static struct cfg_hooks *cfg_hooks;
00035
00036
00037 void
00038 rtl_register_cfg_hooks (void)
00039 {
00040 cfg_hooks = &rtl_cfg_hooks;
00041 }
00042
00043
00044 void
00045 cfg_layout_rtl_register_cfg_hooks (void)
00046 {
00047 cfg_hooks = &cfg_layout_rtl_cfg_hooks;
00048 }
00049
00050
00051
00052 void
00053 tree_register_cfg_hooks (void)
00054 {
00055 cfg_hooks = &tree_cfg_hooks;
00056 }
00057
00058
00059
00060 int
00061 ir_type (void)
00062 {
00063 return cfg_hooks == &tree_cfg_hooks ? 1 : 0;
00064 }
00065
00066
00067
00068
00069
00070
00071 void
00072 verify_flow_info (void)
00073 {
00074 size_t *edge_checksum;
00075 int num_bb_notes, err = 0;
00076 basic_block bb, last_bb_seen;
00077 basic_block *last_visited;
00078
00079 timevar_push (TV_CFG_VERIFY);
00080 last_visited = xcalloc (last_basic_block + 2, sizeof (basic_block));
00081 edge_checksum = xcalloc (last_basic_block + 2, sizeof (size_t));
00082
00083
00084 last_bb_seen = ENTRY_BLOCK_PTR;
00085 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb, NULL, next_bb)
00086 {
00087 if (bb != EXIT_BLOCK_PTR
00088 && bb != BASIC_BLOCK (bb->index))
00089 {
00090 error ("bb %d on wrong place", bb->index);
00091 err = 1;
00092 }
00093
00094 if (bb->prev_bb != last_bb_seen)
00095 {
00096 error ("prev_bb of %d should be %d, not %d",
00097 bb->index, last_bb_seen->index, bb->prev_bb->index);
00098 err = 1;
00099 }
00100
00101 last_bb_seen = bb;
00102 }
00103
00104
00105 FOR_EACH_BB_REVERSE (bb)
00106 {
00107 int n_fallthru = 0;
00108 edge e;
00109 edge_iterator ei;
00110
00111 if (bb->count < 0)
00112 {
00113 error ("verify_flow_info: Wrong count of block %i %i",
00114 bb->index, (int)bb->count);
00115 err = 1;
00116 }
00117 if (bb->frequency < 0)
00118 {
00119 error ("verify_flow_info: Wrong frequency of block %i %i",
00120 bb->index, bb->frequency);
00121 err = 1;
00122 }
00123 FOR_EACH_EDGE (e, ei, bb->succs)
00124 {
00125 if (last_visited [e->dest->index + 2] == bb)
00126 {
00127 error ("verify_flow_info: Duplicate edge %i->%i",
00128 e->src->index, e->dest->index);
00129 err = 1;
00130 }
00131 if (e->probability < 0 || e->probability > REG_BR_PROB_BASE)
00132 {
00133 error ("verify_flow_info: Wrong probability of edge %i->%i %i",
00134 e->src->index, e->dest->index, e->probability);
00135 err = 1;
00136 }
00137 if (e->count < 0)
00138 {
00139 error ("verify_flow_info: Wrong count of edge %i->%i %i",
00140 e->src->index, e->dest->index, (int)e->count);
00141 err = 1;
00142 }
00143
00144 last_visited [e->dest->index + 2] = bb;
00145
00146 if (e->flags & EDGE_FALLTHRU)
00147 n_fallthru++;
00148
00149 if (e->src != bb)
00150 {
00151 error ("verify_flow_info: Basic block %d succ edge is corrupted",
00152 bb->index);
00153 fprintf (stderr, "Predecessor: ");
00154 dump_edge_info (stderr, e, 0);
00155 fprintf (stderr, "\nSuccessor: ");
00156 dump_edge_info (stderr, e, 1);
00157 fprintf (stderr, "\n");
00158 err = 1;
00159 }
00160
00161 edge_checksum[e->dest->index + 2] += (size_t) e;
00162 }
00163 if (n_fallthru > 1)
00164 {
00165 error ("Wrong amount of branch edges after unconditional jump %i", bb->index);
00166 err = 1;
00167 }
00168
00169 FOR_EACH_EDGE (e, ei, bb->preds)
00170 {
00171 if (e->dest != bb)
00172 {
00173 error ("basic block %d pred edge is corrupted", bb->index);
00174 fputs ("Predecessor: ", stderr);
00175 dump_edge_info (stderr, e, 0);
00176 fputs ("\nSuccessor: ", stderr);
00177 dump_edge_info (stderr, e, 1);
00178 fputc ('\n', stderr);
00179 err = 1;
00180 }
00181
00182 if (ei.index != e->dest_idx)
00183 {
00184 error ("basic block %d pred edge is corrupted", bb->index);
00185 error ("its dest_idx should be %d, not %d",
00186 ei.index, e->dest_idx);
00187 fputs ("Predecessor: ", stderr);
00188 dump_edge_info (stderr, e, 0);
00189 fputs ("\nSuccessor: ", stderr);
00190 dump_edge_info (stderr, e, 1);
00191 fputc ('\n', stderr);
00192 err = 1;
00193 }
00194
00195 edge_checksum[e->dest->index + 2] -= (size_t) e;
00196 }
00197 }
00198
00199
00200 {
00201 edge e;
00202 edge_iterator ei;
00203
00204 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
00205 edge_checksum[e->dest->index + 2] += (size_t) e;
00206
00207 FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
00208 edge_checksum[e->dest->index + 2] -= (size_t) e;
00209 }
00210
00211 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
00212 if (edge_checksum[bb->index + 2])
00213 {
00214 error ("basic block %i edge lists are corrupted", bb->index);
00215 err = 1;
00216 }
00217
00218 num_bb_notes = 0;
00219 last_bb_seen = ENTRY_BLOCK_PTR;
00220
00221
00222 free (last_visited);
00223 free (edge_checksum);
00224
00225 if (cfg_hooks->verify_flow_info)
00226 err |= cfg_hooks->verify_flow_info ();
00227 if (err)
00228 internal_error ("verify_flow_info failed");
00229 timevar_pop (TV_CFG_VERIFY);
00230 }
00231
00232
00233
00234
00235
00236 void
00237 dump_bb (basic_block bb, FILE *outf, int indent)
00238 {
00239 edge e;
00240 edge_iterator ei;
00241 char *s_indent;
00242
00243 s_indent = alloca ((size_t) indent + 1);
00244 memset (s_indent, ' ', (size_t) indent);
00245 s_indent[indent] = '\0';
00246
00247 fprintf (outf, ";;%s basic block %d, loop depth %d, count ",
00248 s_indent, bb->index, bb->loop_depth);
00249 fprintf (outf, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT) bb->count);
00250 putc ('\n', outf);
00251
00252 fprintf (outf, ";;%s prev block ", s_indent);
00253 if (bb->prev_bb)
00254 fprintf (outf, "%d, ", bb->prev_bb->index);
00255 else
00256 fprintf (outf, "(nil), ");
00257 fprintf (outf, "next block ");
00258 if (bb->next_bb)
00259 fprintf (outf, "%d", bb->next_bb->index);
00260 else
00261 fprintf (outf, "(nil)");
00262 putc ('\n', outf);
00263
00264 fprintf (outf, ";;%s pred: ", s_indent);
00265 FOR_EACH_EDGE (e, ei, bb->preds)
00266 dump_edge_info (outf, e, 0);
00267 putc ('\n', outf);
00268
00269 fprintf (outf, ";;%s succ: ", s_indent);
00270 FOR_EACH_EDGE (e, ei, bb->succs)
00271 dump_edge_info (outf, e, 1);
00272 putc ('\n', outf);
00273
00274 if (cfg_hooks->dump_bb)
00275 cfg_hooks->dump_bb (bb, outf, indent);
00276 }
00277
00278
00279
00280
00281
00282
00283 edge
00284 redirect_edge_and_branch (edge e, basic_block dest)
00285 {
00286 edge ret;
00287
00288 if (!cfg_hooks->redirect_edge_and_branch)
00289 internal_error ("%s does not support redirect_edge_and_branch.",
00290 cfg_hooks->name);
00291
00292 ret = cfg_hooks->redirect_edge_and_branch (e, dest);
00293
00294 return ret;
00295 }
00296
00297
00298
00299
00300
00301 basic_block
00302 redirect_edge_and_branch_force (edge e, basic_block dest)
00303 {
00304 basic_block ret;
00305
00306 if (!cfg_hooks->redirect_edge_and_branch_force)
00307 internal_error ("%s does not support redirect_edge_and_branch_force.",
00308 cfg_hooks->name);
00309
00310 ret = cfg_hooks->redirect_edge_and_branch_force (e, dest);
00311
00312 return ret;
00313 }
00314
00315
00316
00317
00318
00319 edge
00320 split_block (basic_block bb, void *i)
00321 {
00322 basic_block new_bb;
00323
00324 if (!cfg_hooks->split_block)
00325 internal_error ("%s does not support split_block.", cfg_hooks->name);
00326
00327 new_bb = cfg_hooks->split_block (bb, i);
00328 if (!new_bb)
00329 return NULL;
00330
00331 new_bb->count = bb->count;
00332 new_bb->frequency = bb->frequency;
00333 new_bb->loop_depth = bb->loop_depth;
00334
00335 if (dom_info_available_p (CDI_DOMINATORS))
00336 {
00337 redirect_immediate_dominators (CDI_DOMINATORS, bb, new_bb);
00338 set_immediate_dominator (CDI_DOMINATORS, new_bb, bb);
00339 }
00340
00341 return make_single_succ_edge (bb, new_bb, EDGE_FALLTHRU);
00342 }
00343
00344
00345
00346 edge
00347 split_block_after_labels (basic_block bb)
00348 {
00349 return split_block (bb, NULL);
00350 }
00351
00352
00353
00354
00355 bool
00356 move_block_after (basic_block bb, basic_block after)
00357 {
00358 bool ret;
00359
00360 if (!cfg_hooks->move_block_after)
00361 internal_error ("%s does not support move_block_after.", cfg_hooks->name);
00362
00363 ret = cfg_hooks->move_block_after (bb, after);
00364
00365 return ret;
00366 }
00367
00368
00369
00370 void
00371 delete_basic_block (basic_block bb)
00372 {
00373 if (!cfg_hooks->delete_basic_block)
00374 internal_error ("%s does not support delete_basic_block.", cfg_hooks->name);
00375
00376 cfg_hooks->delete_basic_block (bb);
00377
00378
00379
00380 while (EDGE_COUNT (bb->preds) != 0)
00381 remove_edge (EDGE_PRED (bb, 0));
00382 while (EDGE_COUNT (bb->succs) != 0)
00383 remove_edge (EDGE_SUCC (bb, 0));
00384
00385 if (dom_computed[CDI_DOMINATORS])
00386 delete_from_dominance_info (CDI_DOMINATORS, bb);
00387 if (dom_computed[CDI_POST_DOMINATORS])
00388 delete_from_dominance_info (CDI_POST_DOMINATORS, bb);
00389
00390
00391 expunge_block (bb);
00392 }
00393
00394
00395
00396 basic_block
00397 split_edge (edge e)
00398 {
00399 basic_block ret;
00400 gcov_type count = e->count;
00401 int freq = EDGE_FREQUENCY (e);
00402 edge f;
00403 bool irr = (e->flags & EDGE_IRREDUCIBLE_LOOP) != 0;
00404
00405 if (!cfg_hooks->split_edge)
00406 internal_error ("%s does not support split_edge.", cfg_hooks->name);
00407
00408 ret = cfg_hooks->split_edge (e);
00409 ret->count = count;
00410 ret->frequency = freq;
00411 EDGE_SUCC (ret, 0)->probability = REG_BR_PROB_BASE;
00412 EDGE_SUCC (ret, 0)->count = count;
00413
00414 if (irr)
00415 {
00416 ret->flags |= BB_IRREDUCIBLE_LOOP;
00417 EDGE_PRED (ret, 0)->flags |= EDGE_IRREDUCIBLE_LOOP;
00418 EDGE_SUCC (ret, 0)->flags |= EDGE_IRREDUCIBLE_LOOP;
00419 }
00420
00421 if (dom_computed[CDI_DOMINATORS])
00422 set_immediate_dominator (CDI_DOMINATORS, ret, EDGE_PRED (ret, 0)->src);
00423
00424 if (dom_computed[CDI_DOMINATORS] >= DOM_NO_FAST_QUERY)
00425 {
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435 if (get_immediate_dominator (CDI_DOMINATORS, EDGE_SUCC (ret, 0)->dest)
00436 == EDGE_PRED (ret, 0)->src)
00437 {
00438 edge_iterator ei;
00439 FOR_EACH_EDGE (f, ei, EDGE_SUCC (ret, 0)->dest->preds)
00440 {
00441 if (f == EDGE_SUCC (ret, 0))
00442 continue;
00443
00444 if (!dominated_by_p (CDI_DOMINATORS, f->src,
00445 EDGE_SUCC (ret, 0)->dest))
00446 break;
00447 }
00448
00449 if (!f)
00450 set_immediate_dominator (CDI_DOMINATORS, EDGE_SUCC (ret, 0)->dest, ret);
00451 }
00452 };
00453
00454 return ret;
00455 }
00456
00457
00458
00459
00460
00461 basic_block
00462 create_basic_block (void *head, void *end, basic_block after)
00463 {
00464 basic_block ret;
00465
00466 if (!cfg_hooks->create_basic_block)
00467 internal_error ("%s does not support create_basic_block.", cfg_hooks->name);
00468
00469 ret = cfg_hooks->create_basic_block (head, end, after);
00470
00471 if (dom_computed[CDI_DOMINATORS])
00472 add_to_dominance_info (CDI_DOMINATORS, ret);
00473 if (dom_computed[CDI_POST_DOMINATORS])
00474 add_to_dominance_info (CDI_POST_DOMINATORS, ret);
00475
00476 return ret;
00477 }
00478
00479
00480
00481 basic_block
00482 create_empty_bb (basic_block after)
00483 {
00484 return create_basic_block (NULL, NULL, after);
00485 }
00486
00487
00488
00489 bool
00490 can_merge_blocks_p (basic_block bb1, basic_block bb2)
00491 {
00492 bool ret;
00493
00494 if (!cfg_hooks->can_merge_blocks_p)
00495 internal_error ("%s does not support can_merge_blocks_p.", cfg_hooks->name);
00496
00497 ret = cfg_hooks->can_merge_blocks_p (bb1, bb2);
00498
00499 return ret;
00500 }
00501
00502 void
00503 predict_edge (edge e, enum br_predictor predictor, int probability)
00504 {
00505 if (!cfg_hooks->predict_edge)
00506 internal_error ("%s does not support predict_edge.", cfg_hooks->name);
00507
00508 cfg_hooks->predict_edge (e, predictor, probability);
00509 }
00510
00511 bool
00512 predicted_by_p (basic_block bb, enum br_predictor predictor)
00513 {
00514 if (!cfg_hooks->predict_edge)
00515 internal_error ("%s does not support predicted_by_p.", cfg_hooks->name);
00516
00517 return cfg_hooks->predicted_by_p (bb, predictor);
00518 }
00519
00520
00521
00522 void
00523 merge_blocks (basic_block a, basic_block b)
00524 {
00525 edge e;
00526 edge_iterator ei;
00527
00528 if (!cfg_hooks->merge_blocks)
00529 internal_error ("%s does not support merge_blocks.", cfg_hooks->name);
00530
00531 cfg_hooks->merge_blocks (a, b);
00532
00533
00534
00535
00536
00537
00538 while (EDGE_COUNT (a->succs) != 0)
00539 remove_edge (EDGE_SUCC (a, 0));
00540
00541
00542 FOR_EACH_EDGE (e, ei, b->succs)
00543 e->src = a;
00544 a->succs = b->succs;
00545 a->flags |= b->flags;
00546
00547
00548 b->preds = b->succs = NULL;
00549 a->global_live_at_end = b->global_live_at_end;
00550
00551 if (dom_computed[CDI_DOMINATORS])
00552 redirect_immediate_dominators (CDI_DOMINATORS, b, a);
00553
00554 if (dom_computed[CDI_DOMINATORS])
00555 delete_from_dominance_info (CDI_DOMINATORS, b);
00556 if (dom_computed[CDI_POST_DOMINATORS])
00557 delete_from_dominance_info (CDI_POST_DOMINATORS, b);
00558
00559 expunge_block (b);
00560 }
00561
00562
00563
00564
00565
00566 edge
00567 make_forwarder_block (basic_block bb, bool (*redirect_edge_p) (edge),
00568 void (*new_bb_cbk) (basic_block))
00569 {
00570 edge e, fallthru;
00571 edge_iterator ei;
00572 basic_block dummy, jump;
00573
00574 if (!cfg_hooks->make_forwarder_block)
00575 internal_error ("%s does not support make_forwarder_block.",
00576 cfg_hooks->name);
00577
00578 fallthru = split_block_after_labels (bb);
00579 dummy = fallthru->src;
00580 bb = fallthru->dest;
00581
00582
00583 for (ei = ei_start (dummy->preds); (e = ei_safe_edge (ei)); )
00584 {
00585 if (redirect_edge_p (e))
00586 {
00587 ei_next (&ei);
00588 continue;
00589 }
00590
00591 dummy->frequency -= EDGE_FREQUENCY (e);
00592 dummy->count -= e->count;
00593 if (dummy->frequency < 0)
00594 dummy->frequency = 0;
00595 if (dummy->count < 0)
00596 dummy->count = 0;
00597 fallthru->count -= e->count;
00598 if (fallthru->count < 0)
00599 fallthru->count = 0;
00600
00601 jump = redirect_edge_and_branch_force (e, bb);
00602 if (jump)
00603 new_bb_cbk (jump);
00604 }
00605
00606 if (dom_info_available_p (CDI_DOMINATORS))
00607 {
00608 basic_block doms_to_fix[2];
00609
00610 doms_to_fix[0] = dummy;
00611 doms_to_fix[1] = bb;
00612 iterate_fix_dominators (CDI_DOMINATORS, doms_to_fix, 2);
00613 }
00614
00615 cfg_hooks->make_forwarder_block (fallthru);
00616
00617 return fallthru;
00618 }
00619
00620 void
00621 tidy_fallthru_edge (edge e)
00622 {
00623 if (cfg_hooks->tidy_fallthru_edge)
00624 cfg_hooks->tidy_fallthru_edge (e);
00625 }
00626
00627
00628
00629
00630
00631
00632 void
00633 tidy_fallthru_edges (void)
00634 {
00635 basic_block b, c;
00636
00637 if (!cfg_hooks->tidy_fallthru_edge)
00638 return;
00639
00640 if (ENTRY_BLOCK_PTR->next_bb == EXIT_BLOCK_PTR)
00641 return;
00642
00643 FOR_BB_BETWEEN (b, ENTRY_BLOCK_PTR->next_bb, EXIT_BLOCK_PTR->prev_bb, next_bb)
00644 {
00645 edge s;
00646
00647 c = b->next_bb;
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661 if (EDGE_COUNT (b->succs) == 1)
00662 {
00663 s = EDGE_SUCC (b, 0);
00664 if (! (s->flags & EDGE_COMPLEX)
00665 && s->dest == c
00666 && !find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX))
00667 tidy_fallthru_edge (s);
00668 }
00669 }
00670 }
00671
00672
00673
00674 bool
00675 can_duplicate_block_p (basic_block bb)
00676 {
00677 edge e;
00678
00679 if (!cfg_hooks->can_duplicate_block_p)
00680 internal_error ("%s does not support can_duplicate_block_p.",
00681 cfg_hooks->name);
00682
00683 if (bb == EXIT_BLOCK_PTR || bb == ENTRY_BLOCK_PTR)
00684 return false;
00685
00686
00687
00688 e = find_edge (bb, EXIT_BLOCK_PTR);
00689 if (e && (e->flags & EDGE_FALLTHRU))
00690 return false;
00691
00692 return cfg_hooks->can_duplicate_block_p (bb);
00693 }
00694
00695
00696
00697
00698 basic_block
00699 duplicate_block (basic_block bb, edge e)
00700 {
00701 edge s, n;
00702 basic_block new_bb;
00703 gcov_type new_count = e ? e->count : 0;
00704 edge_iterator ei;
00705
00706 if (!cfg_hooks->duplicate_block)
00707 internal_error ("%s does not support duplicate_block.",
00708 cfg_hooks->name);
00709
00710 if (bb->count < new_count)
00711 new_count = bb->count;
00712
00713 #ifdef ENABLE_CHECKING
00714 gcc_assert (can_duplicate_block_p (bb));
00715 #endif
00716
00717 new_bb = cfg_hooks->duplicate_block (bb);
00718
00719 new_bb->loop_depth = bb->loop_depth;
00720 new_bb->flags = bb->flags;
00721 FOR_EACH_EDGE (s, ei, bb->succs)
00722 {
00723
00724
00725
00726 n = unchecked_make_edge (new_bb, s->dest, s->flags);
00727 n->probability = s->probability;
00728 if (e && bb->count)
00729 {
00730
00731 n->count = s->count * (new_count * 10000 / bb->count) / 10000;
00732 s->count -= n->count;
00733 }
00734 else
00735 n->count = s->count;
00736 n->aux = s->aux;
00737 }
00738
00739 if (e)
00740 {
00741 new_bb->count = new_count;
00742 bb->count -= new_count;
00743
00744 new_bb->frequency = EDGE_FREQUENCY (e);
00745 bb->frequency -= EDGE_FREQUENCY (e);
00746
00747 redirect_edge_and_branch_force (e, new_bb);
00748
00749 if (bb->count < 0)
00750 bb->count = 0;
00751 if (bb->frequency < 0)
00752 bb->frequency = 0;
00753 }
00754 else
00755 {
00756 new_bb->count = bb->count;
00757 new_bb->frequency = bb->frequency;
00758 }
00759
00760 new_bb->rbi->original = bb;
00761 bb->rbi->copy = new_bb;
00762
00763 return new_bb;
00764 }
00765
00766
00767
00768
00769 bool
00770 block_ends_with_call_p (basic_block bb)
00771 {
00772 if (!cfg_hooks->block_ends_with_call_p)
00773 internal_error ("%s does not support block_ends_with_call_p", cfg_hooks->name);
00774
00775 return (cfg_hooks->block_ends_with_call_p) (bb);
00776 }
00777
00778
00779
00780 bool
00781 block_ends_with_condjump_p (basic_block bb)
00782 {
00783 if (!cfg_hooks->block_ends_with_condjump_p)
00784 internal_error ("%s does not support block_ends_with_condjump_p",
00785 cfg_hooks->name);
00786
00787 return (cfg_hooks->block_ends_with_condjump_p) (bb);
00788 }
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798 int
00799 flow_call_edges_add (sbitmap blocks)
00800 {
00801 if (!cfg_hooks->flow_call_edges_add)
00802 internal_error ("%s does not support flow_call_edges_add",
00803 cfg_hooks->name);
00804
00805 return (cfg_hooks->flow_call_edges_add) (blocks);
00806 }
00807
00808
00809
00810
00811 void
00812 execute_on_growing_pred (edge e)
00813 {
00814 if (cfg_hooks->execute_on_growing_pred)
00815 cfg_hooks->execute_on_growing_pred (e);
00816 }
00817
00818
00819
00820
00821 void
00822 execute_on_shrinking_pred (edge e)
00823 {
00824 if (cfg_hooks->execute_on_shrinking_pred)
00825 cfg_hooks->execute_on_shrinking_pred (e);
00826 }