19 #include "iredges_t.h"
24 #include "besched_t.h"
30 #define DBG_MODULE firm_dbg_register("firm.be.irgmod")
32 struct _dom_front_info_t {
36 static void compute_df_local(ir_node *bl, void *data)
38 pmap *df_map = ((dom_front_info_t *) data)->df_map;
39 ir_node *idom = get_Block_idom(bl);
40 pset *df = pmap_get(df_map, bl);
44 * Create a new dom frot set for this node,
48 pmap_insert(df_map, bl, pset_new_ptr(16));
50 for(i = 0, n = get_irn_arity(bl); i < n; ++i) {
52 /* The predecessor block */
53 ir_node *pred = get_nodes_block(get_irn_n(bl, i));
55 /* The dominance frontier set of the predecessor. */
56 pset *df = pmap_get(df_map, pred);
58 df = pset_new_ptr(16);
59 pmap_insert(df_map, pred, df);
62 assert(df && "dom front set must have been created for this node");
64 if(pred != idom && bl)
65 pset_insert_ptr(df, bl);
69 static void compute_df_up(ir_node *bl, void *data)
71 pmap *df_map = ((dom_front_info_t *) data)->df_map;
74 for(y = get_Block_dominated_first(bl); y; y = get_Block_dominated_next(y)) {
76 pset *df = pmap_get(df_map, y);
78 for(w = pset_first(df); w; w = pset_next(df))
79 if(!block_dominates(bl, w) || bl == w)
80 pset_insert_ptr(df, w);
84 dom_front_info_t *be_compute_dominance_frontiers(ir_graph *irg)
86 dom_front_info_t *info = malloc(sizeof(*info));
88 info->df_map = pmap_create();
91 * This must be called as a post walker, since the dom front sets
92 * of all predecessors must be created when a block is reached.
94 dom_tree_walk_irg(irg, NULL, compute_df_local, info);
95 dom_tree_walk_irg(irg, NULL, compute_df_up, info);
99 void be_free_dominance_frontiers(dom_front_info_t *info)
103 for(ent = pmap_first(info->df_map); ent; ent = pmap_next(info->df_map))
104 del_pset(ent->value);
106 pmap_destroy(info->df_map);
110 pset *be_get_dominance_frontier(dom_front_info_t *info, ir_node *block)
112 return pmap_get(info->df_map, block);
116 * Algorithm to place the Phi-Functions.
117 * @see Appel, Modern Compiler Implementation in Java, 2nd ed., p. 399ff
119 * This function takes an original node and a set of already placed
120 * copies of that node called @p copies. It places phi nodes at the
121 * iterated dominance frontiers of these copies and puts these phi nodes
122 * in the @p copies set, since they are another form of copies of the
125 * The rename phase (see below) is responsible for fixing up the usages
126 * of the original node.
128 * @param orig The original node.
129 * @param copies A set contianing nodes representing a copy of the
130 * original node. Each node must be inserted into the block's schedule.
131 * @param copy_blocks A set in which the blocks are recorded which
132 * contain a copy. This is just for efficiency in later phases (see
135 static void place_phi_functions(ir_node *orig, pset *copies,
136 pset *copy_blocks, dom_front_info_t *df_info)
139 ir_node *orig_block = get_nodes_block(orig);
140 ir_graph *irg = get_irn_irg(orig);
141 ir_mode *mode = get_irn_mode(orig);
142 pdeq *worklist = new_pdeq();
143 pset *phi_blocks = pset_new_ptr(8);
144 ir_node **ins = NULL;
146 firm_dbg_module_t *dbg = DBG_MODULE;
149 * Allocate an array for all blocks where the copies and the original
150 * value were defined.
152 int n_orig_blocks = pset_count(copy_blocks);
153 ir_node **orig_blocks = malloc(n_orig_blocks * sizeof(orig_blocks[0]));
156 * Fill the worklist queue and the rest of the orig blocks array.
158 for(it = pset_first(copies), i = 0; it; it = pset_next(copies)) {
159 ir_node *copy_block = get_nodes_block(it);
161 if(!block_dominates(orig_block, copy_block)) {
162 assert(block_dominates(orig_block, copy_block)
163 && "The block of the copy must be dominated by the block of the value");
166 pdeq_putr(worklist, copy_block);
167 orig_blocks[i++] = copy_block;
170 while(!pdeq_empty(worklist)) {
171 ir_node *bl = pdeq_getl(worklist);
173 pset *df = be_get_dominance_frontier(df_info, bl);
175 for(y = pset_first(df); y; y = pset_next(df)) {
176 int n_preds = get_irn_arity(y);
178 if(!pset_find_ptr(phi_blocks, y)) {
183 * Set the orig node as the only operand of the
186 ins = realloc(ins, n_preds * sizeof(ins[0]));
187 for(i = 0; i < n_preds; ++i)
190 /* Insert phi node */
191 phi = new_r_Phi(irg, y, n_preds, ins, mode);
192 DBG((dbg, LEVEL_2, " inserting phi %+F with %d args in block %+F\n",
196 * The phi node itself is also a copy of the original
197 * value. So put it in the copies set also, so that
198 * the rename phase can treat them right.
200 pset_insert_ptr(copies, phi);
201 pset_insert_ptr(copy_blocks, y);
204 * Insert the phi node into the schedule if it
205 * can occur there (PhiM's are not to put into a schedule.
207 if(to_appear_in_schedule(phi))
208 sched_add_before(sched_first(y), phi);
210 /* Insert the phi node in the phi blocks set. */
211 pset_insert_ptr(phi_blocks, y);
214 * If orig or a copy of it were not defined in y,
215 * add y to the worklist.
217 for(i = 0; i < n_orig_blocks; ++i)
218 if(orig_blocks[i] == y) {
224 pdeq_putr(worklist, y);
230 del_pset(phi_blocks);
240 * Find the copy of the given original node whose value is 'active'
243 * The usage is given as a node and a position. Initially, the given operand
244 * points to a node for which copies were introduced. We have to find
245 * the valid copy for this usage. This is done by travering the
246 * dominance tree upwards. If the usage is a phi function, we start
247 * traversing from the predecessor block which corresponds to the phi
250 * @param usage The node which uses the original node.
251 * @param pos The number of the argument which corresponds to the
253 * @param copy_blocks A set containing all basic block in which copies
254 * of the original node are located.
255 * @param copies A set containing all node which are copies from the
257 * @return The valid copy for usage.
259 static ir_node *search_def(ir_node *usage, int pos, pset *copies, pset *copy_blocks)
264 curr_bl = get_nodes_block(usage);
267 * If the usage is in a phi node, search the copy in the
268 * predecessor denoted by pos.
271 curr_bl = get_nodes_block(get_irn_n(curr_bl, pos));
272 start_irn = sched_last(curr_bl);
276 start_irn = sched_prev(usage);
280 * Traverse the dominance tree upwards from the
281 * predecessor block of the usage.
283 while(curr_bl != NULL) {
286 * If this block contains a copy, search the block
287 * instruction by instruction.
289 if(pset_find_ptr(copy_blocks, curr_bl)) {
292 /* Look at each instruction from last to first. */
293 for(irn = start_irn; !is_Block(irn); irn = sched_prev(irn)) {
295 /* Take the first copy we find. */
296 if(pset_find_ptr(copies, irn))
301 /* If were not done yet, look in the immediate dominator */
302 curr_bl = get_Block_idom(curr_bl);
304 start_irn = sched_last(curr_bl);
310 static void fix_usages(ir_node *orig, pset *copies, pset *copy_blocks)
314 const ir_edge_t *edge;
315 firm_dbg_module_t *dbg = DBG_MODULE;
322 /* Count the number of outs. */
323 foreach_out_edge(orig, edge)
327 * Put all outs into an array.
328 * This is neccessary, since the outs would be modified while
329 * interating on them what could bring the outs module in trouble.
331 DBG((dbg, LEVEL_2, " Users of %+F\n", orig));
332 outs = malloc(n_outs * sizeof(outs[0]));
333 foreach_out_edge(orig, edge) {
334 outs[i].irn = get_edge_src_irn(edge);
335 outs[i].pos = get_edge_src_pos(edge);
340 * Search the valid def for each out and set it.
342 for(i = 0; i < n_outs; ++i) {
344 ir_node *irn = outs[i].irn;
345 int pos = outs[i].pos;
347 def = search_def(irn, pos, copies, copy_blocks);
348 DBG((dbg, LEVEL_2, " %+F(%d) -> %+F\n", irn, pos, def));
351 set_irn_n(irn, pos, def);
357 void be_introduce_copies(dom_front_info_t *info, ir_node *orig, int n, ir_node *copy_nodes[])
359 pset *copies = pset_new_ptr(2 * n);
360 pset *copy_blocks = pset_new_ptr(2 * n);
361 int save_optimize = get_optimize();
362 int save_normalize = get_opt_normalize();
363 firm_dbg_module_t *dbg = DBG_MODULE;
366 firm_dbg_set_mask(dbg, -1);
367 DBG((dbg, LEVEL_1, "Introducing following copies of %+F\n", orig));
370 pset_insert_ptr(copies, orig);
371 pset_insert_ptr(copy_blocks, get_nodes_block(orig));
373 for(i = 0; i < n; ++i) {
375 " %+F in block %+F\n", copy_nodes[i], get_nodes_block(copy_nodes[i])));
376 pset_insert_ptr(copies, copy_nodes[i]);
377 pset_insert_ptr(copy_blocks, get_nodes_block(copy_nodes[i]));
381 * Disable optimization so that the phi functions do not
385 set_opt_normalize(0);
388 * Place the phi functions and reroute the usages.
390 place_phi_functions(orig, copies, copy_blocks, info);
391 fix_usages(orig, copies, copy_blocks);
393 /* reset the optimizations */
394 set_optimize(save_optimize);
395 set_opt_normalize(save_normalize);
398 del_pset(copy_blocks);