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