* Merged executionstate branch.
[cacao.git] / src / vm / jit / optimizing / dominators.c
1 /* src/vm/jit/optimizing/dominators.c - dominators and dominance frontier
2
3    Copyright (C) 2005, 2006, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
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.
12
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.
17
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
21    02111-1307, USA.
22
23 */
24
25
26 #include "mm/memory.h"
27
28 #include "toolbox/bitvector.h"
29
30 #include "vm/jit/jit.h"
31
32 #include "vm/jit/optimizing/graph.h"
33 #include "vm/jit/optimizing/dominators.h"
34
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,
41                          int basicblockcount);
42 #else
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);
46 #endif
47
48 /*************************************
49 Calculate Dominators
50 *************************************/
51 dominatordata *compute_Dominators(graphdata *gd, int basicblockcount) {
52         int i,j,n,N,p,s,s_,v,y;
53         graphiterator iter;
54         dominatordata *dd;
55
56         dd = DNEW(dominatordata);
57
58         dom_Dominators_init(dd, basicblockcount);
59         
60         N=0;
61
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
66                         ,basicblockcount
67 #endif
68                         );
69
70         for(i = N-1; i > 0; i--) {
71                 _DOM_CHECK_BOUNDS(i, 0, basicblockcount);
72                 n = dd->vertex[i];
73                 _DOM_CHECK_BOUNDS(n, 0, basicblockcount);
74                 p = dd->parent[n];
75                 s = p;
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])
80                                 s_ = j;
81                         else
82                                 s_ = dd->semi[dom_AncestorWithLowestSemi(dd, j
83 #ifdef DOM_DEBUG_CHECK
84                                                                                                                  ,basicblockcount
85 #endif
86                                                                                                                  )];
87                 _DOM_CHECK_BOUNDS(s_, 0, basicblockcount);
88                 _DOM_CHECK_BOUNDS(s, 0, basicblockcount);
89                         if (dd->dfnum[s_] < dd->dfnum[s])
90                                 s = s_;
91                 }
92                 dd->semi[n] = s;
93                 _DOM_CHECK_BOUNDS(dd->num_bucket[s], 0, basicblockcount);
94                 dd->bucket[s][dd->num_bucket[s]] = n;
95                 dd->num_bucket[s]++;
96                 dom_Link(dd, p, n
97 #ifdef DOM_DEBUG_CHECK
98                                  , basicblockcount
99 #endif
100                                  );
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
107                                                                                    , basicblockcount
108 #endif
109                                                                                    );
110                 _DOM_CHECK_BOUNDS(y, 0, basicblockcount);
111                 _DOM_CHECK_BOUNDS(v, 0, basicblockcount);
112             if (dd->semi[y] == dd->semi[v])
113                                 dd->idom[v] = p;
114                         else
115                                 dd->samedom[v] = y;
116                 }
117                 dd->num_bucket[p] = 0;
118         }
119         for(i = 1; i < N; i++) {
120                 n = dd->vertex[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]];
125                 }
126         }
127         return dd;
128 }
129
130 /********************************************
131 compute Dominace Frontier
132 ********************************************/
133 void computeDF(graphdata *gd, dominatordata *dd, int basicblockcount, int n) {
134         int c,i,j;
135         bool *_S;
136         graphiterator iter;
137
138         _S = DMNEW(bool, basicblockcount);
139         for(i = 0; i < basicblockcount; i++)
140                 _S[i] = false;
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)
145                         _S[i] = true;
146         }
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;
155                         }
156                 }
157         }
158         for(i = 0; i < basicblockcount; i++)
159                 if (_S[i]) {
160                 _DOM_CHECK_BOUNDS(dd->num_DF[n], 0, basicblockcount);
161                         dd->DF[n][dd->num_DF[n]] = i;
162                         dd->num_DF[n]++;
163                 }
164 }
165
166
167 void dom_Dominators_init(dominatordata *dd, int basicblockcount) {
168         int i;
169
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++) {
183                 dd->dfnum[i] = -1;
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);
187                 dd->num_DF[i] = 0;
188                 dd->DF[i] = DMNEW(int, basicblockcount);
189         }
190 }
191
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) {
198 #else
199 void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N) {
200 #endif
201     int i;
202         graphiterator iter;
203
204         _DOM_CHECK_BOUNDS(n,0,basicblockcount);
205         if (dd->dfnum[n] == -1) { /* not visited till now? */
206                 dd->dfnum[n] = *N;
207                 _DOM_CHECK_BOUNDS(*N,0,basicblockcount);
208                 dd->vertex[*N] = n;
209                 dd->parent[n] = p;
210                 (*N)++;
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
215                                         , basicblockcount
216 #endif
217                                         );
218                 }
219         }
220 }
221
222 #ifdef DOM_DEBUG_CHECK
223 int dom_AncestorWithLowestSemi(dominatordata *dd, int v, int basicblockcount) {
224 #else
225 int dom_AncestorWithLowestSemi(dominatordata *dd, int v) {
226 #endif
227         int a,b;
228
229         _DOM_CHECK_BOUNDS(v, 0, basicblockcount);
230         a = dd->ancestor[v];
231         _DOM_CHECK_BOUNDS(a,0,basicblockcount);
232         if (dd->ancestor[a] != -1) {
233                 b = dom_AncestorWithLowestSemi(dd, a
234 #ifdef DOM_DEBUG_CHECK
235                                                                            , basicblockcount
236 #endif
237                                                                            );
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]]])
243                         dd->best[v] = b;
244         }
245         return dd->best[v];
246 }
247
248 #ifdef DOM_DEBUG_CHECK
249 void dom_Link(dominatordata *dd, int p, int n, int basicblockcount) {
250 #else
251 void dom_Link(dominatordata *dd, int p, int n) {
252 #endif
253         _DOM_CHECK_BOUNDS(n,0,basicblockcount);
254         dd->ancestor[n] = p;
255         dd->best[n] = n;
256 }
257
258 /*********************************************************/
259
260 typedef struct basicblock_info basicblock_info;
261
262 struct basicblock_info {
263         basicblock *bb;
264         int dfnum;
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;
273 };
274
275 typedef struct dominator_tree_info dominator_tree_info;
276
277 struct dominator_tree_info {
278         jitdata *jd;
279         basicblock_info *basicblocks;
280         basicblock_info **df_map;
281         unsigned df_counter;
282 };
283
284 static dominator_tree_info *dominator_tree_init(jitdata *jd) {
285         dominator_tree_info *di;
286         basicblock *itb;
287         basicblock_info *iti;
288
289         di = DNEW(dominator_tree_info);
290
291         di->jd = jd;
292
293         di->basicblocks = DMNEW(basicblock_info, jd->basicblockcount);
294         MZERO(di->basicblocks, basicblock_info, jd->basicblockcount);
295         
296         for (iti = di->basicblocks; iti != di->basicblocks + jd->basicblockcount; ++iti) {
297                 iti->dfnum = -1;
298                 iti->bucket = DMNEW(basicblock_info *, jd->basicblockcount);
299                 iti->bucketcount = 0;
300         }
301
302         for (itb = jd->basicblocks; itb; itb = itb->next) {
303                 di->basicblocks[itb->nr].bb = itb;
304         }
305
306         di->df_map = DMNEW(basicblock_info *, jd->basicblockcount);
307         MZERO(di->df_map, basicblock_info *, jd->basicblockcount);
308
309         di->df_counter = 0;
310
311         return di;
312 }
313
314 inline basicblock_info *dominator_tree_get_basicblock(dominator_tree_info *di, basicblock *bb) {
315         return di->basicblocks + bb->nr;
316 }
317
318 static void dominator_tree_depth_first_search(
319         dominator_tree_info *di, basicblock_info *parent, basicblock_info *node
320 ) {
321         basicblock **it;
322
323         if (node->dfnum == -1) {
324
325                 node->dfnum = di->df_counter;
326                 node->parent = parent;
327                 di->df_map[di->df_counter] = node;
328                 di->df_counter += 1;
329
330                 for (it = node->bb->successors; it != node->bb->successors + node->bb->successorcount; ++it) {
331                         dominator_tree_depth_first_search(
332                                 di, node, 
333                                 dominator_tree_get_basicblock(di, *it)
334                         );
335                 }
336         }
337 }
338
339 void dominator_tree_link(dominator_tree_info *di, basicblock_info *parent, basicblock_info *node) {
340         node->ancestor = parent;
341         node->best = node;
342 }
343
344 basicblock_info *dominator_tree_ancestor_with_lowest_semi(
345         dominator_tree_info *di, basicblock_info *node
346 ) {
347         basicblock_info *a, *b;
348
349         a = node->ancestor;
350
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) {
355                         node->best = b;
356                 }
357         }
358
359         return node->best;
360 }
361
362 void dominator_tree_build_intern(jitdata *jd) {
363         
364         dominator_tree_info *di;
365         basicblock_info *node;
366         basicblock_info *semicand;
367         basicblock_info *pred;
368         basicblock **itb;
369         basicblock_info **itii;
370         basicblock_info *v, *y;
371         int i;
372
373         di = dominator_tree_init(jd);
374
375         dominator_tree_depth_first_search(di, NULL, dominator_tree_get_basicblock(di, jd->basicblocks));
376
377         for (i = di->df_counter - 1; i >= 1; --i) {
378                 node = di->df_map[i];
379
380                 node->semi = node->parent;
381
382                 for (
383                         itb = node->bb->predecessors; 
384                         itb != node->bb->predecessors + node->bb->predecessorcount; 
385                         ++itb
386                 ) {
387
388                         pred = dominator_tree_get_basicblock(di, *itb);
389
390                         if (pred->dfnum <= node->dfnum) {
391                                 semicand = pred;
392                         } else {
393                                 semicand = dominator_tree_ancestor_with_lowest_semi(di, pred)->semi;
394                         }
395
396                         if (semicand->dfnum < node->semi->dfnum) {
397                                 node->semi = semicand;
398                         }
399                 }
400
401                 node->semi->bucket[node->semi->bucketcount] = node;
402                 node->semi->bucketcount += 1;
403
404                 dominator_tree_link(di, node->parent, node);
405
406                 for (itii = node->parent->bucket; itii != node->parent->bucket + node->parent->bucketcount; ++itii) {
407                         v = *itii;
408                         y = dominator_tree_ancestor_with_lowest_semi(di, v);
409                         if (y->semi == v->semi) {
410                                 v->idom = node->parent;
411                         } else {
412                                 v->samedom = y;
413                         }
414                 }
415
416                 node->parent->bucketcount = 0;
417         }
418
419         for (i = 1; i < di->df_counter; ++i) {
420                 node = di->df_map[i];
421                 if (node->samedom) {
422                         node->idom = node->samedom->idom;
423                 }
424
425                 node->bb->idom = node->idom->bb;
426                 node->idom->bb->domsuccessorcount += 1;
427         }
428 }
429
430 void dominator_tree_link_children(jitdata *jd) {
431         basicblock *bb;
432         int32_t ds;
433         /* basicblock number => current number of successors */
434         unsigned *numsuccessors;
435
436         /* Allocate memory for successors */
437
438         for (bb = jd->basicblocks; bb; bb = bb->next) {
439                 if (bb->domsuccessorcount > 0) {
440                         bb->domsuccessors = DMNEW(basicblock *, bb->domsuccessorcount);
441                 }
442         }
443
444         /* Allocate memory for per basic block counter of successors */
445
446         ds = dumpmemory_marker();
447         numsuccessors = DMNEW(unsigned, jd->basicblockcount);
448         MZERO(numsuccessors, unsigned, jd->basicblockcount);
449
450         /* Link immediate dominators with successors */
451
452         for (bb = jd->basicblocks; bb; bb = bb->next) {
453                 if (bb->idom) {
454                         bb->idom->domsuccessors[numsuccessors[bb->idom->nr]] = bb;
455                         numsuccessors[bb->idom->nr] += 1;
456                 }
457         }
458
459         /* Free memory */
460
461         dumpmemory_release(ds);
462 }
463
464 bool dominator_tree_build(jitdata *jd) {
465         int32_t ds;
466         
467         ds = dumpmemory_marker();
468         dominator_tree_build_intern(jd);
469         dumpmemory_release(ds);
470
471         dominator_tree_link_children(jd);
472
473         return true;
474 }
475
476 typedef struct dominance_frontier_item dominance_frontier_item;
477
478 struct dominance_frontier_item {
479         basicblock *bb;
480         dominance_frontier_item *next;
481 };
482
483 typedef struct dominance_frontier_list dominance_frontier_list;
484
485 struct dominance_frontier_list {
486         dominance_frontier_item *first;
487         unsigned count;
488 };
489
490 void dominance_frontier_list_add(dominance_frontier_list *list, basicblock *bb) {
491         dominance_frontier_item *item;
492         
493         for (item = list->first; item; item = item->next) {
494                 if (item->bb == bb) return;
495         }
496
497         item = DNEW(dominance_frontier_item);
498         item->bb = bb;
499         item->next = list->first;
500         list->first = item;
501         list->count += 1;
502 }
503
504 typedef struct dominance_frontier_info dominance_frontier_info;
505
506 struct dominance_frontier_info {
507         jitdata *jd;
508         dominance_frontier_list *map;
509 };
510
511 dominance_frontier_info *dominance_frontier_init(jitdata *jd) {
512         dominance_frontier_info *dfi = DNEW(dominance_frontier_info);
513
514         dfi->jd = jd;
515
516         dfi->map = DMNEW(dominance_frontier_list, jd->basicblockcount);
517         MZERO(dfi->map, dominance_frontier_list, jd->basicblockcount);
518
519         return dfi;
520 }
521
522 bool dominance_frontier_dominates(basicblock *d, basicblock *x) {
523         x = x->idom;
524
525         while (x != NULL) {
526                 if (x == d) {
527                         return true;
528                 }
529                 x = x->idom;
530         }
531
532         return false;
533 }
534
535 void dominance_frontier_for_block(dominance_frontier_info *dfi, basicblock *b) {
536         basicblock **it;
537         dominance_frontier_item *itdf;
538         dominance_frontier_list s = { NULL, 0 };
539
540         for (it = b->successors; it != b->successors + b->successorcount; ++it) {
541                 if ((*it)->idom != b) {
542                         dominance_frontier_list_add(&s, *it);
543                 }
544         }
545
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);
551                         }
552                 }
553         }
554
555         dfi->map[b->nr] = s;
556 }
557
558 void dominance_frontier_store(dominance_frontier_info *dfi) {
559         basicblock *bb;
560         dominance_frontier_item *itdf;
561         basicblock **itout;
562
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) {
569                                         *itout = itdf->bb;
570                                         itout += 1;
571                                 }
572                         }
573                 }
574         }
575 }
576
577 bool dominance_frontier_build(jitdata *jd) {
578         int32_t ds = dumpmemory_marker();
579
580         dominance_frontier_info *dfi = dominance_frontier_init(jd);
581         dominance_frontier_for_block(dfi, jd->basicblocks);
582         dominance_frontier_store(dfi);
583 }
584
585 #include "vm/jit/show.h"
586 #include "vm/jit/python.h"
587
588 extern void graph_add_edge( graphdata *gd, int from, int to );
589
590 void dominator_tree_validate(jitdata *jd, dominatordata *_dd) {
591         int32_t ds = dumpmemory_marker();
592         graphdata *gd;
593         int i, j;
594         basicblock *bptr, **it;
595         dominatordata *dd;
596         int *itnr;
597         bool found;
598
599         fprintf(stderr, "%s/%s: \n", jd->m->clazz->name->text, jd->m->name->text);
600         gd = graph_init(jd->basicblockcount);
601
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);
605                 }
606         }
607
608         dd = compute_Dominators(gd, jd->basicblockcount);
609
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);
615                                         assert(0);
616                                 }
617                         } else {
618                                 assert(dd->idom[bptr->nr] == bptr->idom->nr);
619                         }
620                 }
621         }
622
623         computeDF(gd, dd, jd->basicblockcount, 0);
624
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) {
629                                 found = false;
630                                 for (it = bptr->domfrontier; it != bptr->domfrontier + bptr->domfrontiercount; ++it) {
631                                         if ((*it)->nr == *itnr) {
632                                                 found =true; break;
633                                         }
634                                 }
635                                 assert(found);
636                         }
637                 }
638         }
639
640         dumpmemory_release(ds);
641 }
642
643 /*
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  * ---------------------------------------------------------------------
648  * Local variables:
649  * mode: c
650  * indent-tabs-mode: t
651  * c-basic-offset: 4
652  * tab-width: 4
653  * End:
654  */