Added ssa destruction. TODO: Perm placement.
[libfirm] / ir / be / beirgmod.c
1
2 #include <stdlib.h>
3
4 #include "hashptr.h"
5 #include "pdeq.h"
6 #include "pset.h"
7 #include "pmap.h"
8
9 #include "irflag_t.h"
10 #include "ircons_t.h"
11 #include "irnode_t.h"
12 #include "irmode_t.h"
13 #include "irdom_t.h"
14 #include "iredges_t.h"
15
16 #include "besched_t.h"
17 #include "beirgmod.h"
18
19 struct _dom_front_info_t {
20   pmap *df_map;
21 };
22
23 static void compute_df_local(ir_node *bl, void *data)
24 {
25   pmap *df_map = ((dom_front_info_t *) data)->df_map;
26   ir_node *idom = get_Block_idom(bl);
27   int i, n;
28
29   for(i = 0, n = get_irn_arity(bl); i < n; ++i) {
30
31     /* The predecessor block */
32     ir_node *pred = get_nodes_block(get_irn_n(bl, i));
33
34     /* The dominance frontier set of the predecessor. */
35     pset *df = pmap_get(df_map, pred);
36
37     /*
38      * Create the dominance frontier set of the predecessor
39      * if it didn't exist.
40      */
41     if(!df) {
42       df = pset_new_ptr(16);
43       pmap_insert(df_map, pred, df);
44     }
45
46
47     if(pred != idom && bl)
48       pset_insert_ptr(df, bl);
49   }
50 }
51
52 static void compute_df_up(ir_node *bl, void *data)
53 {
54   pmap *df_map = ((dom_front_info_t *) data)->df_map;
55   ir_node *y;
56
57   for(y = get_Block_dominated_first(bl); y; y = get_Block_dominated_next(y)) {
58     ir_node *w;
59     pset *df = pmap_get(df_map, y);
60
61     for(w = pset_first(df); df; w = pset_next(df))
62       if(!block_dominates(bl, w) || bl == w)
63         pset_insert_ptr(df, w);
64   }
65 }
66
67 dom_front_info_t *be_compute_dominance_frontiers(ir_graph *irg)
68 {
69   dom_front_info_t *info = malloc(sizeof(*info));
70
71   info->df_map = pmap_create();
72
73   /* Perhaps both can we interwined */
74   dom_tree_walk_irg(irg, compute_df_local, NULL, info);
75   dom_tree_walk_irg(irg, NULL, compute_df_up, info);
76   return info;
77 }
78
79 void be_free_dominance_frontiers(dom_front_info_t *info)
80 {
81   pmap_entry *ent;
82
83   for(ent = pmap_first(info->df_map); ent; ent = pmap_next(info->df_map))
84     del_pset(ent->value);
85
86   pmap_destroy(info->df_map);
87   free(info);
88 }
89
90 pset *be_get_dominance_frontier(dom_front_info_t *info, ir_node *block)
91 {
92   return pmap_get(info->df_map, block);
93 }
94
95 /**
96  * Algorithm to place the Phi-Functions.
97  * @see Appel, Modern Compiler Implementation in Java, 2nd ed., p. 399ff
98  *
99  * This function takes an original node and a set of already placed
100  * copies of that node called @p copies. It places phi nodes at the
101  * iterated dominance frontiers of these copies and puts these phi nodes
102  * in the @p copies set, since they are another form of copies of the
103  * original value.
104  *
105  * The rename phase (see below) is responsible for fixing up the usages
106  * of the original node.
107  *
108  * @param orig The original node.
109  * @param copies A set contianing nodes representing a copy of the
110  * original node. Each node must be inserted into the block's schedule.
111  * @param copy_blocks A set in which the blocks are recorded which
112  * contain a copy. This is just for efficiency in later phases (see
113  * rename).
114  */
115 static void place_phi_functions(ir_node *orig, pset *copies,
116     pset *copy_blocks, dom_front_info_t *df_info)
117 {
118   int i;
119   ir_node *orig_block = get_nodes_block(orig);
120   ir_graph *irg = get_irn_irg(orig);
121   ir_mode *mode = get_irn_mode(orig);
122   pdeq *worklist = new_pdeq();
123   pset *phi_blocks = pset_new_ptr(8);
124   ir_node **ins = NULL;
125   void *it;
126
127   /*
128    * Allocate an array for all blocks where the copies and the original
129    * value were defined.
130    */
131   int n_orig_blocks = pset_count(copy_blocks) + 1;
132   ir_node **orig_blocks = malloc(n_orig_blocks * sizeof(orig_blocks[0]));
133
134   /*
135    * Fill the array of definition blocks.
136    */
137   orig_blocks[0] = get_nodes_block(orig);
138
139   /*
140    * Fill the worklist queue and the rest of the orig blocks array.
141    */
142   for(it = pset_first(copies), i = 1; it; it = pset_next(copies)) {
143     ir_node *copy_block = get_nodes_block(it);
144
145     assert(block_dominates(orig_block, copy_block)
146         && "The block of the copy must be dominated by the block of the value");
147
148     pdeq_putr(worklist, it);
149     orig_blocks[i++] = copy_block;
150   }
151
152   while(!pdeq_empty(worklist)) {
153     ir_node *irn = pdeq_getl(worklist);
154     ir_node *bl = get_nodes_block(irn);
155     ir_node *y;
156     int n_preds = get_irn_arity(bl);
157     pset *df = be_get_dominance_frontier(df_info, bl);
158
159     for(y = pset_first(df); y; y = pset_next(df)) {
160
161       if(!pset_find_ptr(phi_blocks, y)) {
162         ir_node *phi;
163         int insert = 1;
164
165         /*
166          * Set the orig node as the only operand of the
167          * phi node.
168          */
169         ins = realloc(ins, n_preds * sizeof(ins[0]));
170         for(i = 0; i < n_preds; ++i)
171           ins[0] = orig;
172
173         /* Insert phi node */
174         phi = new_r_Phi(irg, bl, n_preds, ins, mode);
175
176         /*
177          * The phi node itself is also a copy of the original
178          * value. So put it in the copies set also, so that
179          * the rename phase can treat them right.
180          */
181         pset_insert_ptr(copies, phi);
182         pset_insert_ptr(copy_blocks, y);
183
184         /* Insert the phi node into the schedule */
185         sched_add_before(sched_first(y), phi);
186
187         /* Insert the phi node in the phi blocks set. */
188         pset_insert_ptr(phi_blocks, y);
189
190         /*
191          * If orig or a copy of it were not defined in y,
192          * add y to the worklist.
193          */
194         for(i = 0; i < n_orig_blocks; ++i)
195           if(orig_blocks[i] == y) {
196             insert = 0;
197             break;
198           }
199
200         if(insert)
201           pdeq_putr(worklist, y);
202
203       }
204     }
205   }
206
207   del_pset(phi_blocks);
208   del_pdeq(worklist);
209
210   free(orig_blocks);
211
212   if(ins)
213     free(ins);
214 }
215
216 /**
217  * Find the copy of the given original node whose value is 'active'
218  * at a usage.
219  *
220  * The usage is given as a node and a position. Initially, the given operand
221  * points to a node for which copies were introduced. We have to find
222  * the valid copy for this usage. This is done by travering the
223  * dominance tree upwards. If the usage is a phi function, we start
224  * traversing from the predecessor block which corresponds to the phi
225  * usage.
226  *
227  * @param usage The node which uses the original node.
228  * @param pos The number of the argument which corresponds to the
229  * original node.
230  * @param copy_blocks A set containing all basic block in which copies
231  * of the original node are located.
232  * @param copies A set containing all node which are copies from the
233  * original node.
234  * @return The valid copy for usage.
235  */
236 static ir_node *search_def(ir_node *usage, int pos, pset *copies, pset *copy_blocks)
237 {
238   ir_node *curr_bl;
239
240   curr_bl = get_nodes_block(usage);
241
242   /*
243    * If the usage is in a phi node, search the copy in the
244    * predecessor denoted by pos.
245    */
246   if(is_Phi(usage))
247     curr_bl = get_nodes_block(get_irn_n(curr_bl, pos));
248
249   /*
250    * Traverse the dominance tree upwards from the
251    * predecessor block of the usage.
252    */
253   while(curr_bl != NULL) {
254
255     /*
256      * If this block contains a copy, search the block
257      * instruction by instruction.
258      */
259     if(pset_find_ptr(copy_blocks, curr_bl)) {
260       ir_node *irn;
261
262       /* Look at each instruction from last to first. */
263       sched_foreach_reverse(curr_bl, irn) {
264
265         /* Take the first copy we find. */
266         if(pset_find_ptr(copies, irn))
267           return irn;
268       }
269
270       assert(0 && "We must have encountered a copy");
271     }
272
273     /* If were not done yet, look in the immediate dominator */
274     curr_bl = get_Block_idom(curr_bl);
275   }
276
277   return NULL;
278 }
279
280
281 static void fix_usages(ir_node *orig, pset *copies, pset *copy_blocks)
282 {
283   int i;
284   int n_outs = 0;
285   const ir_edge_t *edge;
286   const ir_edge_t **outs;
287
288   /* Count the number of outs. */
289   foreach_out_edge(orig, edge)
290     n_outs++;
291
292   /*
293    * Put all outs into an array.
294    * This is neccessary, since the outs would be modified while
295    * interating on them what could bring the outs module in trouble.
296    */
297   outs = malloc(n_outs * sizeof(outs[0]));
298   foreach_out_edge(orig, edge)
299     outs[i++] = edge;
300
301   /*
302    * Search the valid def for each out and set it.
303    */
304   for(i = 0; i < n_outs; ++i) {
305     ir_node *def;
306     ir_node *irn = get_edge_src_irn(outs[i]);
307     int pos = get_edge_src_pos(outs[i]);
308
309     def = search_def(irn, pos, copies, copy_blocks);
310     set_irn_n(irn, pos, def);
311   }
312
313   free(outs);
314 }
315
316 void be_introduce_copies(dom_front_info_t *info, ir_node *orig, int n, ir_node *copy_nodes[])
317 {
318   pset *copies = pset_new_ptr(2 * n);
319   pset *copy_blocks = pset_new_ptr(2 * n);
320   int save_optimize = get_optimize();
321   int i;
322
323   /* Fill the sets. */
324   for(i = 0; i < n; ++i) {
325     pset_insert_ptr(copies, copy_nodes[i]);
326     pset_insert_ptr(copy_blocks, get_nodes_block(copy_nodes[i]));
327   }
328
329   /*
330    * Disable optimization so that the phi functions do not
331    * disappear.
332    */
333   set_optimize(0);
334
335   /*
336    * Place the phi functions and reroute the usages.
337    */
338   place_phi_functions(orig, copies, copy_blocks, info);
339   fix_usages(orig, copies, copy_blocks);
340
341   /* reset the optimizations */
342   set_optimize(save_optimize);
343
344   del_pset(copies);
345   del_pset(copy_blocks);
346 }