1 /* src/vm/jit/optimizing/dominators.cpp - dominators and dominance frontier
3 Copyright (C) 2005, 2006, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
28 #include "mm/memory.h"
30 #include "toolbox/bitvector.h"
32 #include "vm/jit/jit.hpp"
34 #include "vm/jit/optimizing/graph.h"
35 #include "vm/jit/optimizing/dominators.hpp"
38 /* function prototypes */
39 void dom_Dominators_init(dominatordata *dd, int basicblockcount);
40 #ifdef DOM_DEBUG_CHECK
41 int dom_AncestorWithLowestSemi(dominatordata *dd, int v, int basicblockcount);
42 void dom_Link(dominatordata *dd, int p, int n, int basicblockcount);
43 void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N,
46 int dom_AncestorWithLowestSemi(dominatordata *dd, int v);
47 void dom_Link(dominatordata *dd, int p, int n);
48 void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N);
51 /*************************************
53 *************************************/
54 dominatordata *compute_Dominators(graphdata *gd, int basicblockcount) {
55 int i,j,n,N,p,s,s_,v,y;
59 dd = DNEW(dominatordata);
61 dom_Dominators_init(dd, basicblockcount);
65 /* 1 ist the root node of the method */
66 /* 0 is the artificial parent, where locals are set to their parameters */
67 dom_DFS(gd, dd, -1, 0, &N
68 #ifdef DOM_DEBUG_CHECK
73 for(i = N-1; i > 0; i--) {
74 _DOM_CHECK_BOUNDS(i, 0, basicblockcount);
76 _DOM_CHECK_BOUNDS(n, 0, basicblockcount);
79 j = graph_get_first_predecessor(gd, n, &iter);
80 for (; j != -1; j = graph_get_next(&iter)) {
81 _DOM_CHECK_BOUNDS(j, 0, basicblockcount);
82 if (dd->dfnum[j] <= dd->dfnum[n])
85 s_ = dd->semi[dom_AncestorWithLowestSemi(dd, j
86 #ifdef DOM_DEBUG_CHECK
90 _DOM_CHECK_BOUNDS(s_, 0, basicblockcount);
91 _DOM_CHECK_BOUNDS(s, 0, basicblockcount);
92 if (dd->dfnum[s_] < dd->dfnum[s])
96 _DOM_CHECK_BOUNDS(dd->num_bucket[s], 0, basicblockcount);
97 dd->bucket[s][dd->num_bucket[s]] = n;
100 #ifdef DOM_DEBUG_CHECK
104 _DOM_CHECK_BOUNDS(p, 0, basicblockcount);
105 for(j = 0; j < dd->num_bucket[p]; j++) {
106 _DOM_CHECK_BOUNDS(j, 0, basicblockcount);
107 v = dd->bucket[p][j];
108 y = dom_AncestorWithLowestSemi(dd, v
109 #ifdef DOM_DEBUG_CHECK
113 _DOM_CHECK_BOUNDS(y, 0, basicblockcount);
114 _DOM_CHECK_BOUNDS(v, 0, basicblockcount);
115 if (dd->semi[y] == dd->semi[v])
120 dd->num_bucket[p] = 0;
122 for(i = 1; i < N; i++) {
124 _DOM_CHECK_BOUNDS(n, 0, basicblockcount);
125 if (dd->samedom[n] != -1) {
126 _DOM_CHECK_BOUNDS(dd->samedom[n], 0, basicblockcount);
127 dd->idom[n] = dd->idom[dd->samedom[n]];
133 /********************************************
134 compute Dominace Frontier
135 ********************************************/
136 void computeDF(graphdata *gd, dominatordata *dd, int basicblockcount, int n) {
141 _S = DMNEW(bool, basicblockcount);
142 for(i = 0; i < basicblockcount; i++)
144 i = graph_get_first_successor(gd, n, &iter);
145 for (; i != -1; i = graph_get_next(&iter)) {
146 _DOM_CHECK_BOUNDS(i, 0, basicblockcount);
147 if (dd->idom[i] != n)
150 for(c=0; c < basicblockcount; c++) {
151 if (dd->idom[c] == n) {
152 computeDF(gd, dd, basicblockcount, c);
153 for(j=0; j < dd->num_DF[c]; j++) {
154 _DOM_CHECK_BOUNDS(dd->DF[c][j], 0, basicblockcount);
155 if (n != dd->idom[dd->DF[c][j]])
156 /* n does not dominate DF[c][j] -> traverse idom list? */
157 _S[dd->DF[c][j]] = true;
161 for(i = 0; i < basicblockcount; i++)
163 _DOM_CHECK_BOUNDS(dd->num_DF[n], 0, basicblockcount);
164 dd->DF[n][dd->num_DF[n]] = i;
170 void dom_Dominators_init(dominatordata *dd, int basicblockcount) {
173 dd->dfnum = DMNEW(int, basicblockcount);
174 dd->vertex = DMNEW(int, basicblockcount);
175 dd->parent = DMNEW(int, basicblockcount);
176 dd->semi = DMNEW(int, basicblockcount);
177 dd->ancestor = DMNEW(int, basicblockcount);
178 dd->idom = DMNEW(int, basicblockcount);
179 dd->samedom = DMNEW(int, basicblockcount);
180 dd->bucket = DMNEW(int*, basicblockcount);
181 dd->num_bucket = DMNEW(int, basicblockcount);
182 dd->DF = DMNEW(int*, basicblockcount);
183 dd->num_DF = DMNEW(int, basicblockcount);
184 dd->best = DMNEW(int, basicblockcount);
185 for (i=0; i < basicblockcount; i++) {
187 dd->semi[i] = dd->ancestor[i] = dd->idom[i] = dd->samedom[i] = -1;
188 dd->num_bucket[i] = 0;
189 dd->bucket[i] = DMNEW(int, basicblockcount);
191 dd->DF[i] = DMNEW(int, basicblockcount);
195 /**************************************
196 Create Depth First Spanning Tree
197 **************************************/
198 #ifdef DOM_DEBUG_CHECK
199 void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N,
200 int basicblockcount) {
202 void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N) {
207 _DOM_CHECK_BOUNDS(n,0,basicblockcount);
208 if (dd->dfnum[n] == -1) { /* not visited till now? */
210 _DOM_CHECK_BOUNDS(*N,0,basicblockcount);
214 i = graph_get_first_successor(gd, n, &iter);
215 for (; i != -1; i = graph_get_next(&iter)) {
216 dom_DFS(gd, dd, n, i, N
217 #ifdef DOM_DEBUG_CHECK
225 #ifdef DOM_DEBUG_CHECK
226 int dom_AncestorWithLowestSemi(dominatordata *dd, int v, int basicblockcount) {
228 int dom_AncestorWithLowestSemi(dominatordata *dd, int v) {
232 _DOM_CHECK_BOUNDS(v, 0, basicblockcount);
234 _DOM_CHECK_BOUNDS(a,0,basicblockcount);
235 if (dd->ancestor[a] != -1) {
236 b = dom_AncestorWithLowestSemi(dd, a
237 #ifdef DOM_DEBUG_CHECK
241 dd->ancestor[v] = dd->ancestor[a];
242 _DOM_CHECK_BOUNDS(b,0,basicblockcount);
243 _DOM_CHECK_BOUNDS(dd->best[v],0,basicblockcount);
244 _DOM_CHECK_BOUNDS(dd->semi[dd->best[v]],0,basicblockcount);
245 if (dd->dfnum[dd->semi[b]] < dd->dfnum[dd->semi[dd->best[v]]])
251 #ifdef DOM_DEBUG_CHECK
252 void dom_Link(dominatordata *dd, int p, int n, int basicblockcount) {
254 void dom_Link(dominatordata *dd, int p, int n) {
256 _DOM_CHECK_BOUNDS(n,0,basicblockcount);
261 /*********************************************************/
263 typedef struct basicblock_info basicblock_info;
265 struct basicblock_info {
268 basicblock_info *parent;
269 basicblock_info *semi;
270 basicblock_info *ancestor;
271 basicblock_info *best;
272 basicblock_info *idom;
273 basicblock_info *samedom;
274 basicblock_info **bucket;
275 unsigned bucketcount;
278 typedef struct dominator_tree_info dominator_tree_info;
280 struct dominator_tree_info {
282 basicblock_info *basicblocks;
283 basicblock_info **df_map;
287 static dominator_tree_info *dominator_tree_init(jitdata *jd) {
288 dominator_tree_info *di;
290 basicblock_info *iti;
292 di = DNEW(dominator_tree_info);
296 di->basicblocks = DMNEW(basicblock_info, jd->basicblockcount);
297 MZERO(di->basicblocks, basicblock_info, jd->basicblockcount);
299 for (iti = di->basicblocks; iti != di->basicblocks + jd->basicblockcount; ++iti) {
301 iti->bucket = DMNEW(basicblock_info *, jd->basicblockcount);
302 iti->bucketcount = 0;
305 for (itb = jd->basicblocks; itb; itb = itb->next) {
306 di->basicblocks[itb->nr].bb = itb;
309 di->df_map = DMNEW(basicblock_info *, jd->basicblockcount);
310 MZERO(di->df_map, basicblock_info *, jd->basicblockcount);
317 static inline basicblock_info *dominator_tree_get_basicblock(dominator_tree_info *di, basicblock *bb) {
318 return di->basicblocks + bb->nr;
321 static void dominator_tree_depth_first_search(
322 dominator_tree_info *di, basicblock_info *parent, basicblock_info *node
326 if (node->dfnum == -1) {
328 node->dfnum = di->df_counter;
329 node->parent = parent;
330 di->df_map[di->df_counter] = node;
333 for (it = node->bb->successors; it != node->bb->successors + node->bb->successorcount; ++it) {
334 dominator_tree_depth_first_search(
336 dominator_tree_get_basicblock(di, *it)
342 void dominator_tree_link(dominator_tree_info *di, basicblock_info *parent, basicblock_info *node) {
343 node->ancestor = parent;
347 basicblock_info *dominator_tree_ancestor_with_lowest_semi(
348 dominator_tree_info *di, basicblock_info *node
350 basicblock_info *a, *b;
354 if (a->ancestor != NULL) {
355 b = dominator_tree_ancestor_with_lowest_semi(di, a);
356 node->ancestor = a->ancestor;
357 if (b->semi->dfnum < node->best->semi->dfnum) {
365 void dominator_tree_build_intern(jitdata *jd) {
367 dominator_tree_info *di;
368 basicblock_info *node;
369 basicblock_info *semicand;
370 basicblock_info *pred;
372 basicblock_info **itii;
373 basicblock_info *v, *y;
376 di = dominator_tree_init(jd);
378 dominator_tree_depth_first_search(di, NULL, dominator_tree_get_basicblock(di, jd->basicblocks));
380 for (i = di->df_counter - 1; i >= 1; --i) {
381 node = di->df_map[i];
383 node->semi = node->parent;
386 itb = node->bb->predecessors;
387 itb != node->bb->predecessors + node->bb->predecessorcount;
391 pred = dominator_tree_get_basicblock(di, *itb);
393 if (pred->dfnum <= node->dfnum) {
396 semicand = dominator_tree_ancestor_with_lowest_semi(di, pred)->semi;
399 if (semicand->dfnum < node->semi->dfnum) {
400 node->semi = semicand;
404 node->semi->bucket[node->semi->bucketcount] = node;
405 node->semi->bucketcount += 1;
407 dominator_tree_link(di, node->parent, node);
409 for (itii = node->parent->bucket; itii != node->parent->bucket + node->parent->bucketcount; ++itii) {
411 y = dominator_tree_ancestor_with_lowest_semi(di, v);
412 if (y->semi == v->semi) {
413 v->idom = node->parent;
419 node->parent->bucketcount = 0;
422 for (i = 1; i < di->df_counter; ++i) {
423 node = di->df_map[i];
425 node->idom = node->samedom->idom;
428 node->bb->idom = node->idom->bb;
429 node->idom->bb->domsuccessorcount += 1;
433 void dominator_tree_link_children(jitdata *jd) {
436 /* basicblock number => current number of successors */
437 unsigned *numsuccessors;
439 /* Allocate memory for successors */
441 for (bb = jd->basicblocks; bb; bb = bb->next) {
442 if (bb->domsuccessorcount > 0) {
443 bb->domsuccessors = DMNEW(basicblock *, bb->domsuccessorcount);
447 /* Allocate memory for per basic block counter of successors */
449 ds = dumpmemory_marker();
450 numsuccessors = DMNEW(unsigned, jd->basicblockcount);
451 MZERO(numsuccessors, unsigned, jd->basicblockcount);
453 /* Link immediate dominators with successors */
455 for (bb = jd->basicblocks; bb; bb = bb->next) {
457 bb->idom->domsuccessors[numsuccessors[bb->idom->nr]] = bb;
458 numsuccessors[bb->idom->nr] += 1;
464 dumpmemory_release(ds);
467 bool dominator_tree_build(jitdata *jd) {
470 ds = dumpmemory_marker();
471 dominator_tree_build_intern(jd);
472 dumpmemory_release(ds);
474 dominator_tree_link_children(jd);
479 typedef struct dominance_frontier_item dominance_frontier_item;
481 struct dominance_frontier_item {
483 dominance_frontier_item *next;
486 typedef struct dominance_frontier_list dominance_frontier_list;
488 struct dominance_frontier_list {
489 dominance_frontier_item *first;
493 void dominance_frontier_list_add(dominance_frontier_list *list, basicblock *bb) {
494 dominance_frontier_item *item;
496 for (item = list->first; item; item = item->next) {
497 if (item->bb == bb) return;
500 item = DNEW(dominance_frontier_item);
502 item->next = list->first;
507 typedef struct dominance_frontier_info dominance_frontier_info;
509 struct dominance_frontier_info {
511 dominance_frontier_list *map;
514 dominance_frontier_info *dominance_frontier_init(jitdata *jd) {
515 dominance_frontier_info *dfi = DNEW(dominance_frontier_info);
519 dfi->map = DMNEW(dominance_frontier_list, jd->basicblockcount);
520 MZERO(dfi->map, dominance_frontier_list, jd->basicblockcount);
525 bool dominance_frontier_dominates(basicblock *d, basicblock *x) {
538 void dominance_frontier_for_block(dominance_frontier_info *dfi, basicblock *b) {
540 dominance_frontier_item *itdf;
541 dominance_frontier_list s = { NULL, 0 };
543 for (it = b->successors; it != b->successors + b->successorcount; ++it) {
544 if ((*it)->idom != b) {
545 dominance_frontier_list_add(&s, *it);
549 for (it = b->domsuccessors; it != b->domsuccessors + b->domsuccessorcount; ++it) {
550 dominance_frontier_for_block(dfi, *it);
551 for (itdf = dfi->map[(*it)->nr].first; itdf; itdf = itdf->next) {
552 if (! dominance_frontier_dominates(b, itdf->bb)) {
553 dominance_frontier_list_add(&s, itdf->bb);
561 void dominance_frontier_store(dominance_frontier_info *dfi) {
563 dominance_frontier_item *itdf;
566 for (bb = dfi->jd->basicblocks; bb; bb = bb->next) {
567 if (bb->nr < dfi->jd->basicblockcount) {
568 if (dfi->map[bb->nr].count > 0) {
569 bb->domfrontiercount = dfi->map[bb->nr].count;
570 itout = bb->domfrontier = DMNEW(basicblock *, bb->domfrontiercount);
571 for (itdf = dfi->map[bb->nr].first; itdf; itdf = itdf->next) {
580 bool dominance_frontier_build(jitdata *jd) {
581 int32_t ds = dumpmemory_marker();
583 dominance_frontier_info *dfi = dominance_frontier_init(jd);
584 dominance_frontier_for_block(dfi, jd->basicblocks);
585 dominance_frontier_store(dfi);
588 #include "vm/jit/show.h"
589 #include "vm/jit/python.h"
591 extern void graph_add_edge( graphdata *gd, int from, int to );
593 void dominator_tree_validate(jitdata *jd, dominatordata *_dd) {
594 int32_t ds = dumpmemory_marker();
597 basicblock *bptr, **it;
602 fprintf(stderr, "%s/%s: \n", jd->m->clazz->name->text, jd->m->name->text);
603 gd = graph_init(jd->basicblockcount);
605 for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
606 for (it = bptr->successors; it != bptr->successors + bptr->successorcount; ++it) {
607 graph_add_edge(gd, bptr->nr, (*it)->nr);
611 dd = compute_Dominators(gd, jd->basicblockcount);
613 for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
614 if (bptr->flags >= BBREACHED) {
615 if (bptr->idom == NULL) {
616 if (!(dd->idom[bptr->nr] == -1)) {
617 printf("-- %d %d\n", dd->idom[bptr->nr], bptr->nr);
621 assert(dd->idom[bptr->nr] == bptr->idom->nr);
626 computeDF(gd, dd, jd->basicblockcount, 0);
628 for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
629 if (bptr->flags >= BBREACHED) {
630 assert(bptr->domfrontiercount == dd->num_DF[bptr->nr]);
631 for (itnr = dd->DF[bptr->nr]; itnr != dd->DF[bptr->nr] + dd->num_DF[bptr->nr]; ++itnr) {
633 for (it = bptr->domfrontier; it != bptr->domfrontier + bptr->domfrontiercount; ++it) {
634 if ((*it)->nr == *itnr) {
643 dumpmemory_release(ds);
647 * These are local overrides for various environment variables in Emacs.
648 * Please do not remove this and leave it at the end of the file, where
649 * Emacs will automagically detect them.
650 * ---------------------------------------------------------------------
653 * indent-tabs-mode: t