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