1 /* src/vm/jit/optimizing/dominators.c - 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
26 #include "mm/memory.h"
28 #include "toolbox/bitvector.h"
30 #include "vm/jit/jit.h"
32 #include "vm/jit/optimizing/graph.h"
33 #include "vm/jit/optimizing/dominators.h"
35 /* function prototypes */
36 void dom_Dominators_init(dominatordata *dd, int basicblockcount);
37 #ifdef DOM_DEBUG_CHECK
38 int dom_AncestorWithLowestSemi(dominatordata *dd, int v, int basicblockcount);
39 void dom_Link(dominatordata *dd, int p, int n, int basicblockcount);
40 void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N,
43 int dom_AncestorWithLowestSemi(dominatordata *dd, int v);
44 void dom_Link(dominatordata *dd, int p, int n);
45 void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N);
48 /*************************************
50 *************************************/
51 dominatordata *compute_Dominators(graphdata *gd, int basicblockcount) {
52 int i,j,n,N,p,s,s_,v,y;
56 dd = DNEW(dominatordata);
58 dom_Dominators_init(dd, basicblockcount);
62 /* 1 ist the root node of the method */
63 /* 0 is the artificial parent, where locals are set to their parameters */
64 dom_DFS(gd, dd, -1, 0, &N
65 #ifdef DOM_DEBUG_CHECK
70 for(i = N-1; i > 0; i--) {
71 _DOM_CHECK_BOUNDS(i, 0, basicblockcount);
73 _DOM_CHECK_BOUNDS(n, 0, basicblockcount);
76 j = graph_get_first_predecessor(gd, n, &iter);
77 for (; j != -1; j = graph_get_next(&iter)) {
78 _DOM_CHECK_BOUNDS(j, 0, basicblockcount);
79 if (dd->dfnum[j] <= dd->dfnum[n])
82 s_ = dd->semi[dom_AncestorWithLowestSemi(dd, j
83 #ifdef DOM_DEBUG_CHECK
87 _DOM_CHECK_BOUNDS(s_, 0, basicblockcount);
88 _DOM_CHECK_BOUNDS(s, 0, basicblockcount);
89 if (dd->dfnum[s_] < dd->dfnum[s])
93 _DOM_CHECK_BOUNDS(dd->num_bucket[s], 0, basicblockcount);
94 dd->bucket[s][dd->num_bucket[s]] = n;
97 #ifdef DOM_DEBUG_CHECK
101 _DOM_CHECK_BOUNDS(p, 0, basicblockcount);
102 for(j = 0; j < dd->num_bucket[p]; j++) {
103 _DOM_CHECK_BOUNDS(j, 0, basicblockcount);
104 v = dd->bucket[p][j];
105 y = dom_AncestorWithLowestSemi(dd, v
106 #ifdef DOM_DEBUG_CHECK
110 _DOM_CHECK_BOUNDS(y, 0, basicblockcount);
111 _DOM_CHECK_BOUNDS(v, 0, basicblockcount);
112 if (dd->semi[y] == dd->semi[v])
117 dd->num_bucket[p] = 0;
119 for(i = 1; i < N; i++) {
121 _DOM_CHECK_BOUNDS(n, 0, basicblockcount);
122 if (dd->samedom[n] != -1) {
123 _DOM_CHECK_BOUNDS(dd->samedom[n], 0, basicblockcount);
124 dd->idom[n] = dd->idom[dd->samedom[n]];
130 /********************************************
131 compute Dominace Frontier
132 ********************************************/
133 void computeDF(graphdata *gd, dominatordata *dd, int basicblockcount, int n) {
138 _S = DMNEW(bool, basicblockcount);
139 for(i = 0; i < basicblockcount; i++)
141 i = graph_get_first_successor(gd, n, &iter);
142 for (; i != -1; i = graph_get_next(&iter)) {
143 _DOM_CHECK_BOUNDS(i, 0, basicblockcount);
144 if (dd->idom[i] != n)
147 for(c=0; c < basicblockcount; c++) {
148 if (dd->idom[c] == n) {
149 computeDF(gd, dd, basicblockcount, c);
150 for(j=0; j < dd->num_DF[c]; j++) {
151 _DOM_CHECK_BOUNDS(dd->DF[c][j], 0, basicblockcount);
152 if (n != dd->idom[dd->DF[c][j]])
153 /* n does not dominate DF[c][j] -> traverse idom list? */
154 _S[dd->DF[c][j]] = true;
158 for(i = 0; i < basicblockcount; i++)
160 _DOM_CHECK_BOUNDS(dd->num_DF[n], 0, basicblockcount);
161 dd->DF[n][dd->num_DF[n]] = i;
167 void dom_Dominators_init(dominatordata *dd, int basicblockcount) {
170 dd->dfnum = DMNEW(int, basicblockcount);
171 dd->vertex = DMNEW(int, basicblockcount);
172 dd->parent = DMNEW(int, basicblockcount);
173 dd->semi = DMNEW(int, basicblockcount);
174 dd->ancestor = DMNEW(int, basicblockcount);
175 dd->idom = DMNEW(int, basicblockcount);
176 dd->samedom = DMNEW(int, basicblockcount);
177 dd->bucket = DMNEW(int*, basicblockcount);
178 dd->num_bucket = DMNEW(int, basicblockcount);
179 dd->DF = DMNEW(int*, basicblockcount);
180 dd->num_DF = DMNEW(int, basicblockcount);
181 dd->best = DMNEW(int, basicblockcount);
182 for (i=0; i < basicblockcount; i++) {
184 dd->semi[i] = dd->ancestor[i] = dd->idom[i] = dd->samedom[i] = -1;
185 dd->num_bucket[i] = 0;
186 dd->bucket[i] = DMNEW(int, basicblockcount);
188 dd->DF[i] = DMNEW(int, basicblockcount);
192 /**************************************
193 Create Depth First Spanning Tree
194 **************************************/
195 #ifdef DOM_DEBUG_CHECK
196 void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N,
197 int basicblockcount) {
199 void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N) {
204 _DOM_CHECK_BOUNDS(n,0,basicblockcount);
205 if (dd->dfnum[n] == -1) { /* not visited till now? */
207 _DOM_CHECK_BOUNDS(*N,0,basicblockcount);
211 i = graph_get_first_successor(gd, n, &iter);
212 for (; i != -1; i = graph_get_next(&iter)) {
213 dom_DFS(gd, dd, n, i, N
214 #ifdef DOM_DEBUG_CHECK
222 #ifdef DOM_DEBUG_CHECK
223 int dom_AncestorWithLowestSemi(dominatordata *dd, int v, int basicblockcount) {
225 int dom_AncestorWithLowestSemi(dominatordata *dd, int v) {
229 _DOM_CHECK_BOUNDS(v, 0, basicblockcount);
231 _DOM_CHECK_BOUNDS(a,0,basicblockcount);
232 if (dd->ancestor[a] != -1) {
233 b = dom_AncestorWithLowestSemi(dd, a
234 #ifdef DOM_DEBUG_CHECK
238 dd->ancestor[v] = dd->ancestor[a];
239 _DOM_CHECK_BOUNDS(b,0,basicblockcount);
240 _DOM_CHECK_BOUNDS(dd->best[v],0,basicblockcount);
241 _DOM_CHECK_BOUNDS(dd->semi[dd->best[v]],0,basicblockcount);
242 if (dd->dfnum[dd->semi[b]] < dd->dfnum[dd->semi[dd->best[v]]])
248 #ifdef DOM_DEBUG_CHECK
249 void dom_Link(dominatordata *dd, int p, int n, int basicblockcount) {
251 void dom_Link(dominatordata *dd, int p, int n) {
253 _DOM_CHECK_BOUNDS(n,0,basicblockcount);
258 /*********************************************************/
260 typedef struct basicblock_info basicblock_info;
262 struct basicblock_info {
265 basicblock_info *parent;
266 basicblock_info *semi;
267 basicblock_info *ancestor;
268 basicblock_info *best;
269 basicblock_info *idom;
270 basicblock_info *samedom;
271 basicblock_info **bucket;
272 unsigned bucketcount;
275 typedef struct dominator_tree_info dominator_tree_info;
277 struct dominator_tree_info {
279 basicblock_info *basicblocks;
280 basicblock_info **df_map;
284 static dominator_tree_info *dominator_tree_init(jitdata *jd) {
285 dominator_tree_info *di;
287 basicblock_info *iti;
289 di = DNEW(dominator_tree_info);
293 di->basicblocks = DMNEW(basicblock_info, jd->basicblockcount);
294 MZERO(di->basicblocks, basicblock_info, jd->basicblockcount);
296 for (iti = di->basicblocks; iti != di->basicblocks + jd->basicblockcount; ++iti) {
298 iti->bucket = DMNEW(basicblock_info *, jd->basicblockcount);
299 iti->bucketcount = 0;
302 for (itb = jd->basicblocks; itb; itb = itb->next) {
303 di->basicblocks[itb->nr].bb = itb;
306 di->df_map = DMNEW(basicblock_info *, jd->basicblockcount);
307 MZERO(di->df_map, basicblock_info *, jd->basicblockcount);
314 inline basicblock_info *dominator_tree_get_basicblock(dominator_tree_info *di, basicblock *bb) {
315 return di->basicblocks + bb->nr;
318 static void dominator_tree_depth_first_search(
319 dominator_tree_info *di, basicblock_info *parent, basicblock_info *node
323 if (node->dfnum == -1) {
325 node->dfnum = di->df_counter;
326 node->parent = parent;
327 di->df_map[di->df_counter] = node;
330 for (it = node->bb->successors; it != node->bb->successors + node->bb->successorcount; ++it) {
331 dominator_tree_depth_first_search(
333 dominator_tree_get_basicblock(di, *it)
339 void dominator_tree_link(dominator_tree_info *di, basicblock_info *parent, basicblock_info *node) {
340 node->ancestor = parent;
344 basicblock_info *dominator_tree_ancestor_with_lowest_semi(
345 dominator_tree_info *di, basicblock_info *node
347 basicblock_info *a, *b;
351 if (a->ancestor != NULL) {
352 b = dominator_tree_ancestor_with_lowest_semi(di, a);
353 node->ancestor = a->ancestor;
354 if (b->semi->dfnum < node->best->semi->dfnum) {
362 void dominator_tree_build_intern(jitdata *jd) {
364 dominator_tree_info *di;
365 basicblock_info *node;
366 basicblock_info *semicand;
367 basicblock_info *pred;
369 basicblock_info **itii;
370 basicblock_info *v, *y;
373 di = dominator_tree_init(jd);
375 dominator_tree_depth_first_search(di, NULL, dominator_tree_get_basicblock(di, jd->basicblocks));
377 for (i = di->df_counter - 1; i >= 1; --i) {
378 node = di->df_map[i];
380 node->semi = node->parent;
383 itb = node->bb->predecessors;
384 itb != node->bb->predecessors + node->bb->predecessorcount;
388 pred = dominator_tree_get_basicblock(di, *itb);
390 if (pred->dfnum <= node->dfnum) {
393 semicand = dominator_tree_ancestor_with_lowest_semi(di, pred)->semi;
396 if (semicand->dfnum < node->semi->dfnum) {
397 node->semi = semicand;
401 node->semi->bucket[node->semi->bucketcount] = node;
402 node->semi->bucketcount += 1;
404 dominator_tree_link(di, node->parent, node);
406 for (itii = node->parent->bucket; itii != node->parent->bucket + node->parent->bucketcount; ++itii) {
408 y = dominator_tree_ancestor_with_lowest_semi(di, v);
409 if (y->semi == v->semi) {
410 v->idom = node->parent;
416 node->parent->bucketcount = 0;
419 for (i = 1; i < di->df_counter; ++i) {
420 node = di->df_map[i];
422 node->idom = node->samedom->idom;
425 node->bb->idom = node->idom->bb;
426 node->idom->bb->domsuccessorcount += 1;
430 void dominator_tree_link_children(jitdata *jd) {
433 /* basicblock number => current number of successors */
434 unsigned *numsuccessors;
436 /* Allocate memory for successors */
438 for (bb = jd->basicblocks; bb; bb = bb->next) {
439 if (bb->domsuccessorcount > 0) {
440 bb->domsuccessors = DMNEW(basicblock *, bb->domsuccessorcount);
444 /* Allocate memory for per basic block counter of successors */
446 ds = dumpmemory_marker();
447 numsuccessors = DMNEW(unsigned, jd->basicblockcount);
448 MZERO(numsuccessors, unsigned, jd->basicblockcount);
450 /* Link immediate dominators with successors */
452 for (bb = jd->basicblocks; bb; bb = bb->next) {
454 bb->idom->domsuccessors[numsuccessors[bb->idom->nr]] = bb;
455 numsuccessors[bb->idom->nr] += 1;
461 dumpmemory_release(ds);
464 bool dominator_tree_build(jitdata *jd) {
467 ds = dumpmemory_marker();
468 dominator_tree_build_intern(jd);
469 dumpmemory_release(ds);
471 dominator_tree_link_children(jd);
476 typedef struct dominance_frontier_item dominance_frontier_item;
478 struct dominance_frontier_item {
480 dominance_frontier_item *next;
483 typedef struct dominance_frontier_list dominance_frontier_list;
485 struct dominance_frontier_list {
486 dominance_frontier_item *first;
490 void dominance_frontier_list_add(dominance_frontier_list *list, basicblock *bb) {
491 dominance_frontier_item *item;
493 for (item = list->first; item; item = item->next) {
494 if (item->bb == bb) return;
497 item = DNEW(dominance_frontier_item);
499 item->next = list->first;
504 typedef struct dominance_frontier_info dominance_frontier_info;
506 struct dominance_frontier_info {
508 dominance_frontier_list *map;
511 dominance_frontier_info *dominance_frontier_init(jitdata *jd) {
512 dominance_frontier_info *dfi = DNEW(dominance_frontier_info);
516 dfi->map = DMNEW(dominance_frontier_list, jd->basicblockcount);
517 MZERO(dfi->map, dominance_frontier_list, jd->basicblockcount);
522 bool dominance_frontier_dominates(basicblock *d, basicblock *x) {
535 void dominance_frontier_for_block(dominance_frontier_info *dfi, basicblock *b) {
537 dominance_frontier_item *itdf;
538 dominance_frontier_list s = { NULL, 0 };
540 for (it = b->successors; it != b->successors + b->successorcount; ++it) {
541 if ((*it)->idom != b) {
542 dominance_frontier_list_add(&s, *it);
546 for (it = b->domsuccessors; it != b->domsuccessors + b->domsuccessorcount; ++it) {
547 dominance_frontier_for_block(dfi, *it);
548 for (itdf = dfi->map[(*it)->nr].first; itdf; itdf = itdf->next) {
549 if (! dominance_frontier_dominates(b, itdf->bb)) {
550 dominance_frontier_list_add(&s, itdf->bb);
558 void dominance_frontier_store(dominance_frontier_info *dfi) {
560 dominance_frontier_item *itdf;
563 for (bb = dfi->jd->basicblocks; bb; bb = bb->next) {
564 if (bb->nr < dfi->jd->basicblockcount) {
565 if (dfi->map[bb->nr].count > 0) {
566 bb->domfrontiercount = dfi->map[bb->nr].count;
567 itout = bb->domfrontier = DMNEW(basicblock *, bb->domfrontiercount);
568 for (itdf = dfi->map[bb->nr].first; itdf; itdf = itdf->next) {
577 bool dominance_frontier_build(jitdata *jd) {
578 int32_t ds = dumpmemory_marker();
580 dominance_frontier_info *dfi = dominance_frontier_init(jd);
581 dominance_frontier_for_block(dfi, jd->basicblocks);
582 dominance_frontier_store(dfi);
585 #include "vm/jit/show.h"
586 #include "vm/jit/python.h"
588 extern void graph_add_edge( graphdata *gd, int from, int to );
590 void dominator_tree_validate(jitdata *jd, dominatordata *_dd) {
591 int32_t ds = dumpmemory_marker();
594 basicblock *bptr, **it;
599 fprintf(stderr, "%s/%s: \n", jd->m->clazz->name->text, jd->m->name->text);
600 gd = graph_init(jd->basicblockcount);
602 for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
603 for (it = bptr->successors; it != bptr->successors + bptr->successorcount; ++it) {
604 graph_add_edge(gd, bptr->nr, (*it)->nr);
608 dd = compute_Dominators(gd, jd->basicblockcount);
610 for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
611 if (bptr->flags >= BBREACHED) {
612 if (bptr->idom == NULL) {
613 if (!(dd->idom[bptr->nr] == -1)) {
614 printf("-- %d %d\n", dd->idom[bptr->nr], bptr->nr);
618 assert(dd->idom[bptr->nr] == bptr->idom->nr);
623 computeDF(gd, dd, jd->basicblockcount, 0);
625 for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
626 if (bptr->flags >= BBREACHED) {
627 assert(bptr->domfrontiercount == dd->num_DF[bptr->nr]);
628 for (itnr = dd->DF[bptr->nr]; itnr != dd->DF[bptr->nr] + dd->num_DF[bptr->nr]; ++itnr) {
630 for (it = bptr->domfrontier; it != bptr->domfrontier + bptr->domfrontiercount; ++it) {
631 if ((*it)->nr == *itnr) {
640 dumpmemory_release(ds);
644 * These are local overrides for various environment variables in Emacs.
645 * Please do not remove this and leave it at the end of the file, where
646 * Emacs will automagically detect them.
647 * ---------------------------------------------------------------------
650 * indent-tabs-mode: t