9243bbe794ef46dd11cfd31fdcd0f2565f35bf71
[libfirm] / ir / opt / gvn_pre.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief   Global Value Numbering Partial Redundancy Elimination
23  *          (VanDrunen Hosking 2004)
24  * @author  Michael Beck
25  * @version $Id$
26  * @summary
27  */
28 #include "config.h"
29
30 #include "irflag.h"
31 #include "irdom.h"
32 #include "irouts.h"
33 #include "irgopt.h"
34 #include "irgwalk.h"
35 #include "ircons.h"
36 #include "irgmod.h"
37 #include "valueset.h"
38 #include "irnodemap.h"
39 #include "irnodeset.h"
40 #include "iredges.h"
41 #include "iropt_dbg.h"
42 #include "debug.h"
43
44 #include "irgraph_t.h"
45 #include "irnode_t.h"
46 #include "iropt_t.h"
47
48 /** Additional info we need for every block. */
49 typedef struct block_info {
50         ir_valueset_t     *exp_gen;   /**< The set of expression per block. */
51         ir_valueset_t     *avail_out; /**< The Avail_out set for a block. */
52         ir_valueset_t     *antic_in;  /**< The Antic_in set for a block. */
53         ir_valueset_t     *new_set;   /**< The set of all new values for a block. */
54         ir_node           *avail;     /**< The get_map(avail, block) result. */
55         ir_node           *block;     /**< The Block of the block info. */
56         struct block_info *next;      /**< Links all entries, so we can recover the sets easily. */
57         int               not_found;  /**< Non-zero, if avail was not found in this block. */
58 } block_info;
59
60 /**
61  * A pair of nodes that must be exchanged.
62  * We must defer the exchange because our hash-sets cannot
63  * find an already replace node else.
64  */
65 typedef struct elim_pair {
66         ir_node *old_node;      /**< The old node that will be replaced. */
67         ir_node *new_node;      /**< The new node. */
68         struct elim_pair *next; /**< Links all entries in a list. */
69         int     reason;         /**< The reason for the replacement. */
70 } elim_pair;
71
72 /** The environment for the GVN-PRE algorithm */
73 typedef struct pre_env {
74         struct obstack *obst;   /**< The obstack to allocate on. */
75         ir_node *start_block;   /**< The start block of the current graph. */
76         ir_node *end_block;     /**< The end block of the current graph */
77         block_info *list;       /**< Links all block info entires for easier recovery. */
78         elim_pair *pairs;       /**< A list of node pairs that must be eliminated. */
79         unsigned last_idx;      /**< last node index of "old" nodes, all higher indexes are newly created once. */
80         char changes;           /**< Non-zero, if calculation of Antic_in has changed. */
81         char first_iter;        /**< non-zero for first iteration */
82 } pre_env;
83
84 static pset         *value_table;
85 static ir_nodemap_t value_map;
86
87 /** The debug module handle. */
88 DEBUG_ONLY(static firm_dbg_module_t *dbg;)
89
90 /* ----------  Functions for Value sets ---------- */
91
92 /** computes dst = dst \/ src for value sets */
93 static void value_union(ir_valueset_t *dst, ir_valueset_t *src)
94 {
95         ir_valueset_iterator_t iter;
96         ir_node *value, *expr;
97
98         foreach_valueset(src, value, expr, iter) {
99                 ir_valueset_insert(dst, value, expr);
100         }
101 }
102
103
104 /* ----------  Functions for Values ---------- */
105
106 /**
107  * Add a node e representing the value v to the set.
108  *
109  * @param e  a node representing an expression
110  * @param v  a node representing a value
111  *
112  * @return the final value for the expression e
113  */
114 static ir_node *add(ir_node *e, ir_node *v)
115 {
116         if (is_Proj(v)) {
117                 ir_node *pred = get_Proj_pred(v);
118                 ir_node *v_pred = identify_remember(value_table, pred);
119
120                 if (v_pred != pred) {
121                         /* must create a new value here */
122                         v = new_r_Proj(current_ir_graph, get_nodes_block(v_pred), v_pred, get_irn_mode(v), get_Proj_proj(v));
123                 }
124         }
125         v = identify_remember(value_table, v);
126         ir_nodemap_insert(&value_map, e, v);
127         return v;
128 }  /* add */
129
130 /**
131  * Lookup a value in a value set.
132  *
133  * @param e  a node representing an expression
134  *
135  * @return a node representing the value or NULL if
136  *         the given expression is not available
137  */
138 static ir_node *lookup(ir_node *e)
139 {
140         ir_node *value = ir_nodemap_get(&value_map, e);
141         if (value != NULL)
142                 return identify_remember(value_table, value);
143         return NULL;
144 }  /* lookup */
145
146 /**
147  * Return the block info of a block.
148  *
149  * @param block  the block
150  */
151 static block_info *get_block_info(ir_node *block) {
152         return get_irn_link(block);
153 }  /* get_block_info */
154
155 /**
156  * Allocate a block info for a block.
157  *
158  * @param block   the block
159  * @param env     the environment
160  */
161 static void alloc_blk_info(ir_node *block, pre_env *env) {
162         block_info *info = obstack_alloc(env->obst, sizeof(*info));
163
164         set_irn_link(block, info);
165         info->exp_gen   = ir_valueset_new(16);
166         info->avail_out = ir_valueset_new(16);
167         info->antic_in  = ir_valueset_new(16);
168         info->new_set   = NULL;
169         info->avail     = NULL;
170         info->block     = block;
171         info->next      = env->list;
172         env->list       = info;
173         info->not_found = 0;
174 }  /* alloc_blk_info */
175
176 /**
177  * Returns non-zero if a node is movable and a possible candidate for PRE.
178  *
179  * @param n  the node
180  */
181 static int is_nice_value(ir_node *n) {
182         ir_mode *mode;
183
184         while (is_Proj(n))
185                 n = get_Proj_pred(n);
186         if (get_irn_pinned(n) == op_pin_state_pinned)
187                 return 0;
188         mode = get_irn_mode(n);
189         if (!mode_is_data(mode)) {
190                 if (! is_Div(n) && ! is_Mod(n) && ! is_DivMod(n))
191                         return 0;
192                 if (! is_NoMem(get_fragile_op_mem(n)))
193                         return 0;
194         }
195         return 1;
196 }  /* is_nice_value */
197
198 #ifdef DEBUG_libfirm
199 /**
200  * Dump a value set.
201  *
202  * @param set    the set to dump
203  * @param txt    a text to describe the set
204  * @param block  the owner block of the set
205  */
206 static void dump_value_set(ir_valueset_t *set, char *txt, ir_node *block) {
207         ir_valueset_iterator_t iter;
208         ir_node *value, *expr;
209         int i;
210
211         DB((dbg, LEVEL_2, "%s(%+F) = {\n", txt, block));
212         i = 0;
213         foreach_valueset(set, value, expr, iter) {
214                 if ((i & 3) == 3)
215                         DB((dbg, LEVEL_2, "\n"));
216                 if (value != expr)
217                         DB((dbg, LEVEL_2, " %+F(%+F),", expr, value));
218                 else
219                         DB((dbg, LEVEL_2, " %+F,", expr));
220                 ++i;
221         }
222         DB((dbg, LEVEL_2, "\n}\n"));
223 }  /* dump_value_set */
224
225 #else
226 #define dump_value_set(set, txt, block)
227 #endif /* DEBUG_libfirm */
228
229 /**
230  * Topological walker. Allocates block info for every block and place nodes in topological
231  * order into the nodes set.
232  */
233 static void topo_walker(ir_node *irn, void *ctx) {
234         pre_env    *env = ctx;
235         ir_node    *block;
236         block_info *info;
237         ir_node    *value;
238
239         if (is_Block(irn)) {
240                 /* the topological walker ensures that blocks are visited before anything else */
241                 alloc_blk_info(irn, env);
242                 return;
243         }
244         /* GVN step: remember the value */
245         value = add(irn, irn);
246
247         /* no need to put constants into the sets: they are always redundant */
248         if (! is_nice_value(irn) || is_irn_constlike(irn))
249                 return;
250
251         /* Do not put mode_T nodes info the sets, or PhiT will be created
252           (which are not allowed in Firm). Instead, put the Proj's here only. */
253         if (get_irn_mode(irn) == mode_T)
254                 return;
255
256         /* place this node into the set of possible nodes of its block */
257         block = get_nodes_block(irn);
258         info  = get_block_info(block);
259
260         ir_valueset_insert(info->exp_gen, value, irn);
261 }  /* topo_walker */
262
263 /**
264  * Computes Avail_out(block):
265  *
266  * Avail_in(block)  = Avail_out(dom(block))
267  * Avail_out(block) = Avail_in(block) \/ Nodes(block)
268  *
269  * Precondition:
270  *  This function must be called in the top-down dominance order:
271  *  Then, it computes Leader(Nodes(block)) instead of Nodes(block) !
272  *
273  * @param block   the block
274  * @param ctx     walker context
275  */
276 static void compute_avail_top_down(ir_node *block, void *ctx)
277 {
278         pre_env    *env = ctx;
279         block_info *dom_info;
280         block_info *info = get_block_info(block);
281         ir_node    *dom_blk;
282
283         /* we don't need the end block Avail */
284         if (block == env->end_block)
285                 return;
286
287         /*
288          * First add all nodes from the dominator.
289          * This must be done to ensure that Antic_out contains the leader
290          * for every node. The root has no dominator.
291          */
292         if (block != env->start_block) {
293                 dom_blk = get_Block_idom(block);
294                 assert(is_Block(dom_blk));
295
296                 dom_info = get_block_info(dom_blk);
297                 assert(dom_info);
298
299                 value_union(info->avail_out, dom_info->avail_out);
300         }
301         value_union(info->avail_out, info->exp_gen);
302
303         dump_value_set(info->avail_out, "Avail_out", block);
304 }  /* compute_avail_top_down */
305
306 /**
307  * check if a node n is clean in block block.
308  *
309  * @param n      the node
310  * @param block  the block
311  * @param set    a value set, containing the already processed predecessors
312  */
313 static int is_clean_in_block(ir_node *n, ir_node *block, ir_valueset_t *set) {
314         int i;
315
316         if (is_Phi(n))
317                 return 1;
318
319         if (! is_nice_value(n))
320                 return 0;
321
322         for (i = get_irn_arity(n) - 1; i >= 0; --i) {
323                 ir_node *pred = get_irn_n(n, i);
324                 ir_node *value;
325
326                 if (get_nodes_block(pred) != block)
327                         continue;
328
329                 if (is_Phi(pred))
330                         continue;
331
332                 if (! is_nice_value(pred))
333                         return 0;
334
335                 value = lookup(pred);
336                 if (! value)
337                         return 0;
338                 if (! ir_valueset_lookup(set, value))
339                         return 0;
340         }
341         return 1;
342 }  /* is_clean_in_block */
343
344 /**
345  * Implements phi_translate. Translate a expression above a Phi.
346  *
347  * @param node        the node
348  * @param block       the block in which the node is translated
349  * @param pos         the input number of the destination block
350  * @param translated  the valueset containing the other already translated nodes
351  *
352  * @return a node representing the translated value
353  */
354 static ir_node *phi_translate(ir_node *node, ir_node *block, int pos, ir_valueset_t *translated)
355 {
356         ir_node        *nn;
357         int            i, arity;
358
359         if (is_Phi(node)) {
360                 if (get_nodes_block(node) == block) {
361                         /* a Phi inside our block */
362                         return get_Phi_pred(node, pos);
363                 }
364                 /* already outside */
365                 return node;
366         }
367
368         arity = get_irn_intra_arity(node);
369
370         /* check if the node has at least one Phi predecessor */
371         for (i = 0; i < arity; ++i) {
372                 ir_node *pred    = get_irn_intra_n(node, i);
373                 ir_node *leader  = lookup(pred);
374                 ir_node *trans;
375
376                 leader = leader != NULL ? leader : pred;
377                 trans  = ir_valueset_lookup(translated, leader);
378
379                 if ((trans != NULL && trans != leader) || (is_Phi(leader) && get_nodes_block(leader) == block))
380                         break;
381         }
382         if (i >= arity) {
383                 /* no translation needed */
384                 return node;
385         }
386
387         nn = new_ir_node(
388                 get_irn_dbg_info(node),
389                 current_ir_graph,
390                 NULL,
391                 get_irn_op(node),
392                 get_irn_mode(node),
393                 arity,
394                 get_irn_in(node));
395         /* We need the attribute copy here, because the Hash value of a
396            node might depend on that. */
397         copy_node_attr(node, nn);
398
399         set_nodes_block(nn, get_nodes_block(node));
400         for (i = 0; i < arity; ++i) {
401                 ir_node *pred    = get_irn_intra_n(node, i);
402                 ir_node *leader  = lookup(pred);
403                 ir_node *trans;
404
405                 leader = leader != NULL ? leader : pred;
406                 trans  = ir_valueset_lookup(translated, leader);
407                 if (trans == NULL)
408                         trans = leader;
409
410                 if (is_Phi(trans) && get_nodes_block(trans) == block) {
411                         ir_node *trans_pred = get_Phi_pred(trans, pos);
412                         set_irn_n(nn, i, trans_pred);
413                 } else
414                         set_irn_n(nn, i, trans);
415         }
416         nn = optimize_node(nn);
417         return nn;
418 }  /* phi_translate */
419
420 /**
421  * Block-walker, computes Antic_in(block).
422  *
423  * @param block  the block
424  * @param ctx    the walker environment
425  */
426 static void compute_antic(ir_node *block, void *ctx) {
427         pre_env    *env = ctx;
428         block_info *succ_info;
429         block_info *info = get_block_info(block);
430         ir_node    *succ, *value, *expr;
431         size_t     size;
432         ir_valueset_iterator_t  iter;
433
434         /* no need for computations in start block */
435         if (block == env->start_block)
436                 return;
437
438         size = ir_valueset_size(info->antic_in);
439
440         /* the end block has no successor */
441         if (block != env->end_block) {
442                 int n_succ;
443
444                 /*
445                  * This step puts all generated expression from the current
446                  * current block into Antic_in.
447                  * It is enough to do this in the first iteration only, because
448                  * the set info->exp_gen is not changed anymore.
449                  */
450                 if (env->first_iter) {
451                         foreach_valueset(info->exp_gen, value, expr, iter) {
452                                 ir_valueset_insert(info->antic_in, value, expr);
453                         }
454                 }
455
456                 n_succ = get_Block_n_cfg_outs(block);
457                 if (n_succ == 1) {
458                         int i, pos = -1;
459
460                         /* find blocks position in succ's block predecessors */
461                         succ = get_Block_cfg_out(block, 0);
462                         for (i = get_Block_n_cfgpreds(succ) - 1; i >= 0; --i) {
463                                 if (get_Block_cfgpred_block(succ, i) == block) {
464                                         pos = i;
465                                         break;
466                                 }
467                         }
468                         assert(pos >= 0);
469
470                         succ_info = get_block_info(succ);
471                         /* translate into list: we cannot insert into a set we iterate
472                          * and succ might be equal to block for endless loops */
473                         foreach_valueset(succ_info->antic_in, value, expr, iter) {
474                                 ir_node *trans = phi_translate(expr, succ, pos, info->antic_in);
475
476                                 if (is_clean_in_block(trans, block, info->antic_in))
477                                         ir_valueset_insert(info->antic_in, value, trans);
478                         }
479                 } else { /* n_succ > 1 */
480                         ir_node    *succ0;
481                         block_info *succ0_info;
482                         int        i;
483
484                         assert(n_succ > 1);
485
486                         /* Select a successor to compute the disjoint of all Nodes
487                            sets, it might be useful to select the block with the
488                            smallest number of nodes.  For simplicity we choose the
489                            first one. */
490                         succ0      = get_Block_cfg_out(block, 0);
491                         succ0_info = get_block_info(succ0);
492                         foreach_valueset(succ0_info->antic_in, value, expr, iter) {
493                                 /* we need the disjoint */
494                                 for (i = 1; i < n_succ; ++i) {
495                                         ir_node *succ = get_Block_cfg_out(block, i);
496                                         block_info *succ_info = get_block_info(succ);
497                                         if (ir_valueset_lookup(succ_info->antic_in, value) == NULL)
498                                                 break;
499                                 }
500                                 if (i >= n_succ) {
501                                         /* we found a value that is common in all Antic_in(succ(b)),
502                                             put it in Antic_in(b) if the value is NOT already represented. */
503                                         if (is_clean_in_block(expr, block, info->antic_in))
504                                                 ir_valueset_insert(info->antic_in, value, expr);
505                                 }
506                         }
507                 }
508         }
509
510         /* we do not need a clean here, because we ensure that only cleaned nodes are in exp_gen
511          * and all other sets */
512
513         dump_value_set(info->antic_in, "Antic_in", block);
514         if (size != ir_valueset_size(info->antic_in)) {
515                 /* the Antic_in set has changed */
516                 env->changes |= 1;
517         }
518 }  /* compute_antic */
519
520 /**
521  * Perform insertion of partially redundant values.
522  * For every Block node, do the following:
523  * 1.  Propagate the NEW_SETS of the dominator into the current block.
524  * If the block has multiple predecessors,
525  *     2a. Iterate over the ANTIC expressions for the block to see if
526  *         any of them are partially redundant.
527  *     2b. If so, insert them into the necessary predecessors to make
528  *         the expression fully redundant.
529  *     2c. Insert a new Phi merging the values of the predecessors.
530  *     2d. Insert the new Phi, and the new expressions, into the
531  *         NEW_SETS set.
532  *
533  * @param block  the block
534  * @param ctx    the walker environment
535  */
536 static void insert_nodes(ir_node *block, void *ctx)
537 {
538         pre_env    *env = ctx;
539         ir_node    *value, *expr, *idom, *first_s, *worklist;
540         block_info *curr_info, *idom_info;
541         int        pos, arity = get_irn_intra_arity(block);
542         int        all_same, by_some, updated;
543         ir_valueset_iterator_t iter;
544
545         /* ensure that even the start block has a new_set */
546         curr_info = get_block_info(block);
547         if (curr_info->new_set)
548                 ir_valueset_del(curr_info->new_set);
549         curr_info->new_set = ir_valueset_new(16);
550
551         if (block == env->start_block)
552                 return;
553
554         idom      = get_Block_idom(block);
555         idom_info = get_block_info(idom);
556
557         /* update the new_sets */
558         updated = 0;
559         dump_value_set(idom_info->new_set, "[New Set]", idom);
560         foreach_valueset(idom_info->new_set, value, expr, iter) {
561                 ir_valueset_insert(curr_info->new_set, value, expr);
562                 updated |= ir_valueset_replace(curr_info->avail_out, value, expr);
563         }
564         if (updated) {
565                 dump_value_set(curr_info->avail_out, "Updated [Avail_out]", block);
566         }
567
568         if (arity <= 1)
569                 return;
570
571         /* convert the set into a list. This allows the removal of
572          * elements from the set */
573         worklist = NULL;
574         foreach_valueset(curr_info->antic_in, value, expr, iter) {
575                 ir_mode *mode;
576
577                 /* If the value was already computed in the dominator, then
578                    it is totally redundant.  Hence we have nothing to insert. */
579                 if (ir_valueset_lookup(idom_info->avail_out, value)) {
580                         //      DB((dbg, LEVEL_2, "Found %+F from block %+F avail in dom %+F\n", v, block, idom));
581                         continue;
582                 }
583
584                 by_some  = 0;
585                 all_same = 1;
586                 first_s  = NULL;
587                 mode     = NULL;
588
589                 /* for all predecessor blocks */
590                 for (pos = 0; pos < arity; ++pos) {
591                         block_info *pred_info;
592                         ir_node *pred_blk = get_Block_cfgpred_block(block, pos);
593                         ir_node *e_prime, *v_prime, *e_dprime;
594
595                         /* ignore bad blocks. */
596                         if (is_Bad(pred_blk))
597                                 continue;
598
599                         e_prime = phi_translate(expr, block, pos, curr_info->avail_out);
600                         v_prime = lookup(e_prime);
601                         if (v_prime == NULL)
602                                 v_prime = value;
603
604                         pred_info = get_block_info(pred_blk);
605                         e_dprime  = ir_valueset_lookup(pred_info->avail_out, v_prime);
606
607                         if (e_dprime == NULL) {
608                                 pred_info->avail     = e_prime;
609                                 pred_info->not_found = 1;
610                                 all_same = 0;
611                         } else {
612                                 pred_info->avail     = e_dprime;
613                                 pred_info->not_found = 0;
614                                 mode     = get_irn_mode(e_dprime);
615                                 e_dprime = e_dprime;
616                                 by_some  = 1;
617                                 if (first_s == NULL)
618                                         first_s = e_dprime;
619                                 else if (first_s != e_dprime)
620                                         all_same = 0;
621
622                                 DB((dbg, LEVEL_2, "Found %+F from block %+F as %+F in pred %+F\n", expr, block, e_dprime, pred_blk));
623                         }  /* if */
624                 }  /* for */
625
626                 /* If it's not the same value already existing along every predecessor, and
627                    it's defined by some predecessor, it is partially redundant. */
628                 if (! all_same && by_some) {
629                         ir_node *phi, *l, **in;
630
631                         DB((dbg, LEVEL_1, "Partial redundant %+F from block %+F found\n", expr, block));
632
633                         in = XMALLOCN(ir_node*, arity);
634                         /* for all predecessor blocks */
635                         for (pos = 0; pos < arity; ++pos) {
636                                 ir_node *pred_blk = get_Block_cfgpred_block(block, pos);
637                                 block_info *pred_info = get_block_info(pred_blk);
638
639                                 /* ignore bad blocks. */
640                                 if (is_Bad(pred_blk)) {
641                                         in[pos] = new_Bad();
642                                         continue;
643                                 }
644
645                                 /* ignore blocks that already have the expression */
646                                 if (pred_info->not_found) {
647                                         ir_node *e_prime = pred_info->avail;
648                                         ir_node *nn;
649                                         if (!is_Phi(e_prime)) {
650                                                 ir_node *proj_pred = NULL;
651                                                 if (is_Proj(e_prime)) {
652                                                         ir_node *pred = get_Proj_pred(e_prime);
653                                                         mode = get_irn_mode(pred);
654                                                         nn = new_ir_node(
655                                                                 get_irn_dbg_info(pred),
656                                                                 current_ir_graph, pred_blk,
657                                                                 get_irn_op(pred),
658                                                                 mode,
659                                                                 get_irn_arity(pred),
660                                                                 get_irn_in(pred) + 1);
661                                                         copy_node_attr(pred, nn);
662
663                                                         DB((dbg, LEVEL_1, "New node %+F in block %+F created\n", nn, pred_blk));
664                                                         proj_pred = nn;
665                                                 }
666                                                 mode = get_irn_mode(e_prime);
667                                                 nn = new_ir_node(
668                                                         get_irn_dbg_info(e_prime),
669                                                         current_ir_graph, pred_blk,
670                                                         get_irn_op(e_prime),
671                                                         mode,
672                                                         get_irn_arity(e_prime),
673                                                         get_irn_in(e_prime) + 1);
674                                                 copy_node_attr(e_prime, nn);
675                                                 if (proj_pred != NULL) {
676                                                         set_Proj_pred(nn, proj_pred);
677                                                 }
678
679                                                 DB((dbg, LEVEL_1, "New node %+F in block %+F created\n", nn, pred_blk));
680                                                 l = lookup(expr);
681                                                 if (l == NULL) {
682                                                         l = add(expr, value);
683                                                 }
684                                                 ir_valueset_insert(pred_info->avail_out, add(nn, l), nn);
685                                                 pred_info->avail = nn;
686                                         }
687                                 }
688                                 in[pos] = pred_info->avail;
689                         }  /* for */
690                         phi = new_r_Phi(current_ir_graph, block, arity, in, mode);
691                         l = lookup(expr);
692                         if (l == NULL) {
693                                 l = add(expr, value);
694                         }
695                         value = add(phi, l);
696                         ir_valueset_replace(curr_info->avail_out, value, phi);
697                         ir_valueset_insert(curr_info->new_set, value, phi);
698                         free(in);
699                         DB((dbg, LEVEL_1, "New %+F for redundant %+F created\n", phi, expr));
700                         ir_valueset_remove_iterator(curr_info->antic_in, &iter);
701                         env->changes |= 1;
702                 }  /* if */
703   }  /* node_set_foreach */
704 }  /* insert_nodes */
705
706 /**
707  * Walker, change nodes by its value if different.
708  *
709  * We cannot do the changes right here, as this would change
710  * the hash values of the nodes in the avail_out set!
711  *
712  * @param irn  the node
713  * @param ctx  the walker environment
714  */
715 static void eliminate(ir_node *irn, void *ctx) {
716         pre_env *env = ctx;
717
718         if (is_no_Block(irn)) {
719                 ir_node *block = get_nodes_block(irn);
720                 block_info *bl = get_block_info(block);
721                 ir_node *value = lookup(irn);
722
723                 if (value != NULL) {
724                         ir_node *expr = ir_valueset_lookup(bl->avail_out, value);
725
726                         if (expr != NULL && expr != irn) {
727                                 elim_pair *p = obstack_alloc(env->obst, sizeof(*p));
728
729                                 p->old_node = irn;
730                                 p->new_node = expr;
731                                 p->next     = env->pairs;
732                                 p->reason   = get_irn_idx(expr) >= env->last_idx ? FS_OPT_GVN_PARTLY : FS_OPT_GVN_FULLY;
733                                 env->pairs  = p;
734                         }
735                 }
736         }
737 }  /* eliminate */
738
739 /**
740  * Do all the recorded changes and optimize
741  * newly created Phi's.
742  *
743  * @param pairs  list of elimination pairs
744  */
745 static void eliminate_nodes(elim_pair *pairs) {
746         elim_pair *p;
747
748         for (p = pairs; p != NULL; p = p->next) {
749                 /* might be already changed */
750                 p->new_node = skip_Id(p->new_node);
751
752                 DB((dbg, LEVEL_2, "Replacing %+F by %+F\n", p->old_node, p->new_node));
753                 /*
754                  * PRE tends to create Phi(self, self, ... , x, self, self, ...)
755                  * which we can optimize here
756                  */
757                 if (is_Phi(p->new_node)) {
758                         int i;
759                         ir_node *res = NULL;
760
761                         for (i = get_irn_intra_arity(p->new_node) - 1; i >= 0; --i) {
762                                 ir_node *pred = get_irn_n(p->new_node, i);
763
764                                 if (pred != p->old_node) {
765                                         if (res) {
766                                                 res = NULL;
767                                                 break;
768                                         }
769                                         res = pred;
770                                 }
771                         }
772                         if (res) {
773                                 exchange(p->new_node, res);
774                                 p->new_node = res;
775                         }
776                 }
777                 DBG_OPT_GVN_PRE(p->old_node, p->new_node, p->reason);
778                 exchange(p->old_node, p->new_node);
779         }
780 }  /* eliminate_nodes */
781
782 /*
783  * Argh: Endless loops cause problems, because the
784  * insert algorithm did not terminate. We get translated nodes that
785  * references the origin. These nodes are translated again and again...
786  *
787  * The current fix is to use post-dominance. This simple ignores
788  * endless loops, ie we cannot optimize them.
789  */
790 void do_gvn_pre(ir_graph *irg)
791 {
792         struct obstack       obst;
793         pre_env              a_env;
794         optimization_state_t state;
795         block_info           *bl_info;
796         unsigned             antic_iter, insert_iter;
797         ir_node              *value, *expr;
798
799         /* register a debug mask */
800         FIRM_DBG_REGISTER(dbg, "firm.opt.gvn_pre");
801         firm_dbg_set_mask(dbg, 3);
802
803         /* edges will crash if enabled due to our allocate on other obstack trick */
804         edges_deactivate(irg);
805
806         value_table = new_identities();
807         ir_nodemap_init(&value_map);
808
809         obstack_init(&obst);
810         a_env.obst        = &obst;
811         a_env.list        = NULL;
812         a_env.start_block = get_irg_start_block(irg);
813         a_env.end_block   = get_irg_end_block(irg);
814         a_env.pairs       = NULL;
815
816         /* Move Proj's into the same block as their args,
817            else we would assign the result to wrong blocks */
818         normalize_proj_nodes(irg);
819
820         /* critical edges MUST be removed */
821         remove_critical_cf_edges(irg);
822
823         /* we need dominator for Antic_out calculation */
824         assure_doms(irg);
825         assure_postdoms(irg);
826         /* we get all nodes of a block by following outs */
827         assure_irg_outs(irg);
828
829         /*
830          * Switch on GCSE. We need it to correctly compute
831          * the value of a node, which is independent from
832          * its block.
833          */
834         save_optimization_state(&state);
835         set_opt_global_cse(1);
836
837         DB((dbg, LEVEL_1, "Doing GVN-PRE for %+F\n", irg));
838
839         /* allocate block info for all blocks */
840         irg_walk_blkwise_dom_top_down(irg, NULL, topo_walker, &a_env);
841
842         /* clean the exp_gen set. Doing this here saves the cleanup in the iteration. */
843         for (bl_info = a_env.list; bl_info != NULL; bl_info = bl_info->next) {
844                 ir_valueset_iterator_t iter;
845
846                 foreach_valueset(bl_info->exp_gen, value, expr, iter) {
847                         if (!is_clean_in_block(expr, bl_info->block, bl_info->exp_gen))
848                                 ir_valueset_remove_iterator(bl_info->exp_gen, &iter);
849                 }
850         }
851         /* compute the available value sets for all blocks */
852         dom_tree_walk_irg(irg, compute_avail_top_down, NULL, &a_env);
853
854         /* compute the anticipated value sets for all blocks */
855         antic_iter = 0;
856         a_env.first_iter = 1;
857
858         /* we use the visited flag to mark non-clean nodes */
859         inc_irg_visited(irg);
860         do {
861                 DB((dbg, LEVEL_1, "Antic_in Iteration %d starts ...\n", ++antic_iter));
862                 a_env.changes = 0;
863                 postdom_tree_walk_irg(irg, compute_antic, NULL, &a_env);
864                 a_env.first_iter = 0;
865                 DB((dbg, LEVEL_1, "------------------------\n"));
866         } while (a_env.changes != 0);
867
868         /* compute redundant expressions */
869         insert_iter = 0;
870         a_env.last_idx = get_irg_last_idx(irg);
871         do {
872                 DB((dbg, LEVEL_1, "Insert Iteration %d starts ...\n", ++insert_iter));
873                 a_env.changes = 0;
874                 dom_tree_walk_irg(irg, insert_nodes, NULL, &a_env);
875                 DB((dbg, LEVEL_1, "------------------------\n"));
876         } while (a_env.changes != 0);
877
878         /* last step: eliminate nodes */
879         irg_walk_graph(irg, NULL, eliminate, &a_env);
880         eliminate_nodes(a_env.pairs);
881
882         /* clean up: delete all sets */
883         for (bl_info = a_env.list; bl_info != NULL; bl_info = bl_info->next) {
884                 ir_valueset_del(bl_info->exp_gen);
885                 ir_valueset_del(bl_info->avail_out);
886                 ir_valueset_del(bl_info->antic_in);
887                 if (bl_info->new_set)
888                         ir_valueset_del(bl_info->new_set);
889         }
890         del_identities(value_table);
891         ir_nodemap_destroy(&value_map);
892         obstack_free(&obst, NULL);
893         value_table = NULL;
894
895         /* pin the graph again: This is needed due to the use of set_opt_global_cse(1) */
896         set_irg_pinned(irg, op_pin_state_pinned);
897         restore_optimization_state(&state);
898
899         if (a_env.pairs) {
900                 set_irg_outs_inconsistent(irg);
901                 set_irg_loopinfo_inconsistent(irg);
902         }
903 }  /* do_gvn_pre */