becopyopt: Replace is_Reg_Phi() by just is_Phi().
[libfirm] / ir / lower / lower_mode_b.c
index 36c87c6..e7dd474 100644 (file)
@@ -1,27 +1,12 @@
 /*
- * Copyright (C) 1995-2011 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.
+ * Copyright (C) 2012 University of Karlsruhe.
  */
 
 /**
  * @file
  * @brief       lower mode_b operations to something the backend can handle
  * @author      Matthias Braun, Christoph Mallon
- * @version     $Id$
  */
 #include "config.h"
 
 #include "irpass_t.h"
 #include "util.h"
 #include "array.h"
+#include "irgopt.h"
 
 typedef struct needs_lowering_t {
        ir_node *node;
        int      input;
 } needs_lowering_t;
 
-static const lower_mode_b_config_t *config;
-static needs_lowering_t            *needs_lowering;
+static ir_mode          *lowered_mode;
+static needs_lowering_t *needs_lowering;
 
 static ir_node *create_not(dbg_info *dbgi, ir_node *node)
 {
        ir_node   *block  = get_nodes_block(node);
-       ir_mode   *mode   = config->lowered_mode;
+       ir_mode   *mode   = lowered_mode;
        ir_tarval *tv_one = get_mode_one(mode);
        ir_graph  *irg    = get_irn_irg(node);
        ir_node   *one    = new_rd_Const(dbgi, irg, tv_one);
@@ -69,14 +55,18 @@ static ir_node *convert_to_modeb(ir_node *node)
 {
        ir_node   *block   = get_nodes_block(node);
        ir_graph  *irg     = get_irn_irg(node);
-       ir_mode   *mode    = config->lowered_mode;
+       ir_mode   *mode    = lowered_mode;
        ir_tarval *tv_zero = get_mode_null(mode);
        ir_node   *zero    = new_r_Const(irg, tv_zero);
        ir_node   *cmp     = new_r_Cmp(block, node, zero, ir_relation_less_greater);
        return cmp;
 }
 
-ir_node *ir_create_cond_set(ir_node *cond_value, ir_mode *dest_mode)
+/**
+ * implementation of create_set_func which produces a cond with control
+ * flow
+ */
+static ir_node *create_cond_set(ir_node *cond_value, ir_mode *dest_mode)
 {
        ir_node  *lower_block = part_block_edges(cond_value);
        ir_node  *upper_block = get_nodes_block(cond_value);
@@ -106,7 +96,7 @@ static ir_node *lower_node(ir_node *node)
 {
        dbg_info *dbgi  = get_irn_dbg_info(node);
        ir_node  *block = get_nodes_block(node);
-       ir_mode  *mode  = config->lowered_mode;
+       ir_mode  *mode  = lowered_mode;
        ir_node  *res   = (ir_node*)get_irn_link(node);
        ir_graph *irg;
 
@@ -140,7 +130,7 @@ static ir_node *lower_node(ir_node *node)
 
                for (i = 0; i < arity; ++i) {
                        ir_node *in         = get_irn_n(node, i);
-                       ir_node *lowered_in = is_Bad(in) ? in : lower_node(in);
+                       ir_node *lowered_in = lower_node(in);
 
                        set_irn_n(new_phi, i, lowered_in);
                }
@@ -190,65 +180,9 @@ static ir_node *lower_node(ir_node *node)
                break;
        }
 
-       case iro_Cmp: {
-               ir_node    *left     = get_Cmp_left(node);
-               ir_node    *right    = get_Cmp_right(node);
-               ir_mode    *cmp_mode = get_irn_mode(left);
-               ir_relation relation = get_Cmp_relation(node);
-
-               if ((mode_is_int(cmp_mode) || mode_is_reference(cmp_mode)) &&
-                       (get_mode_size_bits(cmp_mode) < get_mode_size_bits(mode) ||
-                       (mode_is_signed(cmp_mode) && is_Const(right) && is_Const_null(right) && relation != ir_relation_greater))) {
-                       int         need_not = 0;
-                       ir_node    *a        = NULL;
-                       ir_node    *b        = NULL;
-                       int         bits;
-                       ir_tarval  *tv;
-                       ir_node    *shift_cnt;
-
-                       if (relation == ir_relation_less) {
-                               /* a < b  ->  (a - b) >> 31 */
-                               a = left;
-                               b = right;
-                       } else if (relation == ir_relation_less_equal) {
-                               /* a <= b  -> ~(a - b) >> 31 */
-                               a        = right;
-                               b        = left;
-                               need_not = 1;
-                       } else if (relation == ir_relation_greater) {
-                               /* a > b   -> (b - a) >> 31 */
-                               a = right;
-                               b = left;
-                       } else if (relation == ir_relation_greater_equal) {
-                               /* a >= b   -> ~(a - b) >> 31 */
-                               a        = left;
-                               b        = right;
-                               need_not = 1;
-                       } else {
-                               goto synth_zero_one;
-                       }
-
-                       bits      = get_mode_size_bits(mode);
-                       tv        = new_tarval_from_long(bits-1, mode_Iu);
-                       shift_cnt = new_rd_Const(dbgi, irg, tv);
-
-                       if (cmp_mode != mode) {
-                               a = new_rd_Conv(dbgi, block, a, mode);
-                               b = new_rd_Conv(dbgi, block, b, mode);
-                       }
-
-                       res = new_rd_Sub(dbgi, block, a, b, mode);
-                       if (need_not) {
-                               res = new_rd_Not(dbgi, block, res, mode);
-                       }
-                       res = new_rd_Shr(dbgi, block, res, shift_cnt, mode);
-               } else {
-                       /* synthesize the 0/1 value */
-synth_zero_one:
-                       res = config->create_set(node);
-               }
+       case iro_Cmp:
+               res = create_cond_set(node, mode);
                break;
-       }
 
        case iro_Const: {
                ir_tarval *tv = get_Const_tarval(node);
@@ -268,6 +202,10 @@ synth_zero_one:
                res = new_r_Unknown(irg, mode);
                break;
 
+       case iro_Bad:
+               res = new_r_Bad(irg, mode);
+               break;
+
        default:
                panic("Don't know how to lower mode_b node %+F", node);
        }
@@ -284,7 +222,7 @@ static bool needs_mode_b_input(const ir_node *node, int input)
 
 /**
  * Collects "roots" of a mode_b calculation. These are nodes which require a
- * mode_b input (Cond, Mux, Conv(xxx_b))
+ * mode_b input (Cond, Mux)
  */
 static void collect_needs_lowering(ir_node *node, void *env)
 {
@@ -292,12 +230,12 @@ static void collect_needs_lowering(ir_node *node, void *env)
        int i;
        (void) env;
 
-       /* if the node produces mode_b then it is not a root (but should be
+       /* if the node produces mode_b then it is not a root (but should be
         * something our lower_node function can handle) */
        if (get_irn_mode(node) == mode_b) {
                assert(is_And(node) || is_Or(node) || is_Eor(node) || is_Phi(node)
                       || is_Not(node) || is_Mux(node) || is_Cmp(node)
-                      || is_Const(node) || is_Unknown(node));
+                      || is_Const(node) || is_Unknown(node) || is_Bad(node));
                return;
        }
 
@@ -315,17 +253,18 @@ static void collect_needs_lowering(ir_node *node, void *env)
        }
 }
 
