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 "rtl.h"
00039 #include "hard-reg-set.h"
00040 #include "basic-block.h"
00041 #include "errors.h"
00042 #include "et-forest.h"
00043
00044 struct dominance_info
00045 {
00046 et_forest_t forest;
00047 varray_type varray;
00048 };
00049
00050 #define BB_NODE(info, bb) \
00051 ((et_forest_node_t)VARRAY_GENERIC_PTR ((info)->varray, (bb)->index + 2))
00052 #define SET_BB_NODE(info, bb, node) \
00053 (VARRAY_GENERIC_PTR ((info)->varray, (bb)->index + 2) = (node))
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 typedef unsigned int TBB;
00064
00065
00066
00067
00068
00069
00070 struct dom_info
00071 {
00072
00073 TBB *dfs_parent;
00074
00075
00076
00077 TBB *key;
00078
00079
00080 TBB *path_min;
00081
00082 TBB *bucket;
00083
00084 TBB *next_bucket;
00085
00086
00087 TBB *dom;
00088
00089
00090
00091
00092
00093 TBB *set_chain;
00094
00095 unsigned int *set_size;
00096
00097
00098 TBB *set_child;
00099
00100
00101
00102
00103 TBB *dfs_order;
00104
00105
00106
00107
00108 basic_block *dfs_to_bb;
00109
00110
00111 unsigned int dfsnum;
00112
00113 unsigned int nodes;
00114 };
00115
00116 static void init_dom_info PARAMS ((struct dom_info *));
00117 static void free_dom_info PARAMS ((struct dom_info *));
00118 static void calc_dfs_tree_nonrec PARAMS ((struct dom_info *,
00119 basic_block,
00120 enum cdi_direction));
00121 static void calc_dfs_tree PARAMS ((struct dom_info *,
00122 enum cdi_direction));
00123 static void compress PARAMS ((struct dom_info *, TBB));
00124 static TBB eval PARAMS ((struct dom_info *, TBB));
00125 static void link_roots PARAMS ((struct dom_info *, TBB, TBB));
00126 static void calc_idoms PARAMS ((struct dom_info *,
00127 enum cdi_direction));
00128 void debug_dominance_info PARAMS ((dominance_info));
00129
00130
00131
00132 #define init_ar(var, type, num, content) \
00133 do \
00134 { \
00135 unsigned int i = 1; \
00136 if (! (content)) \
00137 (var) = (type *) xcalloc ((num), sizeof (type)); \
00138 else \
00139 { \
00140 (var) = (type *) xmalloc ((num) * sizeof (type)); \
00141 for (i = 0; i < num; i++) \
00142 (var)[i] = (content); \
00143 } \
00144 } \
00145 while (0)
00146
00147
00148
00149
00150 static void
00151 init_dom_info (di)
00152 struct dom_info *di;
00153 {
00154
00155
00156 unsigned int num = n_basic_blocks + 1 + 1;
00157 init_ar (di->dfs_parent, TBB, num, 0);
00158 init_ar (di->path_min, TBB, num, i);
00159 init_ar (di->key, TBB, num, i);
00160 init_ar (di->dom, TBB, num, 0);
00161
00162 init_ar (di->bucket, TBB, num, 0);
00163 init_ar (di->next_bucket, TBB, num, 0);
00164
00165 init_ar (di->set_chain, TBB, num, 0);
00166 init_ar (di->set_size, unsigned int, num, 1);
00167 init_ar (di->set_child, TBB, num, 0);
00168
00169 init_ar (di->dfs_order, TBB, (unsigned int) last_basic_block + 1, 0);
00170 init_ar (di->dfs_to_bb, basic_block, num, 0);
00171
00172 di->dfsnum = 1;
00173 di->nodes = 0;
00174 }
00175
00176 #undef init_ar
00177
00178
00179
00180 static void
00181 free_dom_info (di)
00182 struct dom_info *di;
00183 {
00184 free (di->dfs_parent);
00185 free (di->path_min);
00186 free (di->key);
00187 free (di->dom);
00188 free (di->bucket);
00189 free (di->next_bucket);
00190 free (di->set_chain);
00191 free (di->set_size);
00192 free (di->set_child);
00193 free (di->dfs_order);
00194 free (di->dfs_to_bb);
00195 }
00196
00197
00198
00199
00200
00201
00202
00203 static void
00204 calc_dfs_tree_nonrec (di, bb, reverse)
00205 struct dom_info *di;
00206 basic_block bb;
00207 enum cdi_direction reverse;
00208 {
00209
00210
00211 edge e;
00212 TBB child_i, my_i = 0;
00213 edge *stack;
00214 int sp;
00215
00216
00217 basic_block en_block;
00218
00219 basic_block ex_block;
00220
00221 stack = (edge *) xmalloc ((n_basic_blocks + 3) * sizeof (edge));
00222 sp = 0;
00223
00224
00225 if (reverse)
00226 {
00227 e = bb->pred;
00228 en_block = EXIT_BLOCK_PTR;
00229 ex_block = ENTRY_BLOCK_PTR;
00230 }
00231 else
00232 {
00233 e = bb->succ;
00234 en_block = ENTRY_BLOCK_PTR;
00235 ex_block = EXIT_BLOCK_PTR;
00236 }
00237
00238
00239 while (1)
00240 {
00241 basic_block bn;
00242
00243
00244
00245 while (e)
00246 {
00247 edge e_next;
00248
00249
00250
00251 if (reverse)
00252 {
00253 bn = e->src;
00254
00255
00256
00257
00258 if (bn == ex_block || di->dfs_order[bn->index])
00259 {
00260 e = e->pred_next;
00261 continue;
00262 }
00263 bb = e->dest;
00264 e_next = bn->pred;
00265 }
00266 else
00267 {
00268 bn = e->dest;
00269 if (bn == ex_block || di->dfs_order[bn->index])
00270 {
00271 e = e->succ_next;
00272 continue;
00273 }
00274 bb = e->src;
00275 e_next = bn->succ;
00276 }
00277
00278 if (bn == en_block)
00279 abort ();
00280
00281
00282 if (bb != en_block)
00283 my_i = di->dfs_order[bb->index];
00284 else
00285 my_i = di->dfs_order[last_basic_block];
00286 child_i = di->dfs_order[bn->index] = di->dfsnum++;
00287 di->dfs_to_bb[child_i] = bn;
00288 di->dfs_parent[child_i] = my_i;
00289
00290
00291 stack[sp++] = e;
00292 e = e_next;
00293 }
00294
00295 if (!sp)
00296 break;
00297 e = stack[--sp];
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 if (reverse)
00309 e = e->pred_next;
00310 else
00311 e = e->succ_next;
00312 }
00313 free (stack);
00314 }
00315
00316
00317
00318
00319
00320
00321 static void
00322 calc_dfs_tree (di, reverse)
00323 struct dom_info *di;
00324 enum cdi_direction reverse;
00325 {
00326
00327 basic_block begin = reverse ? EXIT_BLOCK_PTR : ENTRY_BLOCK_PTR;
00328 di->dfs_order[last_basic_block] = di->dfsnum;
00329 di->dfs_to_bb[di->dfsnum] = begin;
00330 di->dfsnum++;
00331
00332 calc_dfs_tree_nonrec (di, begin, reverse);
00333
00334 if (reverse)
00335 {
00336
00337
00338
00339
00340 basic_block b;
00341 FOR_EACH_BB_REVERSE (b)
00342 {
00343 if (di->dfs_order[b->index])
00344 continue;
00345 di->dfs_order[b->index] = di->dfsnum;
00346 di->dfs_to_bb[di->dfsnum] = b;
00347 di->dfsnum++;
00348 calc_dfs_tree_nonrec (di, b, reverse);
00349 }
00350 }
00351
00352 di->nodes = di->dfsnum - 1;
00353
00354
00355 if (di->nodes != (unsigned int) n_basic_blocks + 1)
00356 abort ();
00357 }
00358
00359
00360
00361
00362
00363
00364 static void
00365 compress (di, v)
00366 struct dom_info *di;
00367 TBB v;
00368 {
00369
00370
00371
00372 TBB parent = di->set_chain[v];
00373 if (di->set_chain[parent])
00374 {
00375 compress (di, parent);
00376 if (di->key[di->path_min[parent]] < di->key[di->path_min[v]])
00377 di->path_min[v] = di->path_min[parent];
00378 di->set_chain[v] = di->set_chain[parent];
00379 }
00380 }
00381
00382
00383
00384
00385
00386 static inline TBB
00387 eval (di, v)
00388 struct dom_info *di;
00389 TBB v;
00390 {
00391
00392
00393 TBB rep = di->set_chain[v];
00394
00395
00396 if (!rep)
00397 return di->path_min[v];
00398
00399
00400 if (di->set_chain[rep])
00401 {
00402 compress (di, v);
00403 rep = di->set_chain[v];
00404 }
00405
00406 if (di->key[di->path_min[rep]] >= di->key[di->path_min[v]])
00407 return di->path_min[v];
00408 else
00409 return di->path_min[rep];
00410 }
00411
00412
00413
00414
00415
00416
00417 static void
00418 link_roots (di, v, w)
00419 struct dom_info *di;
00420 TBB v, w;
00421 {
00422 TBB s = w;
00423
00424
00425 while (di->key[di->path_min[w]] < di->key[di->path_min[di->set_child[s]]])
00426 {
00427 if (di->set_size[s] + di->set_size[di->set_child[di->set_child[s]]]
00428 >= 2 * di->set_size[di->set_child[s]])
00429 {
00430 di->set_chain[di->set_child[s]] = s;
00431 di->set_child[s] = di->set_child[di->set_child[s]];
00432 }
00433 else
00434 {
00435 di->set_size[di->set_child[s]] = di->set_size[s];
00436 s = di->set_chain[s] = di->set_child[s];
00437 }
00438 }
00439
00440 di->path_min[s] = di->path_min[w];
00441 di->set_size[v] += di->set_size[w];
00442 if (di->set_size[v] < 2 * di->set_size[w])
00443 {
00444 TBB tmp = s;
00445 s = di->set_child[v];
00446 di->set_child[v] = tmp;
00447 }
00448
00449
00450 while (s)
00451 {
00452 di->set_chain[s] = v;
00453 s = di->set_child[s];
00454 }
00455 }
00456
00457
00458
00459
00460
00461 static void
00462 calc_idoms (di, reverse)
00463 struct dom_info *di;
00464 enum cdi_direction reverse;
00465 {
00466 TBB v, w, k, par;
00467 basic_block en_block;
00468 if (reverse)
00469 en_block = EXIT_BLOCK_PTR;
00470 else
00471 en_block = ENTRY_BLOCK_PTR;
00472
00473
00474 v = di->nodes;
00475 while (v > 1)
00476 {
00477 basic_block bb = di->dfs_to_bb[v];
00478 edge e, e_next;
00479
00480 par = di->dfs_parent[v];
00481 k = v;
00482 if (reverse)
00483 e = bb->succ;
00484 else
00485 e = bb->pred;
00486
00487
00488
00489
00490
00491 for (; e; e = e_next)
00492 {
00493 TBB k1;
00494 basic_block b;
00495
00496 if (reverse)
00497 {
00498 b = e->dest;
00499 e_next = e->succ_next;
00500 }
00501 else
00502 {
00503 b = e->src;
00504 e_next = e->pred_next;
00505 }
00506 if (b == en_block)
00507 k1 = di->dfs_order[last_basic_block];
00508 else
00509 k1 = di->dfs_order[b->index];
00510
00511
00512
00513 if (k1 > v)
00514 k1 = di->key[eval (di, k1)];
00515 if (k1 < k)
00516 k = k1;
00517 }
00518
00519 di->key[v] = k;
00520 link_roots (di, par, v);
00521 di->next_bucket[v] = di->bucket[k];
00522 di->bucket[k] = v;
00523
00524
00525 for (w = di->bucket[par]; w; w = di->next_bucket[w])
00526 {
00527 k = eval (di, w);
00528 if (di->key[k] < di->key[w])
00529 di->dom[w] = k;
00530 else
00531 di->dom[w] = par;
00532 }
00533
00534 di->bucket[par] = 0;
00535 v--;
00536 }
00537
00538
00539 di->dom[1] = 0;
00540 for (v = 2; v <= di->nodes; v++)
00541 if (di->dom[v] != di->key[v])
00542 di->dom[v] = di->dom[di->dom[v]];
00543 }
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557 dominance_info
00558 calculate_dominance_info (reverse)
00559 enum cdi_direction reverse;
00560 {
00561 struct dom_info di;
00562 dominance_info info;
00563 basic_block b;
00564
00565
00566 info = xmalloc (sizeof (struct dominance_info));
00567 info->forest = et_forest_create ();
00568 VARRAY_GENERIC_PTR_INIT (info->varray, last_basic_block + 3, "dominance info");
00569
00570
00571 SET_BB_NODE (info, ENTRY_BLOCK_PTR, et_forest_add_node (info->forest,
00572 ENTRY_BLOCK_PTR));
00573 SET_BB_NODE (info, EXIT_BLOCK_PTR, et_forest_add_node (info->forest,
00574 EXIT_BLOCK_PTR));
00575 FOR_EACH_BB (b)
00576 SET_BB_NODE (info, b, et_forest_add_node (info->forest, b));
00577
00578 init_dom_info (&di);
00579 calc_dfs_tree (&di, reverse);
00580 calc_idoms (&di, reverse);
00581
00582
00583 FOR_EACH_BB (b)
00584 {
00585 TBB d = di.dom[di.dfs_order[b->index]];
00586
00587 if (di.dfs_to_bb[d])
00588 et_forest_add_edge (info->forest, BB_NODE (info, di.dfs_to_bb[d]), BB_NODE (info, b));
00589 }
00590
00591 free_dom_info (&di);
00592 return info;
00593 }
00594
00595
00596 void
00597 free_dominance_info (info)
00598 dominance_info info;
00599 {
00600 basic_block bb;
00601
00602
00603
00604 FOR_EACH_BB (bb)
00605 if (bb->index < (int)(info->varray->num_elements - 2)
00606 && BB_NODE (info, bb))
00607 delete_from_dominance_info (info, bb);
00608 delete_from_dominance_info (info, ENTRY_BLOCK_PTR);
00609 delete_from_dominance_info (info, EXIT_BLOCK_PTR);
00610 et_forest_delete (info->forest);
00611 VARRAY_GROW (info->varray, 0);
00612 free (info);
00613 }
00614
00615
00616 basic_block
00617 get_immediate_dominator (dom, bb)
00618 dominance_info dom;
00619 basic_block bb;
00620 {
00621 return et_forest_node_value (dom->forest,
00622 et_forest_parent (dom->forest,
00623 BB_NODE (dom, bb)));
00624 }
00625
00626
00627
00628 #ifndef KEY
00629 inline
00630 #endif
00631 void
00632 set_immediate_dominator (dom, bb, dominated_by)
00633 dominance_info dom;
00634 basic_block bb, dominated_by;
00635 {
00636 void *aux_bb_node;
00637 et_forest_node_t bb_node = BB_NODE (dom, bb);
00638
00639 aux_bb_node = et_forest_parent (dom->forest, bb_node);
00640 if (aux_bb_node)
00641 et_forest_remove_edge (dom->forest, aux_bb_node, bb_node);
00642 if (dominated_by != NULL)
00643 {
00644 if (bb == dominated_by)
00645 abort ();
00646 if (!et_forest_add_edge (dom->forest, BB_NODE (dom, dominated_by), bb_node))
00647 abort ();
00648 }
00649 }
00650
00651
00652 int
00653 get_dominated_by (dom, bb, bbs)
00654 dominance_info dom;
00655 basic_block bb;
00656 basic_block **bbs;
00657 {
00658 int n, i;
00659
00660 *bbs = xmalloc (n_basic_blocks * sizeof (basic_block));
00661 n = et_forest_enumerate_sons (dom->forest, BB_NODE (dom, bb), (et_forest_node_t *)*bbs);
00662 for (i = 0; i < n; i++)
00663 (*bbs)[i] = et_forest_node_value (dom->forest, (et_forest_node_t)(*bbs)[i]);
00664 return n;
00665 }
00666
00667
00668 void
00669 redirect_immediate_dominators (dom, bb, to)
00670 dominance_info dom;
00671 basic_block bb;
00672 basic_block to;
00673 {
00674 et_forest_node_t *bbs = xmalloc (n_basic_blocks * sizeof (basic_block));
00675 et_forest_node_t node = BB_NODE (dom, bb);
00676 et_forest_node_t node2 = BB_NODE (dom, to);
00677 int n = et_forest_enumerate_sons (dom->forest, node, bbs);
00678 int i;
00679
00680 for (i = 0; i < n; i++)
00681 {
00682 et_forest_remove_edge (dom->forest, node, bbs[i]);
00683 et_forest_add_edge (dom->forest, node2, bbs[i]);
00684 }
00685 free (bbs);
00686 }
00687
00688
00689 basic_block
00690 nearest_common_dominator (dom, bb1, bb2)
00691 dominance_info dom;
00692 basic_block bb1;
00693 basic_block bb2;
00694 {
00695 if (!bb1)
00696 return bb2;
00697 if (!bb2)
00698 return bb1;
00699 return et_forest_node_value (dom->forest,
00700 et_forest_common_ancestor (dom->forest,
00701 BB_NODE (dom, bb1),
00702 BB_NODE (dom,
00703 bb2)));
00704 }
00705
00706
00707 bool
00708 dominated_by_p (dom, bb1, bb2)
00709 dominance_info dom;
00710 basic_block bb1;
00711 basic_block bb2;
00712 {
00713 return nearest_common_dominator (dom, bb1, bb2) == bb2;
00714 }
00715
00716
00717 void
00718 verify_dominators (dom)
00719 dominance_info dom;
00720 {
00721 int err = 0;
00722 basic_block bb;
00723
00724 FOR_EACH_BB (bb)
00725 {
00726 basic_block dom_bb;
00727
00728 dom_bb = recount_dominator (dom, bb);
00729 if (dom_bb != get_immediate_dominator (dom, bb))
00730 {
00731 error ("dominator of %d should be %d, not %d",
00732 bb->index, dom_bb->index, get_immediate_dominator(dom, bb)->index);
00733 err = 1;
00734 }
00735 }
00736 if (err)
00737 abort ();
00738 }
00739
00740
00741 basic_block
00742 recount_dominator (dom, bb)
00743 dominance_info dom;
00744 basic_block bb;
00745 {
00746 basic_block dom_bb = NULL;
00747 edge e;
00748
00749 for (e = bb->pred; e; e = e->pred_next)
00750 {
00751 if (!dominated_by_p (dom, e->src, bb))
00752 dom_bb = nearest_common_dominator (dom, dom_bb, e->src);
00753 }
00754
00755 return dom_bb;
00756 }
00757
00758
00759
00760 void
00761 iterate_fix_dominators (dom, bbs, n)
00762 dominance_info dom;
00763 basic_block *bbs;
00764 int n;
00765 {
00766 int i, changed = 1;
00767 basic_block old_dom, new_dom;
00768
00769 while (changed)
00770 {
00771 changed = 0;
00772 for (i = 0; i < n; i++)
00773 {
00774 old_dom = get_immediate_dominator (dom, bbs[i]);
00775 new_dom = recount_dominator (dom, bbs[i]);
00776 if (old_dom != new_dom)
00777 {
00778 changed = 1;
00779 set_immediate_dominator (dom, bbs[i], new_dom);
00780 }
00781 }
00782 }
00783 }
00784
00785 void
00786 add_to_dominance_info (dom, bb)
00787 dominance_info dom;
00788 basic_block bb;
00789 {
00790 VARRAY_GROW (dom->varray, last_basic_block + 3);
00791 #ifdef ENABLE_CHECKING
00792 if (BB_NODE (dom, bb))
00793 abort ();
00794 #endif
00795 SET_BB_NODE (dom, bb, et_forest_add_node (dom->forest, bb));
00796 }
00797
00798 void
00799 delete_from_dominance_info (dom, bb)
00800 dominance_info dom;
00801 basic_block bb;
00802 {
00803 et_forest_remove_node (dom->forest, BB_NODE (dom, bb));
00804 SET_BB_NODE (dom, bb, NULL);
00805 }
00806
00807 void
00808 debug_dominance_info (dom)
00809 dominance_info dom;
00810 {
00811 basic_block bb, bb2;
00812 FOR_EACH_BB (bb)
00813 if ((bb2 = get_immediate_dominator (dom, bb)))
00814 fprintf (stderr, "%i %i\n", bb->index, bb2->index);
00815 }