85f233f285a47a40dd32b120461c441409dc1b66
[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
13 #include "irflag_t.h"
14 #include "ircons_t.h"
15 #include "irnode_t.h"
16 #include "irmode_t.h"
17 #include "irdom_t.h"
18 #include "iredges_t.h"
19
20 #include "be_t.h"
21 #include "bearch.h"
22 #include "besched_t.h"
23 #include "belive_t.h"
24 #include "benode_t.h"
25
26 #include "beirgmod.h"
27
28 struct _dom_front_info_t {
29   pmap *df_map;
30 };
31
32 static void compute_df_local(ir_node *bl, void *data)
33 {
34   pmap *df_map = ((dom_front_info_t *) data)->df_map;
35   ir_node *idom = get_Block_idom(bl);
36   int i, n;
37
38   for(i = 0, n = get_irn_arity(bl); i < n; ++i) {
39
40     /* The predecessor block */
41     ir_node *pred = get_nodes_block(get_irn_n(bl, i));
42
43     /* The dominance frontier set of the predecessor. */
44     pset *df = pmap_get(df_map, pred);
45
46     /*
47      * Create the dominance frontier set of the predecessor
48      * if it didn't exist.
49      */
50     if(!df) {
51       df = pset_new_ptr(16);
52       pmap_insert(df_map, pred, df);
53     }
54
55
56     if(pred != idom && bl)
57       pset_insert_ptr(df, bl);
58   }
59 }
60
61 static void compute_df_up(ir_node *bl, void *data)
62 {
63   pmap *df_map = ((dom_front_info_t *) data)->df_map;
64   ir_node *y;
65
66   for(y = get_Block_dominated_first(bl); y; y = get_Block_dominated_next(y)) {
67     ir_node *w;
68     pset *df = pmap_get(df_map, y);
69
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);
73   }
74 }
75
76 dom_front_info_t *be_compute_dominance_frontiers(ir_graph *irg)
77 {
78   dom_front_info_t *info = malloc(sizeof(*info));
79
80   info->df_map = pmap_create();
81
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);
85   return info;
86 }
87
88 void be_free_dominance_frontiers(dom_front_info_t *info)
89 {
90   pmap_entry *ent;
91
92   for(ent = pmap_first(info->df_map); ent; ent = pmap_next(info->df_map))
93     del_pset(ent->value);
94
95   pmap_destroy(info->df_map);
96   free(info);
97 }
98
99 pset *be_get_dominance_frontier(dom_front_info_t *info, ir_node *block)
100 {
101   return pmap_get(info->df_map, block);
102 }
103
104 /**
105  * Algorithm to place the Phi-Functions.
106  * @see Appel, Modern Compiler Implementation in Java, 2nd ed., p. 399ff
107  *
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
112  * original value.
113  *
114  * The rename phase (see below) is responsible for fixing up the usages
115  * of the original node.
116  *
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
122  * rename).
123  */
124 static void place_phi_functions(ir_node *orig, pset *copies,
125     pset *copy_blocks, dom_front_info_t *df_info)
126 {
127   int i;
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;
134   void *it;
135
136   /*
137    * Allocate an array for all blocks where the copies and the original
138    * value were defined.
139    */
140   int n_orig_blocks = pset_count(copy_blocks) + 1;
141   ir_node **orig_blocks = malloc(n_orig_blocks * sizeof(orig_blocks[0]));
142
143   /*
144    * Fill the array of definition blocks.
145    */
146   orig_blocks[0] = get_nodes_block(orig);
147
148   /*
149    * Fill the worklist queue and the rest of the orig blocks array.
150    */
151   for(it = pset_first(copies), i = 1; it; it = pset_next(copies)) {
152     ir_node *copy_block = get_nodes_block(it);
153
154     assert(block_dominates(orig_block, copy_block)
155         && "The block of the copy must be dominated by the block of the value");
156
157     pdeq_putr(worklist, it);
158     orig_blocks[i++] = copy_block;
159   }
160
161   while(!pdeq_empty(worklist)) {
162     ir_node *irn = pdeq_getl(worklist);
163     ir_node *bl = get_nodes_block(irn);
164     ir_node *y;
165     int n_preds = get_irn_arity(bl);
166     pset *df = be_get_dominance_frontier(df_info, bl);
167
168     for(y = pset_first(df); y; y = pset_next(df)) {
169
170       if(!pset_find_ptr(phi_blocks, y)) {
171         ir_node *phi;
172         int insert = 1;
173
174         /*
175          * Set the orig node as the only operand of the
176          * phi node.
177          */
178         ins = realloc(ins, n_preds * sizeof(ins[0]));
179         for(i = 0; i < n_preds; ++i)
180           ins[0] = orig;
181
182         /* Insert phi node */
183         phi = new_r_Phi(irg, bl, n_preds, ins, mode);
184
185         /*
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.
189          */
190         pset_insert_ptr(copies, phi);
191         pset_insert_ptr(copy_blocks, y);
192
193         /* Insert the phi node into the schedule */
194         sched_add_before(sched_first(y), phi);
195
196         /* Insert the phi node in the phi blocks set. */
197         pset_insert_ptr(phi_blocks, y);
198
199         /*
200          * If orig or a copy of it were not defined in y,
201          * add y to the worklist.
202          */
203         for(i = 0; i < n_orig_blocks; ++i)
204           if(orig_blocks[i] == y) {
205             insert = 0;
206             break;
207           }
208
209         if(insert)
210           pdeq_putr(worklist, y);
211
212       }
213     }
214   }
215
216   del_pset(phi_blocks);
217   del_pdeq(worklist);
218
219   free(orig_blocks);
220
221   if(ins)
222     free(ins);
223 }
224
225 /**
226  * Find the copy of the given original node whose value is 'active'
227  * at a usage.
228  *
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
234  * usage.
235  *
236  * @param usage The node which uses the original node.
237  * @param pos The number of the argument which corresponds to the
238  * original node.
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
242  * original node.
243  * @return The valid copy for usage.
244  */
245 static ir_node *search_def(ir_node *usage, int pos, pset *copies, pset *copy_blocks)
246 {
247   ir_node *curr_bl;
248
249   curr_bl = get_nodes_block(usage);
250
251   /*
252    * If the usage is in a phi node, search the copy in the
253    * predecessor denoted by pos.
254    */
255   if(is_Phi(usage))
256     curr_bl = get_nodes_block(get_irn_n(curr_bl, pos));
257
258   /*
259    * Traverse the dominance tree upwards from the
260    * predecessor block of the usage.
261    */
262   while(curr_bl != NULL) {
263
264     /*
265      * If this block contains a copy, search the block
266      * instruction by instruction.
267      */
268     if(pset_find_ptr(copy_blocks, curr_bl)) {
269       ir_node *irn;
270
271       /* Look at each instruction from last to first. */
272       sched_foreach_reverse(curr_bl, irn) {
273
274         /* Take the first copy we find. */
275         if(pset_find_ptr(copies, irn))
276           return irn;
277       }
278
279       assert(0 && "We must have encountered a copy");
280     }
281
282     /* If were not done yet, look in the immediate dominator */
283     curr_bl = get_Block_idom(curr_bl);
284   }
285
286   return NULL;
287 }
288
289 static void fix_usages(ir_node *orig, pset *copies, pset *copy_blocks)
290 {
291   int i;
292   int n_outs = 0;
293   const ir_edge_t *edge;
294   const ir_edge_t **outs;
295
296   /* Count the number of outs. */
297   foreach_out_edge(orig, edge)
298     n_outs++;
299
300   /*
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.
304    */
305   outs = malloc(n_outs * sizeof(outs[0]));
306   foreach_out_edge(orig, edge)
307     outs[i++] = edge;
308
309   /*
310    * Search the valid def for each out and set it.
311    */
312   for(i = 0; i < n_outs; ++i) {
313     ir_node *def;
314     ir_node *irn = get_edge_src_irn(outs[i]);
315     int pos = get_edge_src_pos(outs[i]);
316
317     def = search_def(irn, pos, copies, copy_blocks);
318     set_irn_n(irn, pos, def);
319   }
320
321   free(outs);
322 }
323
324 void be_introduce_copies(dom_front_info_t *info, ir_node *orig, int n, ir_node *copy_nodes[])
325 {
326   pset *copies = pset_new_ptr(2 * n);
327   pset *copy_blocks = pset_new_ptr(2 * n);
328   int save_optimize = get_optimize();
329   int i;
330
331   /* Fill the sets. */
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]));
335   }
336
337   /*
338    * Disable optimization so that the phi functions do not
339    * disappear.
340    */
341   set_optimize(0);
342
343   /*
344    * Place the phi functions and reroute the usages.
345    */
346   place_phi_functions(orig, copies, copy_blocks, info);
347   fix_usages(orig, copies, copy_blocks);
348
349   /* reset the optimizations */
350   set_optimize(save_optimize);
351
352   del_pset(copies);
353   del_pset(copy_blocks);
354 }