-void ir_lower_mode_b(ir_graph *irg, const lower_mode_b_config_t *nconfig)
+void ir_lower_mode_b(ir_graph *const irg, ir_mode *const nlowered_mode)
 {
        size_t i;
        size_t n;
 
-       config = nconfig;
+       lowered_mode = nlowered_mode;
 
        /* edges are used by part_block_edges in the ir_create_cond_set variant. */
-       edges_assure(irg);
+       assure_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUT_EDGES
+                                | IR_GRAPH_PROPERTY_NO_TUPLES);
 
-       set_irg_state(irg, IR_GRAPH_STATE_MODEB_LOWERED);
+       add_irg_constraints(irg, IR_GRAPH_CONSTRAINT_MODEB_LOWERED);
        ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK);
 
        needs_lowering = NEW_ARR_F(needs_lowering_t, 0);
@@ -349,10 +288,5 @@ void ir_lower_mode_b(ir_graph *irg, const lower_mode_b_config_t *nconfig)
 
        DEL_ARR_F(needs_lowering);
 
-       if (n > 0) {
-               /* lowering might create new blocks, so be sure to handle this */
-               set_irg_extblk_inconsistent(irg);
-               clear_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_DOMINANCE);
-               edges_deactivate(irg);
-       }
+       confirm_irg_properties(irg, n > 0 ? IR_GRAPH_PROPERTIES_NONE : IR_GRAPH_PROPERTIES_ALL);
 }