Fixed a bug
[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         /*
204          * Insert the phi node into the schedule if it
205          * can occur there (PhiM's are not to put into a schedule.
206          */
207         if(to_appear_in_schedule(phi))
208           sched_add_before(sched_first(y), phi);
209
210         /* Insert the phi node in the phi blocks set. */
211         pset_insert_ptr(phi_blocks, y);
212
213         /*
214          * If orig or a copy of it were not defined in y,
215          * add y to the worklist.
216          */
217         for(i = 0; i < n_orig_blocks; ++i)
218           if(orig_blocks[i] == y) {
219             insert = 0;
220             break;
221           }
222
223         if(insert)
224           pdeq_putr(worklist, y);
225
226       }
227     }
228   }
229
230   del_pset(phi_blocks);
231   del_pdeq(worklist);
232
233   free(orig_blocks);
234
235   if(ins)
236     free(ins);
237 }
238
239 /**
240  * Find the copy of the given original node whose value is 'active'
241  * at a usage.
242  *
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
248  * usage.
249  *
250  * @param usage The node which uses the original node.
251  * @param pos The number of the argument which corresponds to the
252  * original node.
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
256  * original node.
257  * @return The valid copy for usage.
258  */
259 static ir_node *search_def(ir_node *usage, int pos, pset *copies, pset *copy_blocks)
260 {
261   ir_node *curr_bl;
262   ir_node *start_irn;
263
264   curr_bl = get_nodes_block(usage);
265
266   /*
267    * If the usage is in a phi node, search the copy in the
268    * predecessor denoted by pos.
269    */
270   if(is_Phi(usage)) {
271     curr_bl = get_nodes_block(get_irn_n(curr_bl, pos));
272     start_irn = sched_last(curr_bl);
273   }
274
275   else {
276     start_irn = sched_prev(usage);
277   }
278
279   /*
280    * Traverse the dominance tree upwards from the
281    * predecessor block of the usage.
282    */
283   while(curr_bl != NULL) {
284
285     /*
286      * If this block contains a copy, search the block
287      * instruction by instruction.
288      */
289     if(pset_find_ptr(copy_blocks, curr_bl)) {
290       ir_node *irn;
291
292       /* Look at each instruction from last to first. */
293       for(irn = start_irn; !is_Block(irn); irn = sched_prev(irn)) {
294
295         /* Take the first copy we find. */
296         if(pset_find_ptr(copies, irn))
297           return irn;
298       }
299     }
300
301     /* If were not done yet, look in the immediate dominator */
302     curr_bl = get_Block_idom(curr_bl);
303     if(curr_bl)
304       start_irn = sched_last(curr_bl);
305   }
306
307   return NULL;
308 }
309
310 static void fix_usages(ir_node *orig, pset *copies, pset *copy_blocks)
311 {
312   int i = 0;
313   int n_outs = 0;
314   const ir_edge_t *edge;
315   firm_dbg_module_t *dbg = DBG_MODULE;
316
317   struct {
318     ir_node *irn;
319     int pos;
320   } *outs;
321
322   /* Count the number of outs. */
323   foreach_out_edge(orig, edge)
324     n_outs++;
325
326   /*
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.
330    */
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);
336     i += 1;
337   }
338
339   /*
340    * Search the valid def for each out and set it.
341    */
342   for(i = 0; i < n_outs; ++i) {
343     ir_node *def;
344     ir_node *irn = outs[i].irn;
345     int pos = outs[i].pos;
346
347     def = search_def(irn, pos, copies, copy_blocks);
348     DBG((dbg, LEVEL_2, "    %+F(%d) -> %+F\n", irn, pos, def));
349
350     if(def != NULL)
351       set_irn_n(irn, pos, def);
352   }
353
354   free(outs);
355 }
356
357 void be_introduce_copies(dom_front_info_t *info, ir_node *orig, int n, ir_node *copy_nodes[])
358 {
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;
364   int i;
365
366   firm_dbg_set_mask(dbg, -1);
367   DBG((dbg, LEVEL_1, "Introducing following copies of %+F\n", orig));
368
369   /* Fill the sets. */
370   pset_insert_ptr(copies, orig);
371   pset_insert_ptr(copy_blocks, get_nodes_block(orig));
372
373   for(i = 0; i < n; ++i) {
374     DBG((dbg, LEVEL_1,
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]));
378   }
379
380   /*
381    * Disable optimization so that the phi functions do not
382    * disappear.
383    */
384   set_optimize(0);
385   set_opt_normalize(0);
386
387   /*
388    * Place the phi functions and reroute the usages.
389    */
390   place_phi_functions(orig, copies, copy_blocks, info);
391   fix_usages(orig, copies, copy_blocks);
392
393   /* reset the optimizations */
394   set_optimize(save_optimize);
395   set_opt_normalize(save_normalize);
396
397   del_pset(copies);
398   del_pset(copy_blocks);
399 }