26 #include "iredges_t.h"
31 #include "besched_t.h"
38 #define DBG_MODULE firm_dbg_register("firm.be.irgmod")
39 #define DBG_LEVEL SET_LEVEL_0
41 struct _dom_front_info_t {
46 * A wrapper for get_Block_idom.
47 * This function returns the block itself, if the block is the start
48 * block. Returning NULL would make any != comparison true which
49 * suggests, that the start block is dominated by some other node.
50 * @param bl The block.
51 * @return The immediate dominator of the block.
53 static INLINE ir_node *get_idom(ir_node *bl)
55 ir_node *idom = get_Block_idom(bl);
56 return idom == NULL ? bl : idom;
59 static void compute_df(ir_node *n, pmap *df_map)
62 const ir_edge_t *edge;
63 pset *df = pset_new_ptr_default();
65 /* Add local dominance frontiers */
66 foreach_block_succ(n, edge) {
67 ir_node *y = edge->src;
70 pset_insert_ptr(df, y);
74 * Go recursively down the dominance tree and add all blocks
75 * int the dominance frontiers of the children, which are not
76 * dominated by the given block.
78 for(c = get_Block_dominated_first(n); c; c = get_Block_dominated_next(c)) {
82 compute_df(c, df_map);
83 df_c = pmap_get(df_map, c);
85 for(w = pset_first(df_c); w; w = pset_next(df_c)) {
87 pset_insert_ptr(df, w);
91 pmap_insert(df_map, n, df);
95 dom_front_info_t *be_compute_dominance_frontiers(ir_graph *irg)
97 dom_front_info_t *info = malloc(sizeof(*info));
100 info->df_map = pmap_create();
101 compute_df(get_irg_start_block(irg), info->df_map);
106 void be_free_dominance_frontiers(dom_front_info_t *info)
110 for(ent = pmap_first(info->df_map); ent; ent = pmap_next(info->df_map))
111 del_pset(ent->value);
113 pmap_destroy(info->df_map);
117 pset *be_get_dominance_frontier(dom_front_info_t *info, ir_node *block)
119 return pmap_get(info->df_map, block);
122 static void determine_phi_blocks(ir_node *orig, pset *copies,
123 pset *copy_blocks, pset *phi_blocks, dom_front_info_t *df_info)
126 ir_node *orig_block = get_nodes_block(orig);
127 pdeq *worklist = new_pdeq();
128 firm_dbg_module_t *dbg = DBG_MODULE;
131 * Fill the worklist queue and the rest of the orig blocks array.
133 for(bl = pset_first(copy_blocks); bl; bl = pset_next(copy_blocks)) {
134 assert(block_dominates(orig_block, bl)
135 && "The block of the copy must be dominated by the block of the value");
137 pdeq_putr(worklist, bl);
140 while(!pdeq_empty(worklist)) {
141 ir_node *bl = pdeq_getl(worklist);
143 pset *df = be_get_dominance_frontier(df_info, bl);
145 DBG((dbg, LEVEL_3, "dom front of %+F\n", bl));
146 for(y = pset_first(df); y; y = pset_next(df))
147 DBG((dbg, LEVEL_3, "\t%+F\n", y));
149 for(y = pset_first(df); y; y = pset_next(df)) {
150 if(!pset_find_ptr(phi_blocks, y)) {
151 pset_insert_ptr(phi_blocks, y);
154 * Clear the link field of a possible phi block, since
155 * the possibly created phi will be stored there. See,
158 set_irn_link(y, NULL);
160 if(!pset_find_ptr(copy_blocks, y))
161 pdeq_putr(worklist, y);
171 * Find the copy of the given original node whose value is 'active'
174 * The usage is given as a node and a position. Initially, the given operand
175 * points to a node for which copies were introduced. We have to find
176 * the valid copy for this usage. This is done by travering the
177 * dominance tree upwards. If the usage is a phi function, we start
178 * traversing from the predecessor block which corresponds to the phi
181 * @param usage The node which uses the original node.
182 * @param pos The number of the argument which corresponds to the
184 * @param copy_blocks A set containing all basic block in which copies
185 * of the original node are located.
186 * @param copies A set containing all node which are copies from the
188 * @return The valid copy for usage.
190 static ir_node *search_def(ir_node *usage, int pos, pset *copies,
191 pset *copy_blocks, pset *phi_blocks, ir_mode *mode)
195 firm_dbg_module_t *dbg = DBG_MODULE;
197 curr_bl = get_nodes_block(usage);
200 DBG((dbg, LEVEL_1, "Searching valid def for use %+F at pos %d\n", usage, pos));
202 * If the usage is in a phi node, search the copy in the
203 * predecessor denoted by pos.
206 curr_bl = get_Block_cfgpred_block(curr_bl, pos);
207 start_irn = sched_last(curr_bl);
209 start_irn = sched_prev(usage);
213 * Traverse the dominance tree upwards from the
214 * predecessor block of the usage.
216 while(curr_bl != NULL) {
219 * If this block contains a copy, search the block
220 * instruction by instruction.
222 if(pset_find_ptr(copy_blocks, curr_bl)) {
225 /* Look at each instruction from last to first. */
226 sched_foreach_reverse_from(start_irn, irn) {
228 /* Take the first copy we find. */
229 if(pset_find_ptr(copies, irn))
234 if(pset_find_ptr(phi_blocks, curr_bl)) {
235 ir_node *phi = get_irn_link(curr_bl);
238 int i, n_preds = get_irn_arity(curr_bl);
239 ir_graph *irg = get_irn_irg(curr_bl);
240 ir_node **ins = malloc(n_preds * sizeof(ins[0]));
242 for(i = 0; i < n_preds; ++i)
243 ins[i] = new_r_Unknown(irg, mode);
245 phi = new_r_Phi(irg, curr_bl, n_preds, ins, mode);
246 DBG((dbg, LEVEL_2, "\tcreating phi %+F in %+F\n", phi, curr_bl));
248 set_irn_link(curr_bl, phi);
249 sched_add_after(curr_bl, phi);
252 for(i = 0; i < n_preds; ++i) {
253 ir_node *arg = search_def(phi, i, copies, copy_blocks, phi_blocks, mode);
254 DBG((dbg, LEVEL_2, "\t\t%+F(%d) -> %+F\n", phi, i, arg));
255 set_irn_n(phi, i, arg);
262 /* If were not done yet, look in the immediate dominator */
263 curr_bl = get_Block_idom(curr_bl);
265 start_irn = sched_last(curr_bl);
271 static void fix_usages(ir_node *orig, pset *copies, pset *copy_blocks,
272 pset *phi_blocks, pset *ignore_uses)
276 const ir_edge_t *edge;
277 ir_mode *mode = get_irn_mode(orig);
279 firm_dbg_module_t *dbg = DBG_MODULE;
286 /* Count the number of outs. */
287 foreach_out_edge(orig, edge)
288 n_outs += !pset_find_ptr(ignore_uses, get_edge_src_irn(edge));
291 * Put all outs into an array.
292 * This is neccessary, since the outs would be modified while
293 * interating on them what could bring the outs module in trouble.
295 outs = malloc(n_outs * sizeof(outs[0]));
296 foreach_out_edge(orig, edge) {
297 if(!pset_find_ptr(ignore_uses, get_edge_src_irn(edge))) {
298 outs[i].irn = get_edge_src_irn(edge);
299 outs[i].pos = get_edge_src_pos(edge);
305 * Search the valid def for each out and set it.
307 for(i = 0; i < n_outs; ++i) {
309 ir_node *irn = outs[i].irn;
310 int pos = outs[i].pos;
312 def = search_def(irn, pos, copies, copy_blocks, phi_blocks, mode);
313 DBG((dbg, LEVEL_2, "\t%+F(%d) -> %+F\n", irn, pos, def));
316 set_irn_n(irn, pos, def);
323 * Remove phis which are not neccesary.
324 * During place_phi_functions() phi functions are put on the dominance
325 * frontiers blindly. However some of them will never be used (these
326 * have at least one predecessor which is NULL, see search_def() for
327 * this case). Since place_phi_functions() enters them into the
328 * schedule, we have to remove them from there.
330 * @param copies The set of all copies made (including the phi functions).
332 static void remove_odd_phis(pset *copies, pset *unused_copies)
336 for(irn = pset_first(copies); irn; irn = pset_next(copies)) {
341 assert(sched_is_scheduled(irn) && "phi must be scheduled");
342 for(i = 0, n = get_irn_arity(irn); i < n && !illegal; ++i)
343 illegal = get_irn_n(irn, i) == NULL;
350 for(irn = pset_first(unused_copies); irn; irn = pset_next(unused_copies)) {
355 void be_introduce_copies_ignore(dom_front_info_t *info, ir_node *orig,
356 int n, ir_node *copy_nodes[], pset *ignore_uses)
358 pset *copies = pset_new_ptr(2 * n);
359 pset *copy_blocks = pset_new_ptr(2 * n);
360 pset *phi_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;
371 snprintf(buf, sizeof(buf), "-post-%d", ser++);
372 dump_ir_block_graph_sched(get_irn_irg(orig), buf);
376 firm_dbg_set_mask(dbg, DBG_LEVEL);
377 DBG((dbg, LEVEL_1, "Introducing following copies of %+F\n", orig));
380 pset_insert_ptr(copies, orig);
381 pset_insert_ptr(copy_blocks, get_nodes_block(orig));
384 * All phis using the original value are also copies of it
385 * and must be present in the copies set.
387 for(i = 0; i < n; ++i) {
389 " %+F in block %+F\n", copy_nodes[i], get_nodes_block(copy_nodes[i])));
390 pset_insert_ptr(copies, copy_nodes[i]);
391 pset_insert_ptr(copy_blocks, get_nodes_block(copy_nodes[i]));
395 * Disable optimization so that the phi functions do not
399 set_opt_normalize(0);
402 * Place the phi functions and reroute the usages.
404 determine_phi_blocks(orig, copies, copy_blocks, phi_blocks, info);
405 fix_usages(orig, copies, copy_blocks, phi_blocks, ignore_uses);
407 /* reset the optimizations */
408 set_optimize(save_optimize);
409 set_opt_normalize(save_normalize);
412 del_pset(phi_blocks);
413 del_pset(copy_blocks);
418 void be_introduce_copies(dom_front_info_t *info, ir_node *orig, int n, ir_node *copy_nodes[])
420 static pset *empty_set = NULL;
423 empty_set = pset_new_ptr_default();
425 be_introduce_copies_ignore(info, orig, n, copy_nodes, empty_set);
428 void be_introduce_copies_pset(dom_front_info_t *info, pset *nodes) {
429 int i, n = pset_count(nodes);
430 ir_node *orig, *irn, **copy_nodes;
431 static pset *empty_set = NULL;
436 copy_nodes = alloca((n-1)*sizeof(*copy_nodes));
437 irn = pset_first(nodes);
439 for (i=0, irn = pset_next(nodes); irn; irn=pset_next(nodes))
440 copy_nodes[i++] = irn;
444 empty_set = pset_new_ptr_default();
446 be_introduce_copies_ignore(info, orig, n-1, copy_nodes, empty_set);