Loop inversion does not fail the given test cases but is still 'dumb'.
[libfirm] / ir / opt / gvn_pre.c
index 5e35e27..a91b703 100644 (file)
  *          (VanDrunen Hosking 2004)
  * @author  Michael Beck
  * @version $Id$
- * @summary
+ * @brief
  */
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
 
 #include "irflag.h"
 #include "irdom.h"
@@ -42,6 +40,7 @@
 #include "iredges.h"
 #include "iropt_dbg.h"
 #include "debug.h"
+#include "irpass.h"
 
 #include "irgraph_t.h"
 #include "irnode_t.h"
@@ -76,7 +75,7 @@ typedef struct pre_env {
        struct obstack *obst;   /**< The obstack to allocate on. */
        ir_node *start_block;   /**< The start block of the current graph. */
        ir_node *end_block;     /**< The end block of the current graph */
-       block_info *list;       /**< Links all block info entires for easier recovery. */
+       block_info *list;       /**< Links all block info entries for easier recovery. */
        elim_pair *pairs;       /**< A list of node pairs that must be eliminated. */
        unsigned last_idx;      /**< last node index of "old" nodes, all higher indexes are newly created once. */
        char changes;           /**< Non-zero, if calculation of Antic_in has changed. */
@@ -121,7 +120,7 @@ static ir_node *add(ir_node *e, ir_node *v)
 
                if (v_pred != pred) {
                        /* must create a new value here */
-                       v = new_r_Proj(current_ir_graph, get_nodes_block(v_pred), v_pred, get_irn_mode(v), get_Proj_proj(v));
+                       v = new_r_Proj(get_nodes_block(v_pred), v_pred, get_irn_mode(v), get_Proj_proj(v));
                }
        }
        v = identify_remember(value_table, v);
@@ -161,7 +160,7 @@ static block_info *get_block_info(ir_node *block) {
  * @param env     the environment
  */
 static void alloc_blk_info(ir_node *block, pre_env *env) {
-       block_info *info = obstack_alloc(env->obst, sizeof(*info));
+       block_info *info = OALLOC(env->obst, block_info);
 
        set_irn_link(block, info);
        info->exp_gen   = ir_valueset_new(16);
@@ -456,16 +455,11 @@ static void compute_antic(ir_node *block, void *ctx) {
 
                n_succ = get_Block_n_cfg_outs(block);
                if (n_succ == 1) {
-                       int i, pos = -1;
+                       int pos = -1;
 
                        /* find blocks position in succ's block predecessors */
                        succ = get_Block_cfg_out(block, 0);
-                       for (i = get_Block_n_cfgpreds(succ) - 1; i >= 0; --i) {
-                               if (get_Block_cfgpred_block(succ, i) == block) {
-                                       pos = i;
-                                       break;
-                               }
-                       }
+                       pos  = get_Block_cfgpred_pos(succ, block);
                        assert(pos >= 0);
 
                        succ_info = get_block_info(succ);
@@ -688,7 +682,7 @@ static void insert_nodes(ir_node *block, void *ctx)
                                }
                                in[pos] = pred_info->avail;
                        }  /* for */
-                       phi = new_r_Phi(current_ir_graph, block, arity, in, mode);
+                       phi = new_r_Phi(block, arity, in, mode);
                        l = lookup(expr);
                        if (l == NULL) {
                                l = add(expr, value);
@@ -725,7 +719,7 @@ static void eliminate(ir_node *irn, void *ctx) {
                        ir_node *expr = ir_valueset_lookup(bl->avail_out, value);
 
                        if (expr != NULL && expr != irn) {
-                               elim_pair *p = obstack_alloc(env->obst, sizeof(*p));
+                               elim_pair *p = OALLOC(env->obst, elim_pair);
 
                                p->old_node = irn;
                                p->new_node = expr;
@@ -786,7 +780,7 @@ static void eliminate_nodes(elim_pair *pairs) {
  * references the origin. These nodes are translated again and again...
  *
  * The current fix is to use post-dominance. This simple ignores
- * endless loops, ie we cannot optimize them.
+ * endless loops, i.e. we cannot optimize them.
  */
 void do_gvn_pre(ir_graph *irg)
 {
@@ -799,7 +793,6 @@ void do_gvn_pre(ir_graph *irg)
 
        /* register a debug mask */
        FIRM_DBG_REGISTER(dbg, "firm.opt.gvn_pre");
-       firm_dbg_set_mask(dbg, 3);
 
        /* edges will crash if enabled due to our allocate on other obstack trick */
        edges_deactivate(irg);
@@ -829,7 +822,8 @@ void do_gvn_pre(ir_graph *irg)
 
        /*
         * Switch on GCSE. We need it to correctly compute
-        * the leader of a node by hashing.
+        * the value of a node, which is independent from
+        * its block.
         */
        save_optimization_state(&state);
        set_opt_global_cse(1);
@@ -837,7 +831,7 @@ void do_gvn_pre(ir_graph *irg)
        DB((dbg, LEVEL_1, "Doing GVN-PRE for %+F\n", irg));
 
        /* allocate block info for all blocks */
-       irg_walk_blkwise_graph(irg, NULL, topo_walker, &a_env);
+       irg_walk_blkwise_dom_top_down(irg, NULL, topo_walker, &a_env);
 
        /* clean the exp_gen set. Doing this here saves the cleanup in the iteration. */
        for (bl_info = a_env.list; bl_info != NULL; bl_info = bl_info->next) {
@@ -899,6 +893,11 @@ void do_gvn_pre(ir_graph *irg)
        if (a_env.pairs) {
                set_irg_outs_inconsistent(irg);
                set_irg_loopinfo_inconsistent(irg);
-
        }
 }  /* do_gvn_pre */
+
+/* Creates an ir_graph pass for do_gvn_pre. */
+ir_graph_pass_t *do_gvn_pre_pass(const char *name)
+{
+       return def_graph_pass(name ? name : "gvn_pre", do_gvn_pre);
+}  /* do_gvn_pre_pass */