Slimified the bitset implementation a little bit
[libfirm] / ir / ana / irconsconfirm.c
index f33a716..eb5a354 100644 (file)
@@ -1,28 +1,41 @@
 /*
- * Project:     libFIRM
- * File name:   ir/ana/irconsconfirm.c
- * Purpose:     Construction of Confirm nodes
- * Author:      Michael Beck
- * Modified by:
- * Created:     6.2005
- * CVS-ID:      $Id$
- * Copyright:   (C) 2002-2005 Universität Karlsruhe
- * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+ * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
+ *
+ * This file is part of libFirm.
+ *
+ * This file may be distributed and/or modified under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * Licensees holding valid libFirm Professional Edition licenses may use
+ * this file in accordance with the libFirm Commercial License.
+ * Agreement provided with the Software.
+ *
+ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE.
  */
 
 /**
- * @file irconsconfirm.c
- *
- * Construction of Confirm nodes
- *
- * @author Michael Beck
+ * @file
+ * @brief    Construction of Confirm nodes
+ * @author   Michael Beck
+ * @date     6.2005
+ * @version  $Id$
  */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
 #include "irgraph_t.h"
 #include "irnode_t.h"
 #include "ircons_t.h"
 #include "irgmod.h"
 #include "iropt_dbg.h"
 #include "iredges_t.h"
+#include "irgwalk.h"
+#include "irprintf.h"
 
 /**
  * Walker environment.
@@ -33,12 +46,30 @@ typedef struct _env_t {
   unsigned num_eq;        /**< number of equalities placed */
 } env_t;
 
+/**
+ * Return the effective use block of a node and it's predecessor on
+ * position pos.
+ *
+ * @param node  the node
+ * @param pos   the position of the used input
+ *
+ * This handles correctly Phi nodes.
+ */
+static ir_node *get_effective_use_block(ir_node *node, int pos)
+{
+  /* the effective use of a Phi is in its predecessor block */
+  if (is_Phi(node))
+    return get_nodes_block(get_irn_n(node, pos));
+  else
+    return get_nodes_block(node);
+}
+
 /**
  * Handle a CASE-branch.
  *
  * @param block   the block which is entered by the branch
  * @param irn     the node expressing the switch value
- * @param pnc     the branch label
+ * @param nr      the branch label
  * @param env     statistical environment
  *
  * Branch labels are a simple case. We can replace the value
@@ -46,13 +77,16 @@ typedef struct _env_t {
  */
 static void handle_case(ir_node *block, ir_node *irn, long nr, env_t *env)
 {
-  int pos;
   const ir_edge_t *edge, *next;
   ir_node *c = NULL;
 
+  if (is_Bad(irn))
+    return;
+
   for (edge = get_irn_out_edge_first(irn); edge; edge = next) {
     ir_node *succ = get_edge_src_irn(edge);
-    ir_node *blk = get_nodes_block(succ);
+    int     pos   = get_edge_src_pos(edge);
+    ir_node *blk  = get_effective_use_block(succ, pos);
 
     next = get_irn_out_edge_next(irn, edge);
 
@@ -66,19 +100,19 @@ static void handle_case(ir_node *block, ir_node *irn, long nr, env_t *env)
 
       if (! c) {
         ir_mode *mode = get_irn_mode(irn);
-        type *tp      = get_irn_type(irn);
+        ir_type *tp   = get_irn_type(irn);
         tarval *tv    = new_tarval_from_long(nr, mode);
         c = new_r_Const_type(current_ir_graph, block, mode, tv, tp);
       }
 
-      pos = get_edge_src_pos(edge);
       set_irn_n(succ, pos, c);
       DBG_OPT_CONFIRM_C(irn, c);
+//      ir_printf("1 Replacing input %d of node %n with %n\n", pos, succ, c);
 
       env->num_consts += 1;
     }
   }
-}
+}  /* handle_case */
 
 /**
  * Handle an IF-branch.
@@ -92,14 +126,22 @@ static void handle_if(ir_node *block, ir_node *cmp, pn_Cmp pnc, env_t *env)
 {
   ir_node *left  = get_Cmp_left(cmp);
   ir_node *right = get_Cmp_right(cmp);
+  ir_op *op;
   const ir_edge_t *edge, *next;
 
-  /* remove unordered if it's an integer compare */
-  if (mode_is_int(get_irn_mode(left)))
-    pnc &= ~pn_Cmp_Uo;
+  /* Beware of Bads */
+  if (is_Bad(left) ||is_Bad(right))
+    return;
 
