Fixed small copy & paste error in the "foreach" defines and added additional defines...
[libfirm] / ir / be / beirgmod.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <stdlib.h>
6
7 #include "hashptr.h"
8 #include "pdeq.h"
9 #include "pset.h"
10 #include "pmap.h"
11 #include "util.h"
12 #include "debug.h"
13
14 #include "irflag_t.h"
15 #include "ircons_t.h"
16 #include "irnode_t.h"
17 #include "irmode_t.h"
18 #include "irdom_t.h"
19 #include "iredges_t.h"
20 #include "irgopt.h"
21
22 #include "be_t.h"
23 #include "bearch.h"
24 #include "besched_t.h"
25 #include "belive_t.h"
26 #include "benode_t.h"
27
28 #include "beirgmod.h"
29
30 #define DBG_MODULE firm_dbg_register("firm.be.irgmod")
31
32 struct _dom_front_info_t {
33   pmap *df_map;
34 };
35
36 static void compute_df_local(ir_node *bl, void *data)
37 {
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);
41   int i, n;
42
43   /*
44    * Create a new dom frot set for this node,
45    * if none exists.
46    */
47   if(!df)
48         pmap_insert(df_map, bl, pset_new_ptr(16));
49
50   for(i = 0, n = get_irn_arity(bl); i < n; ++i) {
51
52     /* The predecessor block */
53     ir_node *pred = get_nodes_block(get_irn_n(bl, i));
54
55     /* The dominance frontier set of the predecessor. */
56     pset *df = pmap_get(df_map, pred);
57           if(!df) {
58                 df = pset_new_ptr(16);
59                 pmap_insert(df_map, pred, df);
60           }
61
62     assert(df && "dom front set must have been created for this node");
63
64     if(pred != idom && bl)
65       pset_insert_ptr(df, bl);
66   }
67 }
68
69 static void compute_df_up(ir_node *bl, void *data)
70 {
71   pmap *df_map = ((dom_front_info_t *) data)->df_map;
72   ir_node *y;
73
74   for(y = get_Block_dominated_first(bl); y; y = get_Block_dominated_next(y)) {
75     ir_node *w;
76     pset *df = pmap_get(df_map, y);
77
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);
81   }
82 }
83
84 dom_front_info_t *be_compute_dominance_frontiers(ir_graph *irg)
85 {
86   dom_front_info_t *info = malloc(sizeof(*info));
87
88   info->df_map = pmap_create();
89
90   /*
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.
93    */
94   dom_tree_walk_irg(irg, NULL, compute_df_local, info);
95   dom_tree_walk_irg(irg, NULL, compute_df_up, info);
96   return info;
97 }
98
99 void be_free_dominance_frontiers(dom_front_info_t *info)
100 {
101   pmap_entry *ent;
102
103   for(ent = pmap_first(info->df_map); ent; ent = pmap_next(info->df_map))
104     del_pset(ent->value);
105
106   pmap_destroy(info->df_map);
107   free(info);
108 }
109
110 pset *be_get_dominance_frontier(dom_front_info_t *info, ir_node *block)
111 {
112   return pmap_get(info->df_map, block);
113 }
114
115 /**
116  * Algorithm to place the Phi-Functions.
117  * @see Appel, Modern Compiler Implementation in Java, 2nd ed., p. 399ff
118  *
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
123  * original value.
124  *
125  * The rename phase (see below) is responsible for fixing up the usages
126  * of the original node.
127  *
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
133  * rename).
134  */
135 static void place_phi_functions(ir_node *orig, pset *copies,
136     pset *copy_blocks, dom_front_info_t *df_info)
137 {
138   int i;
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;
145   void *it;
146   firm_dbg_module_t *dbg = DBG_MODULE;
147
148   /*
149    * Allocate an array for all blocks where the copies and the original
150    * value were defined.
151    */
152   int n_orig_blocks = pset_count(copy_blocks);
153   ir_node **orig_blocks = malloc(n_orig_blocks * sizeof(orig_blocks[0]));
154
155   /*
156    * Fill the worklist queue and the rest of the orig blocks array.
157    */
158   for(it = pset_first(copies), i = 0; it; it = pset_next(copies)) {
159     ir_node *copy_block = get_nodes_block(it);
160
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");
164     }
165
166     pdeq_putr(worklist, copy_block);
167     orig_blocks[i++] = copy_block;
168   }
169
170   while(!pdeq_empty(worklist)) {
171     ir_node *bl = pdeq_getl(worklist);
172     ir_node *y;
173     pset *df = be_get_dominance_frontier(df_info, bl);
174
175     for(y = pset_first(df); y; y = pset_next(df)) {
176       int n_preds = get_irn_arity(y);
177
178       if(!pset_find_ptr(phi_blocks, y)) {
179         ir_node *phi;
180         int insert = 1;
181
182         /*
183          * Set the orig node as the only operand of the
184          * phi node.
185          */
186         ins = realloc(ins, n_preds * sizeof(ins[0]));
187         for(i = 0; i < n_preds; ++i)
188           ins[i] = orig;
189
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",
193               phi, n_preds, bl));
194
195         /*
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.
199          */
200         pset_insert_ptr(copies, phi);
201         pset_insert_ptr(copy_blocks, y);
202
203         /* Insert the phi node into the schedule */
204         sched_add_before(sched_first(y), phi);
205
206         /* Insert the phi node in the phi blocks set. */
207         pset_insert_ptr(phi_blocks, y);
208
209         /*
210          * If orig or a copy of it were not defined in y,
211          * add y to the worklist.
212          */
213         for(i = 0; i < n_orig_blocks; ++i)
214           if(orig_blocks[i] == y) {
215             insert = 0;
216             break;
217           }
218
219         if(insert)
220           pdeq_putr(worklist, y);
221
222       }
223     }
224   }
225
226   del_pset(phi_blocks);
227   del_pdeq(worklist);
228
229   free(orig_blocks);
230
231   if(ins)
232     free(ins);
233 }
234
235 /**
236  * Find the copy of the given original node whose value is 'active'
237  * at a usage.
238  *
239  * The usage is given as a node and a position. Initially, the given operand
240  * points to a node for which copies were introduced. We have to find
241  * the valid copy for this usage. This is done by travering the
242  * dominance tree upwards. If the usage is a phi function, we start
243  * traversing from the predecessor block which corresponds to the phi
244  * usage.
245  *
246  * @param usage The node which uses the original node.
247  * @param pos The number of the argument which corresponds to the
248  * original node.
249  * @param copy_blocks A set containing all basic block in which copies
250  * of the original node are located.
251  * @param copies A set containing all node which are copies from the
252  * original node.
253  * @return The valid copy for usage.
254  */
255 static ir_node *search_def(ir_node *usage, int pos, pset *copies, pset *copy_blocks)
256 {
257   ir_node *curr_bl;
258   ir_node *start_irn;
259
260   curr_bl = get_nodes_block(usage);
261
262   /*
263    * If the usage is in a phi node, search the copy in the
264    * predecessor denoted by pos.
265    */
266   if(is_Phi(usage)) {
267     curr_bl = get_nodes_block(get_irn_n(curr_bl, pos));
268     start_irn = sched_last(curr_bl);
269   }
270
271   else {
272     start_irn = sched_prev(usage);
273   }
274
275   /*
276    * Traverse the dominance tree upwards from the
277    * predecessor block of the usage.
278    */
279   while(curr_bl != NULL) {
280
281     /*
282      * If this block contains a copy, search the block
283      * instruction by instruction.
284      */
285     if(pset_find_ptr(copy_blocks, curr_bl)) {
286       ir_node *irn;
287
288       /* Look at each instruction from last to first. */
289       for(irn = start_irn; !is_Block(irn); irn = sched_prev(irn)) {
290
291         /* Take the first copy we find. */
292         if(pset_find_ptr(copies, irn))
293           return irn;
294       }
295     }
296
297     /* If were not done yet, look in the immediate dominator */
298     curr_bl = get_Block_idom(curr_bl);
299     if(curr_bl)
300       start_irn = sched_last(curr_bl);
301   }
302
303   return NULL;
304 }
305
306 static void fix_usages(ir_node *orig, pset *copies, pset *copy_blocks)
307 {
308   int i = 0;
309   int n_outs = 0;
310   const ir_edge_t *edge;
311   firm_dbg_module_t *dbg = DBG_MODULE;
312
313   struct {
314     ir_node *irn;
315     int pos;
316   } *outs;
317
318   /* Count the number of outs. */
319   foreach_out_edge(orig, edge)
320     n_outs++;
321
322   /*
323    * Put all outs into an array.
324    * This is neccessary, since the outs would be modified while
325    * interating on them what could bring the outs module in trouble.
326    */
327   DBG((dbg, LEVEL_2, "  Users of %+F\n", orig));
328   outs = malloc(n_outs * sizeof(outs[0]));
329   foreach_out_edge(orig, edge) {
330     outs[i].irn = get_edge_src_irn(edge);
331     outs[i].pos = get_edge_src_pos(edge);
332     i += 1;
333   }
334
335   /*
336    * Search the valid def for each out and set it.
337    */
338   for(i = 0; i < n_outs; ++i) {
339     ir_node *def;
340     ir_node *irn = outs[i].irn;
341     int pos = outs[i].pos;
342
343     def = search_def(irn, pos, copies, copy_blocks);
344     DBG((dbg, LEVEL_2, "    %+F(%d) -> %+F\n", irn, pos, def));
345
346     if(def != NULL)
347       set_irn_n(irn, pos, def);
348   }
349
350   free(outs);
351 }
352
353 void be_introduce_copies(dom_front_info_t *info, ir_node *orig, int n, ir_node *copy_nodes[])
354 {
355   pset *copies = pset_new_ptr(2 * n);
356   pset *copy_blocks = pset_new_ptr(2 * n);
357   int save_optimize = get_optimize();
358   int save_normalize = get_opt_normalize();
359   firm_dbg_module_t *dbg = DBG_MODULE;
360   int i;
361
362   firm_dbg_set_mask(dbg, -1);
363   DBG((dbg, LEVEL_1, "Introducing following copies of %+F\n", orig));
364
365   /* Fill the sets. */
366   pset_insert_ptr(copies, orig);
367   pset_insert_ptr(copy_blocks, get_nodes_block(orig));
368
369   for(i = 0; i < n; ++i) {
370     DBG((dbg, LEVEL_1,
371           "  %+F in block %+F\n", copy_nodes[i], get_nodes_block(copy_nodes[i])));
372     pset_insert_ptr(copies, copy_nodes[i]);
373     pset_insert_ptr(copy_blocks, get_nodes_block(copy_nodes[i]));
374   }
375
376   /*
377    * Disable optimization so that the phi functions do not
378    * disappear.
379    */
380   set_optimize(0);
381   set_opt_normalize(0);
382
383   /*
384    * Place the phi functions and reroute the usages.
385    */
386   place_phi_functions(orig, copies, copy_blocks, info);
387   fix_usages(orig, copies, copy_blocks);
388
389   /* reset the optimizations */
390   set_optimize(save_optimize);
391   set_opt_normalize(save_normalize);
392
393   del_pset(copies);
394   del_pset(copy_blocks);
395 }