1 // SPDX-License-Identifier: MIT
3 // Various utilities for flowgraphs.
5 // Copyright (c) 2017 Luc Van Oostenryck.
10 #include "flow.h" // for bb_generation
17 struct basic_block_list
*list
;
23 static void label_postorder(struct basic_block
*bb
, struct cfg_info
*info
)
25 struct basic_block
*child
;
27 if (bb
->generation
== info
->gen
)
30 bb
->generation
= info
->gen
;
31 FOR_EACH_PTR_REVERSE(bb
->children
, child
) {
32 label_postorder(child
, info
);
33 } END_FOR_EACH_PTR_REVERSE(child
);
35 bb
->postorder_nr
= info
->nr
++;
36 add_bb(&info
->list
, bb
);
39 static void reverse_bbs(struct basic_block_list
**dst
, struct basic_block_list
*src
)
41 struct basic_block
*bb
;
42 FOR_EACH_PTR_REVERSE(src
, bb
) {
44 } END_FOR_EACH_PTR_REVERSE(bb
);
47 static void debug_postorder(struct entrypoint
*ep
)
49 struct basic_block
*bb
;
51 printf("%s's reverse postorder:\n", show_ident(ep
->name
->ident
));
52 FOR_EACH_PTR(ep
->bbs
, bb
) {
53 printf("\t.L%u: %u\n", bb
->nr
, bb
->postorder_nr
);
54 } END_FOR_EACH_PTR(bb
);
58 // cfg_postorder - Set the BB's reverse postorder links
60 // Do a postorder DFS walk and set the links
61 // (which will do the reverse part).
63 int cfg_postorder(struct entrypoint
*ep
)
65 struct cfg_info info
= {
66 .gen
= ++bb_generation
,
69 label_postorder(ep
->entry
->bb
, &info
);
71 // OK, now info.list contains the node in postorder
72 // Reuse ep->bbs for the reverse postorder.
73 free_ptr_list(&ep
->bbs
);
75 reverse_bbs(&ep
->bbs
, info
.list
);
76 free_ptr_list(&info
.list
);
83 // Calculate the dominance tree following:
84 // "A simple, fast dominance algorithm"
85 // by K. D. Cooper, T. J. Harvey, and K. Kennedy.
86 // cfr. http://www.cs.rice.edu/∼keith/EMBED/dom.pdf
88 static struct basic_block
*intersect_dom(struct basic_block
*doms
[],
89 struct basic_block
*b1
, struct basic_block
*b2
)
91 int f1
= b1
->postorder_nr
, f2
= b2
->postorder_nr
;
95 f1
= b1
->postorder_nr
;
99 f2
= b2
->postorder_nr
;
105 static void debug_domtree(struct entrypoint
*ep
)
107 struct basic_block
*bb
= ep
->entry
->bb
;
109 printf("%s's idoms:\n", show_ident(ep
->name
->ident
));
110 FOR_EACH_PTR(ep
->bbs
, bb
) {
111 if (bb
== ep
->entry
->bb
)
112 continue; // entry node has no idom
113 printf("\t%s <- %s\n", show_label(bb
), show_label(bb
->idom
));
114 } END_FOR_EACH_PTR(bb
);
117 void domtree_build(struct entrypoint
*ep
)
119 struct basic_block
*entry
= ep
->entry
->bb
;
120 struct basic_block
**doms
;
121 struct basic_block
*bb
;
126 // First calculate the (reverse) postorder.
127 // This will give use us:
128 // - the links to do a reverse postorder traversal
129 // - the order number for each block
130 size
= cfg_postorder(ep
);
132 // initialize the dominators array
133 doms
= calloc(size
, sizeof(*doms
));
134 assert(entry
->postorder_nr
== size
-1);
135 doms
[size
-1] = entry
;
138 struct basic_block
*b
;
141 FOR_EACH_PTR(ep
->bbs
, b
) {
142 struct basic_block
*p
;
143 int bnr
= b
->postorder_nr
;
144 struct basic_block
*new_idom
= NULL
;
147 continue; // ignore entry node
149 FOR_EACH_PTR(b
->parents
, p
) {
150 unsigned int pnr
= p
->postorder_nr
;
158 new_idom
= intersect_dom(doms
, p
, new_idom
);
159 } END_FOR_EACH_PTR(p
);
162 if (doms
[bnr
] != new_idom
) {
163 doms
[bnr
] = new_idom
;
166 } END_FOR_EACH_PTR(b
);
169 FOR_EACH_PTR(ep
->bbs
, bb
) {
170 free_ptr_list(&bb
->doms
);
171 } END_FOR_EACH_PTR(bb
);
173 // set the idom links
174 FOR_EACH_PTR(ep
->bbs
, bb
) {
175 struct basic_block
*idom
= doms
[bb
->postorder_nr
];
178 continue; // ignore entry node
181 add_bb(&idom
->doms
, bb
);
182 } END_FOR_EACH_PTR(bb
);
185 // set the dominance levels
186 FOR_EACH_PTR(ep
->bbs
, bb
) {
187 struct basic_block
*idom
= bb
->idom
;
188 int level
= idom
? idom
->dom_level
+ 1 : 0;
190 bb
->dom_level
= level
;
191 if (max_level
< level
)
193 } END_FOR_EACH_PTR(bb
);
194 ep
->dom_levels
= max_level
+ 1;
201 // dt_dominates - does BB a dominates BB b?
202 bool domtree_dominates(struct basic_block
*a
, struct basic_block
*b
)
204 if (a
== b
) // dominance is reflexive
211 // can't dominate if deeper in the DT
212 if (a
->dom_level
>= b
->dom_level
)
215 // FIXME: can be faster if we have the DFS in-out numbers
217 // walk up the dominator tree
218 for (b
= b
->idom
; b
; b
= b
->idom
) {