-  /* try to place the constant on the right side */
-  if (get_irn_op(left) == op_Const) {
+  op = get_irn_op(left);
+
+  /* Do not create Confirm nodes for Cmp(Const, Const) constructs.
+     These are removed anyway */
+  if (op == op_Const && is_Const(right))
+    return;
+
+  /* try to place the constant on the right side for a Confirm */
+  if (op == op_Const || op == op_SymConst) {
     ir_node *t = left;
 
     left  = right;
@@ -110,57 +152,57 @@ static void handle_if(ir_node *block, ir_node *cmp, pn_Cmp pnc, env_t *env)
 
   /*
    * First case: both values are identical.
-   * replace the left one by the right one.
+   * replace the left one by the right (potentially const) one.
    */
   if (pnc == pn_Cmp_Eq) {
-    int pos;
-
     for (edge = get_irn_out_edge_first(left); edge; edge = next) {
       ir_node *succ = get_edge_src_irn(edge);
-      ir_node *blk = get_nodes_block(succ);
+      int     pos   = get_edge_src_pos(edge);
+      ir_node *blk  = get_effective_use_block(succ, pos);
 
       next = get_irn_out_edge_next(left, edge);
       if (block_dominates(block, blk)) {
         /*
-         * Ok, we found a user of left that is placed
-         * in a block dominated by the branch block.
+         * Ok, we found a usage of left in a block
+         * dominated by the branch block.
          * We can replace the input with right.
          */
-        pos = get_edge_src_pos(edge);
         set_irn_n(succ, pos, right);
         DBG_OPT_CONFIRM(left, right);
 
+//        ir_printf("2 Replacing input %d of node %n with %n\n", pos, succ, right);
+
         env->num_eq += 1;
       }
     }
   }
-  else { /* not == cases */
-    int pos;
+  else { /* not pn_Cmp_Eq cases */
     ir_node *c = NULL;
 
     for (edge = get_irn_out_edge_first(left); edge; edge = next) {
       ir_node *succ = get_edge_src_irn(edge);
-      ir_node *blk = get_nodes_block(succ);
+      int     pos   = get_edge_src_pos(edge);
+      ir_node *blk  = get_effective_use_block(succ, pos);
 
       next = get_irn_out_edge_next(left, edge);
       if (block_dominates(block, blk)) {
         /*
-         * Ok, we found a user of left that is placed
-         * in a block dominated by the branch block.
+         * Ok, we found a usage of left in a block
+         * dominated by the branch block.
          * We can replace the input with a Confirm(left, pnc, right).
          */
-
         if (! c)
           c = new_r_Confirm(current_ir_graph, block, left, right, pnc);
 
         pos = get_edge_src_pos(edge);
         set_irn_n(succ, pos, c);
+//        ir_printf("3 Replacing input %d of node %n with %n\n", pos, succ, c);
 
         env->num_confirms += 1;
       }
     }
   }
-}
+}  /* handle_if */
 
 /**
  * Pre-walker: Called for every block to insert Confirm nodes
@@ -172,7 +214,7 @@ static void insert_Confirm(ir_node *block, void *env)
 
   /*
    * we can only handle blocks with only ONE control flow
-   * predecessor
+   * predecessor yet.
    */
   if (get_Block_n_cfgpreds(block) != 1)
     return;
@@ -206,6 +248,8 @@ static void insert_Confirm(ir_node *block, void *env)
       /* it's the false branch */
       pnc = get_negated_pnc(pnc, mode);
     }
+//    ir_printf("At %n using %n Confirm %=\n", block, cmp, pnc);
+
     handle_if(block, cmp, pnc, env);
   }
   else if (mode_is_int(mode)) {
@@ -217,7 +261,7 @@ static void insert_Confirm(ir_node *block, void *env)
 
     handle_case(block, get_Cond_selector(cond), proj_nr, env);
   }
-}
+}  /* insert_Confirm */
 
 /*
  * Construct Confirm nodes
@@ -227,10 +271,11 @@ void construct_confirms(ir_graph *irg)
   env_t env;
   int edges_active = edges_activated(irg);
 
-  if (get_irg_dom_state(irg) != dom_consistent) {
-    /* we need dominance info */
-    compute_doms(irg);
-  }
+  /* we need dominance info */
+  assure_doms(irg);
+
+  assert(get_irg_pinned(irg) == op_pin_state_pinned &&
+    "Nodes must be placed to insert Confirms");
 
   if (! edges_active) {
     /* We need edges */
@@ -261,20 +306,29 @@ void construct_confirms(ir_graph *irg)
   /* deactivate edges if they where off */
   if (! edges_active)
     edges_deactivate(irg);
-}
+}  /* construct_confirms */
 
 /**
- * Post-walker: Remove COnfirm nodes
+ * Post-walker: Remove Confirm nodes
  */
 static void rem_Confirm(ir_node *n, void *env) {
   if (get_irn_op(n) == op_Confirm) {
-    exchange(n, get_Confirm_value(n));
+    ir_node *value = get_Confirm_value(n);
+    if (value != n)
+      exchange(n, value);
+    else {
+      /*
+       * Strange: a Confirm is it's own bound. This can happen
+       * in dead blocks when Phi nodes are already removed.
+       */
+      exchange(n, new_Bad());
+    }
   }
-}
+}  /* rem_Confirm */
 
 /*
  * Remove all Confirm nodes from a graph.
  */
 void remove_confirms(ir_graph *irg) {
   irg_walk_graph(irg, NULL, rem_Confirm, NULL);
-}
+}  /* remove_confirms */