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 "rtl.h"
00041 #include "hard-reg-set.h"
00042 #include "obstack.h"
00043 #include "basic-block.h"
00044 #include "errors.h"
00045 #include "et-forest.h"
00046
00047
00048 enum dom_state dom_computed[2];
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 typedef unsigned int TBB;
00059
00060
00061
00062
00063
00064
00065 struct dom_info
00066 {
00067
00068 TBB *dfs_parent;
00069
00070
00071
00072 TBB *key;
00073
00074
00075 TBB *path_min;
00076
00077 TBB *bucket;
00078
00079 TBB *next_bucket;
00080
00081
00082 TBB *dom;
00083
00084
00085
00086
00087
00088 TBB *set_chain;
00089
00090 unsigned int *set_size;
00091
00092
00093 TBB *set_child;
00094
00095
00096
00097
00098 TBB *dfs_order;
00099
00100
00101
00102
00103 basic_block *dfs_to_bb;
00104
00105
00106 unsigned int dfsnum;
00107
00108 unsigned int nodes;
00109
00110
00111
00112 bitmap fake_exit_edge;
00113 };
00114
00115 static void init_dom_info (struct dom_info *, enum cdi_direction);
00116 static void free_dom_info (struct dom_info *);
00117 static void calc_dfs_tree_nonrec (struct dom_info *, basic_block,
00118 enum cdi_direction);
00119 static void calc_dfs_tree (struct dom_info *, enum cdi_direction);
00120 static void compress (struct dom_info *, TBB);
00121 static TBB eval (struct dom_info *, TBB);
00122 static void link_roots (struct dom_info *, TBB, TBB);
00123 static void calc_idoms (struct dom_info *, enum cdi_direction);
00124 void debug_dominance_info (enum cdi_direction);
00125
00126
00127 static unsigned n_bbs_in_dom_tree[2];
00128
00129
00130
00131 #define init_ar(var, type, num, content) \
00132 do \
00133 { \
00134 unsigned int i = 1; \
00135 if (! (content)) \
00136 (var) = xcalloc ((num), sizeof (type)); \
00137 else \
00138 { \
00139 (var) = xmalloc ((num) * sizeof (type)); \
00140 for (i = 0; i < num; i++) \
00141 (var)[i] = (content); \
00142 } \
00143 } \
00144 while (0)
00145
00146
00147
00148
00149 static void
00150 init_dom_info (struct dom_info *di, enum cdi_direction dir)
00151 {
00152
00153
00154 unsigned int num = n_basic_blocks + 1 + 1;
00155 init_ar (di->dfs_parent, TBB, num, 0);
00156 init_ar (di->path_min, TBB, num, i);
00157 init_ar (di->key, TBB, num, i);
00158 init_ar (di->dom, TBB, num, 0);
00159
00160 init_ar (di->bucket, TBB, num, 0);
00161 init_ar (di->next_bucket, TBB, num, 0);
00162
00163 init_ar (di->set_chain, TBB, num, 0);
00164 init_ar (di->set_size, unsigned int, num, 1);
00165 init_ar (di->set_child, TBB, num, 0);
00166
00167 init_ar (di->dfs_order, TBB, (unsigned int) last_basic_block + 1, 0);
00168 init_ar (di->dfs_to_bb, basic_block, num, 0);
00169
00170 di->dfsnum = 1;
00171 di->nodes = 0;
00172
00173 di->fake_exit_edge = dir ? BITMAP_ALLOC (NULL) : NULL;
00174 }
00175
00176 #undef init_ar
00177
00178
00179
00180 static void
00181 free_dom_info (struct dom_info *di)
00182 {
00183 free (di->dfs_parent);
00184 free (di->path_min);
00185 free (di->key);
00186 free (di->dom);
00187 free (di->bucket);
00188 free (di->next_bucket);
00189 free (di->set_chain);
00190 free (di->set_size);
00191 free (di->set_child);
00192 free (di->dfs_order);
00193 free (di->dfs_to_bb);
00194 BITMAP_FREE (di->fake_exit_edge);
00195 }
00196
00197
00198
00199
00200
00201
00202
00203 static void
00204 calc_dfs_tree_nonrec (struct dom_info *di, basic_block bb,
00205 enum cdi_direction reverse)
00206 {
00207
00208 edge e;
00209 TBB child_i, my_i = 0;
00210 edge_iterator *stack;
00211 edge_iterator ei, einext;
00212 int sp;
00213
00214
00215 basic_block en_block;
00216
00217 basic_block ex_block;
00218
00219 stack = xmalloc ((n_basic_blocks + 3) * sizeof (edge_iterator));
00220 sp = 0;
00221
00222
00223 if (reverse)
00224 {
00225 ei = ei_start (bb->preds);
00226 en_block = EXIT_BLOCK_PTR;
00227 ex_block = ENTRY_BLOCK_PTR;
00228 }
00229 else
00230 {
00231 ei = ei_start (bb->succs);
00232 en_block = ENTRY_BLOCK_PTR;
00233 ex_block = EXIT_BLOCK_PTR;
00234 }
00235
00236
00237 while (1)
00238 {
00239 basic_block bn;
00240
00241
00242
00243 while (!ei_end_p (ei))
00244 {
00245 e = ei_edge (ei);
00246
00247
00248
00249 if (reverse)
00250 {
00251 bn = e->src;
00252
00253
00254
00255
00256 if (bn == ex_block || di->dfs_order[bn->index])
00257 {
00258 ei_next (&ei);
00259 continue;
00260 }
00261 bb = e->dest;
00262 einext = ei_start (bn->preds);
00263 }
00264 else
00265 {
00266 bn = e->dest;
00267 if (bn == ex_block || di->dfs_order[bn->index])
00268 {
00269 ei_next (&ei);
00270 continue;
00271 }
00272 bb = e->src;
00273 einext = ei_start (bn->succs);
00274 }
00275
00276 gcc_assert (bn != en_block);
00277
00278
00279 if (bb != en_block)
00280 my_i = di->dfs_order[bb->index];
00281 else
00282 my_i = di->dfs_order[last_basic_block];
00283 child_i = di->dfs_order[bn->index] = di->dfsnum++;
00284 di->dfs_to_bb[child_i] = bn;
00285 di->dfs_parent[child_i] = my_i;
00286
00287
00288 stack[sp++] = ei;
00289 ei = einext;
00290 }
00291
00292 if (!sp)
00293 break;
00294 ei = stack[--sp];
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 ei_next (&ei);
00306 }
00307 free (stack);
00308 }
00309
00310
00311
00312
00313
00314
00315 static void
00316 calc_dfs_tree (struct dom_info *di, enum cdi_direction reverse)
00317 {
00318
00319 basic_block begin = reverse ? EXIT_BLOCK_PTR : ENTRY_BLOCK_PTR;
00320 di->dfs_order[last_basic_block] = di->dfsnum;
00321 di->dfs_to_bb[di->dfsnum] = begin;
00322 di->dfsnum++;
00323
00324 calc_dfs_tree_nonrec (di, begin, reverse);
00325
00326 if (reverse)
00327 {
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 basic_block b;
00339 bool saw_unconnected = false;
00340
00341 FOR_EACH_BB_REVERSE (b)
00342 {
00343 if (EDGE_COUNT (b->succs) > 0)
00344 {
00345 if (di->dfs_order[b->index] == 0)
00346 saw_unconnected = true;
00347 continue;
00348 }
00349 bitmap_set_bit (di->fake_exit_edge, b->index);
00350 di->dfs_order[b->index] = di->dfsnum;
00351 di->dfs_to_bb[di->dfsnum] = b;
00352 di->dfs_parent[di->dfsnum] = di->dfs_order[last_basic_block];
00353 di->dfsnum++;
00354 calc_dfs_tree_nonrec (di, b, reverse);
00355 }
00356
00357 if (saw_unconnected)
00358 {
00359 FOR_EACH_BB_REVERSE (b)
00360 {
00361 if (di->dfs_order[b->index])
00362 continue;
00363 bitmap_set_bit (di->fake_exit_edge, b->index);
00364 di->dfs_order[b->index] = di->dfsnum;
00365 di->dfs_to_bb[di->dfsnum] = b;
00366 di->dfs_parent[di->dfsnum] = di->dfs_order[last_basic_block];
00367 di->dfsnum++;
00368 calc_dfs_tree_nonrec (di, b, reverse);
00369 }
00370 }
00371 }
00372
00373 di->nodes = di->dfsnum - 1;
00374
00375
00376 gcc_assert (di->nodes == (unsigned int) n_basic_blocks + 1);
00377 }
00378
00379
00380
00381
00382
00383
00384 static void
00385 compress (struct dom_info *di, TBB v)
00386 {
00387
00388
00389
00390 TBB parent = di->set_chain[v];
00391 if (di->set_chain[parent])
00392 {
00393 compress (di, parent);
00394 if (di->key[di->path_min[parent]] < di->key[di->path_min[v]])
00395 di->path_min[v] = di->path_min[parent];
00396 di->set_chain[v] = di->set_chain[parent];
00397 }
00398 }
00399
00400
00401
00402
00403
00404 static inline TBB
00405 eval (struct dom_info *di, TBB v)
00406 {
00407
00408
00409 TBB rep = di->set_chain[v];
00410
00411
00412 if (!rep)
00413 return di->path_min[v];
00414
00415
00416 if (di->set_chain[rep])
00417 {
00418 compress (di, v);
00419 rep = di->set_chain[v];
00420 }
00421
00422 if (di->key[di->path_min[rep]] >= di->key[di->path_min[v]])
00423 return di->path_min[v];
00424 else
00425 return di->path_min[rep];
00426 }
00427
00428
00429
00430
00431
00432
00433 static void
00434 link_roots (struct dom_info *di, TBB v, TBB w)
00435 {
00436 TBB s = w;
00437
00438
00439 while (di->key[di->path_min[w]] < di->key[di->path_min[di->set_child[s]]])
00440 {
00441 if (di->set_size[s] + di->set_size[di->set_child[di->set_child[s]]]
00442 >= 2 * di->set_size[di->set_child[s]])
00443 {
00444 di->set_chain[di->set_child[s]] = s;
00445 di->set_child[s] = di->set_child[di->set_child[s]];
00446 }
00447 else
00448 {
00449 di->set_size[di->set_child[s]] = di->set_size[s];
00450 s = di->set_chain[s] = di->set_child[s];
00451 }
00452 }
00453
00454 di->path_min[s] = di->path_min[w];
00455 di->set_size[v] += di->set_size[w];
00456 if (di->set_size[v] < 2 * di->set_size[w])
00457 {
00458 TBB tmp = s;
00459 s = di->set_child[v];
00460 di->set_child[v] = tmp;
00461 }
00462
00463
00464 while (s)
00465 {
00466 di->set_chain[s] = v;
00467 s = di->set_child[s];
00468 }
00469 }
00470
00471
00472
00473
00474
00475 static void
00476 calc_idoms (struct dom_info *di, enum cdi_direction reverse)
00477 {
00478 TBB v, w, k, par;
00479 basic_block en_block;
00480 edge_iterator ei, einext;
00481
00482 if (reverse)
00483 en_block = EXIT_BLOCK_PTR;
00484 else
00485 en_block = ENTRY_BLOCK_PTR;
00486
00487
00488 v = di->nodes;
00489 while (v > 1)
00490 {
00491 basic_block bb = di->dfs_to_bb[v];
00492 edge e;
00493
00494 par = di->dfs_parent[v];
00495 k = v;
00496
00497 ei = (reverse) ? ei_start (bb->succs) : ei_start (bb->preds);
00498
00499 if (reverse)
00500 {
00501
00502 if (bitmap_bit_p (di->fake_exit_edge, bb->index))
00503 {
00504 einext = ei;
00505 einext.index = 0;
00506 goto do_fake_exit_edge;
00507 }
00508 }
00509
00510
00511
00512
00513
00514 while (!ei_end_p (ei))
00515 {
00516 TBB k1;
00517 basic_block b;
00518
00519 e = ei_edge (ei);
00520 b = (reverse) ? e->dest : e->src;
00521 einext = ei;
00522 ei_next (&einext);
00523
00524 if (b == en_block)
00525 {
00526 do_fake_exit_edge:
00527 k1 = di->dfs_order[last_basic_block];
00528 }
00529 else
00530 k1 = di->dfs_order[b->index];
00531
00532
00533
00534 if (k1 > v)
00535 k1 = di->key[eval (di, k1)];
00536 if (k1 < k)
00537 k = k1;
00538
00539 ei = einext;
00540 }
00541
00542 di->key[v] = k;
00543 link_roots (di, par, v);
00544 di->next_bucket[v] = di->bucket[k];
00545 di->bucket[k] = v;
00546
00547
00548 for (w = di->bucket[par]; w; w = di->next_bucket[w])
00549 {
00550 k = eval (di, w);
00551 if (di->key[k] < di->key[w])
00552 di->dom[w] = k;
00553 else
00554 di->dom[w] = par;
00555 }
00556
00557 di->bucket[par] = 0;
00558 v--;
00559 }
00560
00561
00562 di->dom[1] = 0;
00563 for (v = 2; v <= di->nodes; v++)
00564 if (di->dom[v] != di->key[v])
00565 di->dom[v] = di->dom[di->dom[v]];
00566 }
00567
00568
00569
00570 static void
00571 assign_dfs_numbers (struct et_node *node, int *num)
00572 {
00573 struct et_node *son;
00574
00575 node->dfs_num_in = (*num)++;
00576
00577 if (node->son)
00578 {
00579 assign_dfs_numbers (node->son, num);
00580 for (son = node->son->right; son != node->son; son = son->right)
00581 assign_dfs_numbers (son, num);
00582 }
00583
00584 node->dfs_num_out = (*num)++;
00585 }
00586
00587
00588
00589
00590 static void
00591 compute_dom_fast_query (enum cdi_direction dir)
00592 {
00593 int num = 0;
00594 basic_block bb;
00595
00596 gcc_assert (dom_info_available_p (dir));
00597
00598 if (dom_computed[dir] == DOM_OK)
00599 return;
00600
00601 FOR_ALL_BB (bb)
00602 {
00603 if (!bb->dom[dir]->father)
00604 assign_dfs_numbers (bb->dom[dir], &num);
00605 }
00606
00607 dom_computed[dir] = DOM_OK;
00608 }
00609
00610
00611
00612
00613 void
00614 calculate_dominance_info (enum cdi_direction dir)
00615 {
00616 struct dom_info di;
00617 basic_block b;
00618
00619 if (dom_computed[dir] == DOM_OK)
00620 return;
00621
00622 if (!dom_info_available_p (dir))
00623 {
00624 gcc_assert (!n_bbs_in_dom_tree[dir]);
00625
00626 FOR_ALL_BB (b)
00627 {
00628 b->dom[dir] = et_new_tree (b);
00629 }
00630 n_bbs_in_dom_tree[dir] = n_basic_blocks + 2;
00631
00632 init_dom_info (&di, dir);
00633 calc_dfs_tree (&di, dir);
00634 calc_idoms (&di, dir);
00635
00636 FOR_EACH_BB (b)
00637 {
00638 TBB d = di.dom[di.dfs_order[b->index]];
00639
00640 if (di.dfs_to_bb[d])
00641 et_set_father (b->dom[dir], di.dfs_to_bb[d]->dom[dir]);
00642 }
00643
00644 free_dom_info (&di);
00645 dom_computed[dir] = DOM_NO_FAST_QUERY;
00646 }
00647
00648 compute_dom_fast_query (dir);
00649 }
00650
00651
00652 void
00653 free_dominance_info (enum cdi_direction dir)
00654 {
00655 basic_block bb;
00656
00657 if (!dom_info_available_p (dir))
00658 return;
00659
00660 FOR_ALL_BB (bb)
00661 {
00662 delete_from_dominance_info (dir, bb);
00663 }
00664
00665
00666 gcc_assert (!n_bbs_in_dom_tree[dir]);
00667
00668 dom_computed[dir] = DOM_NONE;
00669 }
00670
00671
00672 basic_block
00673 get_immediate_dominator (enum cdi_direction dir, basic_block bb)
00674 {
00675 struct et_node *node = bb->dom[dir];
00676
00677 gcc_assert (dom_computed[dir]);
00678
00679 if (!node->father)
00680 return NULL;
00681
00682 return node->father->data;
00683 }
00684
00685
00686
00687 inline void
00688 set_immediate_dominator (enum cdi_direction dir, basic_block bb,
00689 basic_block dominated_by)
00690 {
00691 struct et_node *node = bb->dom[dir];
00692
00693 gcc_assert (dom_computed[dir]);
00694
00695 if (node->father)
00696 {
00697 if (node->father->data == dominated_by)
00698 return;
00699 et_split (node);
00700 }
00701
00702 if (dominated_by)
00703 et_set_father (node, dominated_by->dom[dir]);
00704
00705 if (dom_computed[dir] == DOM_OK)
00706 dom_computed[dir] = DOM_NO_FAST_QUERY;
00707 }
00708
00709
00710
00711 int
00712 get_dominated_by (enum cdi_direction dir, basic_block bb, basic_block **bbs)
00713 {
00714 int n;
00715 struct et_node *node = bb->dom[dir], *son = node->son, *ason;
00716
00717 gcc_assert (dom_computed[dir]);
00718
00719 if (!son)
00720 {
00721 *bbs = NULL;
00722 return 0;
00723 }
00724
00725 for (ason = son->right, n = 1; ason != son; ason = ason->right)
00726 n++;
00727
00728 *bbs = xmalloc (n * sizeof (basic_block));
00729 (*bbs)[0] = son->data;
00730 for (ason = son->right, n = 1; ason != son; ason = ason->right)
00731 (*bbs)[n++] = ason->data;
00732
00733 return n;
00734 }
00735
00736
00737
00738
00739
00740
00741 unsigned
00742 get_dominated_by_region (enum cdi_direction dir, basic_block *region,
00743 unsigned n_region, basic_block *doms)
00744 {
00745 unsigned n_doms = 0, i;
00746 basic_block dom;
00747
00748 for (i = 0; i < n_region; i++)
00749 region[i]->rbi->duplicated = 1;
00750 for (i = 0; i < n_region; i++)
00751 for (dom = first_dom_son (dir, region[i]);
00752 dom;
00753 dom = next_dom_son (dir, dom))
00754 if (!dom->rbi->duplicated)
00755 doms[n_doms++] = dom;
00756 for (i = 0; i < n_region; i++)
00757 region[i]->rbi->duplicated = 0;
00758
00759 return n_doms;
00760 }
00761
00762
00763 void
00764 redirect_immediate_dominators (enum cdi_direction dir, basic_block bb,
00765 basic_block to)
00766 {
00767 struct et_node *bb_node = bb->dom[dir], *to_node = to->dom[dir], *son;
00768
00769 gcc_assert (dom_computed[dir]);
00770
00771 if (!bb_node->son)
00772 return;
00773
00774 while (bb_node->son)
00775 {
00776 son = bb_node->son;
00777
00778 et_split (son);
00779 et_set_father (son, to_node);
00780 }
00781
00782 if (dom_computed[dir] == DOM_OK)
00783 dom_computed[dir] = DOM_NO_FAST_QUERY;
00784 }
00785
00786
00787 basic_block
00788 nearest_common_dominator (enum cdi_direction dir, basic_block bb1, basic_block bb2)
00789 {
00790 gcc_assert (dom_computed[dir]);
00791
00792 if (!bb1)
00793 return bb2;
00794 if (!bb2)
00795 return bb1;
00796
00797 return et_nca (bb1->dom[dir], bb2->dom[dir])->data;
00798 }
00799
00800
00801 bool
00802 dominated_by_p (enum cdi_direction dir, basic_block bb1, basic_block bb2)
00803 {
00804 struct et_node *n1 = bb1->dom[dir], *n2 = bb2->dom[dir];
00805
00806 gcc_assert (dom_computed[dir]);
00807
00808 if (dom_computed[dir] == DOM_OK)
00809 return (n1->dfs_num_in >= n2->dfs_num_in
00810 && n1->dfs_num_out <= n2->dfs_num_out);
00811
00812 return et_below (n1, n2);
00813 }
00814
00815
00816 void
00817 verify_dominators (enum cdi_direction dir)
00818 {
00819 int err = 0;
00820 basic_block bb;
00821
00822 gcc_assert (dom_info_available_p (dir));
00823
00824 FOR_EACH_BB (bb)
00825 {
00826 basic_block dom_bb;
00827 basic_block imm_bb;
00828
00829 dom_bb = recount_dominator (dir, bb);
00830 imm_bb = get_immediate_dominator (dir, bb);
00831 if (dom_bb != imm_bb)
00832 {
00833 if ((dom_bb == NULL) || (imm_bb == NULL))
00834 error ("dominator of %d status unknown", bb->index);
00835 else
00836 error ("dominator of %d should be %d, not %d",
00837 bb->index, dom_bb->index, imm_bb->index);
00838 err = 1;
00839 }
00840 }
00841
00842 if (dir == CDI_DOMINATORS)
00843 {
00844 FOR_EACH_BB (bb)
00845 {
00846 if (!dominated_by_p (dir, bb, ENTRY_BLOCK_PTR))
00847 {
00848 error ("ENTRY does not dominate bb %d", bb->index);
00849 err = 1;
00850 }
00851 }
00852 }
00853
00854 gcc_assert (!err);
00855 }
00856
00857
00858
00859
00860
00861
00862 basic_block
00863 recount_dominator (enum cdi_direction dir, basic_block bb)
00864 {
00865 basic_block dom_bb = NULL;
00866 edge e;
00867 edge_iterator ei;
00868
00869 gcc_assert (dom_computed[dir]);
00870
00871 if (dir == CDI_DOMINATORS)
00872 {
00873 FOR_EACH_EDGE (e, ei, bb->preds)
00874 {
00875
00876
00877 if (!dominated_by_p (dir, e->src, ENTRY_BLOCK_PTR))
00878 continue;
00879
00880 if (!dominated_by_p (dir, e->src, bb))
00881 dom_bb = nearest_common_dominator (dir, dom_bb, e->src);
00882 }
00883 }
00884 else
00885 {
00886 FOR_EACH_EDGE (e, ei, bb->succs)
00887 {
00888 if (!dominated_by_p (dir, e->dest, bb))
00889 dom_bb = nearest_common_dominator (dir, dom_bb, e->dest);
00890 }
00891 }
00892
00893 return dom_bb;
00894 }
00895
00896
00897
00898 void
00899 iterate_fix_dominators (enum cdi_direction dir, basic_block *bbs, int n)
00900 {
00901 int i, changed = 1;
00902 basic_block old_dom, new_dom;
00903
00904 gcc_assert (dom_computed[dir]);
00905
00906 for (i = 0; i < n; i++)
00907 set_immediate_dominator (dir, bbs[i], NULL);
00908
00909 while (changed)
00910 {
00911 changed = 0;
00912 for (i = 0; i < n; i++)
00913 {
00914 old_dom = get_immediate_dominator (dir, bbs[i]);
00915 new_dom = recount_dominator (dir, bbs[i]);
00916 if (old_dom != new_dom)
00917 {
00918 changed = 1;
00919 set_immediate_dominator (dir, bbs[i], new_dom);
00920 }
00921 }
00922 }
00923
00924 for (i = 0; i < n; i++)
00925 gcc_assert (get_immediate_dominator (dir, bbs[i]));
00926 }
00927
00928 void
00929 add_to_dominance_info (enum cdi_direction dir, basic_block bb)
00930 {
00931 gcc_assert (dom_computed[dir]);
00932 gcc_assert (!bb->dom[dir]);
00933
00934 n_bbs_in_dom_tree[dir]++;
00935
00936 bb->dom[dir] = et_new_tree (bb);
00937
00938 if (dom_computed[dir] == DOM_OK)
00939 dom_computed[dir] = DOM_NO_FAST_QUERY;
00940 }
00941
00942 void
00943 delete_from_dominance_info (enum cdi_direction dir, basic_block bb)
00944 {
00945 gcc_assert (dom_computed[dir]);
00946
00947 et_free_tree (bb->dom[dir]);
00948 bb->dom[dir] = NULL;
00949 n_bbs_in_dom_tree[dir]--;
00950
00951 if (dom_computed[dir] == DOM_OK)
00952 dom_computed[dir] = DOM_NO_FAST_QUERY;
00953 }
00954
00955
00956
00957
00958 basic_block
00959 first_dom_son (enum cdi_direction dir, basic_block bb)
00960 {
00961 struct et_node *son = bb->dom[dir]->son;
00962
00963 return son ? son->data : NULL;
00964 }
00965
00966
00967
00968
00969 basic_block
00970 next_dom_son (enum cdi_direction dir, basic_block bb)
00971 {
00972 struct et_node *next = bb->dom[dir]->right;
00973
00974 return next->father->son == next ? NULL : next->data;
00975 }
00976
00977
00978
00979 bool
00980 dom_info_available_p (enum cdi_direction dir)
00981 {
00982 return dom_computed[dir] != DOM_NONE;
00983 }
00984
00985 void
00986 debug_dominance_info (enum cdi_direction dir)
00987 {
00988 basic_block bb, bb2;
00989 FOR_EACH_BB (bb)
00990 if ((bb2 = get_immediate_dominator (dir, bb)))
00991 fprintf (stderr, "%i %i\n", bb->index, bb2->index);
00992 }