18 #include "iredges_t.h"
22 #include "besched_t.h"
28 struct _dom_front_info_t {
32 static void compute_df_local(ir_node *bl, void *data)
34 pmap *df_map = ((dom_front_info_t *) data)->df_map;
35 ir_node *idom = get_Block_idom(bl);
38 for(i = 0, n = get_irn_arity(bl); i < n; ++i) {
40 /* The predecessor block */
41 ir_node *pred = get_nodes_block(get_irn_n(bl, i));
43 /* The dominance frontier set of the predecessor. */
44 pset *df = pmap_get(df_map, pred);
47 * Create the dominance frontier set of the predecessor
51 df = pset_new_ptr(16);
52 pmap_insert(df_map, pred, df);
56 if(pred != idom && bl)
57 pset_insert_ptr(df, bl);
61 static void compute_df_up(ir_node *bl, void *data)
63 pmap *df_map = ((dom_front_info_t *) data)->df_map;
66 for(y = get_Block_dominated_first(bl); y; y = get_Block_dominated_next(y)) {
68 pset *df = pmap_get(df_map, y);
70 for(w = pset_first(df); df; w = pset_next(df))
71 if(!block_dominates(bl, w) || bl == w)
72 pset_insert_ptr(df, w);
76 dom_front_info_t *be_compute_dominance_frontiers(ir_graph *irg)
78 dom_front_info_t *info = malloc(sizeof(*info));
80 info->df_map = pmap_create();
82 /* Perhaps both can we interwined */
83 dom_tree_walk_irg(irg, compute_df_local, NULL, info);
84 dom_tree_walk_irg(irg, NULL, compute_df_up, info);
88 void be_free_dominance_frontiers(dom_front_info_t *info)
92 for(ent = pmap_first(info->df_map); ent; ent = pmap_next(info->df_map))
95 pmap_destroy(info->df_map);
99 pset *be_get_dominance_frontier(dom_front_info_t *info, ir_node *block)
101 return pmap_get(info->df_map, block);
105 * Algorithm to place the Phi-Functions.
106 * @see Appel, Modern Compiler Implementation in Java, 2nd ed., p. 399ff
108 * This function takes an original node and a set of already placed
109 * copies of that node called @p copies. It places phi nodes at the
110 * iterated dominance frontiers of these copies and puts these phi nodes
111 * in the @p copies set, since they are another form of copies of the
114 * The rename phase (see below) is responsible for fixing up the usages
115 * of the original node.
117 * @param orig The original node.
118 * @param copies A set contianing nodes representing a copy of the
119 * original node. Each node must be inserted into the block's schedule.
120 * @param copy_blocks A set in which the blocks are recorded which
121 * contain a copy. This is just for efficiency in later phases (see
124 static void place_phi_functions(ir_node *orig, pset *copies,
125 pset *copy_blocks, dom_front_info_t *df_info)
128 ir_node *orig_block = get_nodes_block(orig);
129 ir_graph *irg = get_irn_irg(orig);
130 ir_mode *mode = get_irn_mode(orig);
131 pdeq *worklist = new_pdeq();
132 pset *phi_blocks = pset_new_ptr(8);
133 ir_node **ins = NULL;
137 * Allocate an array for all blocks where the copies and the original
138 * value were defined.
140 int n_orig_blocks = pset_count(copy_blocks) + 1;
141 ir_node **orig_blocks = malloc(n_orig_blocks * sizeof(orig_blocks[0]));
144 * Fill the array of definition blocks.
146 orig_blocks[0] = get_nodes_block(orig);
149 * Fill the worklist queue and the rest of the orig blocks array.
151 for(it = pset_first(copies), i = 1; it; it = pset_next(copies)) {
152 ir_node *copy_block = get_nodes_block(it);
154 assert(block_dominates(orig_block, copy_block)
155 && "The block of the copy must be dominated by the block of the value");
157 pdeq_putr(worklist, it);
158 orig_blocks[i++] = copy_block;
161 while(!pdeq_empty(worklist)) {
162 ir_node *irn = pdeq_getl(worklist);
163 ir_node *bl = get_nodes_block(irn);
165 int n_preds = get_irn_arity(bl);
166 pset *df = be_get_dominance_frontier(df_info, bl);
168 for(y = pset_first(df); y; y = pset_next(df)) {
170 if(!pset_find_ptr(phi_blocks, y)) {
175 * Set the orig node as the only operand of the
178 ins = realloc(ins, n_preds * sizeof(ins[0]));
179 for(i = 0; i < n_preds; ++i)
182 /* Insert phi node */
183 phi = new_r_Phi(irg, bl, n_preds, ins, mode);
186 * The phi node itself is also a copy of the original
187 * value. So put it in the copies set also, so that
188 * the rename phase can treat them right.
190 pset_insert_ptr(copies, phi);
191 pset_insert_ptr(copy_blocks, y);
193 /* Insert the phi node into the schedule */
194 sched_add_before(sched_first(y), phi);
196 /* Insert the phi node in the phi blocks set. */
197 pset_insert_ptr(phi_blocks, y);
200 * If orig or a copy of it were not defined in y,
201 * add y to the worklist.
203 for(i = 0; i < n_orig_blocks; ++i)
204 if(orig_blocks[i] == y) {
210 pdeq_putr(worklist, y);
216 del_pset(phi_blocks);
226 * Find the copy of the given original node whose value is 'active'
229 * The usage is given as a node and a position. Initially, the given operand
230 * points to a node for which copies were introduced. We have to find
231 * the valid copy for this usage. This is done by travering the
232 * dominance tree upwards. If the usage is a phi function, we start
233 * traversing from the predecessor block which corresponds to the phi
236 * @param usage The node which uses the original node.
237 * @param pos The number of the argument which corresponds to the
239 * @param copy_blocks A set containing all basic block in which copies
240 * of the original node are located.
241 * @param copies A set containing all node which are copies from the
243 * @return The valid copy for usage.
245 static ir_node *search_def(ir_node *usage, int pos, pset *copies, pset *copy_blocks)
249 curr_bl = get_nodes_block(usage);
252 * If the usage is in a phi node, search the copy in the
253 * predecessor denoted by pos.
256 curr_bl = get_nodes_block(get_irn_n(curr_bl, pos));
259 * Traverse the dominance tree upwards from the
260 * predecessor block of the usage.
262 while(curr_bl != NULL) {
265 * If this block contains a copy, search the block
266 * instruction by instruction.
268 if(pset_find_ptr(copy_blocks, curr_bl)) {
271 /* Look at each instruction from last to first. */
272 sched_foreach_reverse(curr_bl, irn) {
274 /* Take the first copy we find. */
275 if(pset_find_ptr(copies, irn))
279 assert(0 && "We must have encountered a copy");
282 /* If were not done yet, look in the immediate dominator */
283 curr_bl = get_Block_idom(curr_bl);
289 static void fix_usages(ir_node *orig, pset *copies, pset *copy_blocks)
293 const ir_edge_t *edge;
294 const ir_edge_t **outs;
296 /* Count the number of outs. */
297 foreach_out_edge(orig, edge)
301 * Put all outs into an array.
302 * This is neccessary, since the outs would be modified while
303 * interating on them what could bring the outs module in trouble.
305 outs = malloc(n_outs * sizeof(outs[0]));
306 foreach_out_edge(orig, edge)
310 * Search the valid def for each out and set it.
312 for(i = 0; i < n_outs; ++i) {
314 ir_node *irn = get_edge_src_irn(outs[i]);
315 int pos = get_edge_src_pos(outs[i]);
317 def = search_def(irn, pos, copies, copy_blocks);
318 set_irn_n(irn, pos, def);
324 void be_introduce_copies(dom_front_info_t *info, ir_node *orig, int n, ir_node *copy_nodes[])
326 pset *copies = pset_new_ptr(2 * n);
327 pset *copy_blocks = pset_new_ptr(2 * n);
328 int save_optimize = get_optimize();
332 for(i = 0; i < n; ++i) {
333 pset_insert_ptr(copies, copy_nodes[i]);
334 pset_insert_ptr(copy_blocks, get_nodes_block(copy_nodes[i]));
338 * Disable optimization so that the phi functions do not
344 * Place the phi functions and reroute the usages.
346 place_phi_functions(orig, copies, copy_blocks, info);
347 fix_usages(orig, copies, copy_blocks);
349 /* reset the optimizations */
350 set_optimize(save_optimize);
353 del_pset(copy_blocks);