verify: Clarify assertion message.
[libfirm] / ir / ir / iropt.c
index 02c3a4b..348f93e 100644 (file)
@@ -51,6 +51,7 @@
 #include "bitfiddle.h"
 #include "be.h"
 #include "error.h"
+#include "firmstat_t.h"
 
 #include "entity_t.h"
 
@@ -181,48 +182,6 @@ static ir_tarval *computed_value_Sub(const ir_node *n)
        return tarval_bad;
 }
 
-/**
- * Return the value of a Carry.
- * Special : a op 0, 0 op b
- */
-static ir_tarval *computed_value_Carry(const ir_node *n)
-{
-       ir_node   *a  = get_binop_left(n);
-       ir_node   *b  = get_binop_right(n);
-       ir_mode   *m  = get_irn_mode(n);
-       ir_tarval *ta = value_of(a);
-       ir_tarval *tb = value_of(b);
-
-       if ((ta != tarval_bad) && (tb != tarval_bad)) {
-               tarval_add(ta, tb);
-               return tarval_carry() ? get_mode_one(m) : get_mode_null(m);
-       } else {
-               if (tarval_is_null(ta) || tarval_is_null(tb))
-                       return get_mode_null(m);
-       }
-       return tarval_bad;
-}
-
-/**
- * Return the value of a Borrow.
- * Special : a op 0
- */
-static ir_tarval *computed_value_Borrow(const ir_node *n)
-{
-       ir_node   *a  = get_binop_left(n);
-       ir_node   *b  = get_binop_right(n);
-       ir_mode   *m  = get_irn_mode(n);
-       ir_tarval *ta = value_of(a);
-       ir_tarval *tb = value_of(b);
-
-       if ((ta != tarval_bad) && (tb != tarval_bad)) {
-               return tarval_cmp(ta, tb) == ir_relation_less ? get_mode_one(m) : get_mode_null(m);
-       } else if (tarval_is_null(ta)) {
-               return get_mode_null(m);
-       }
-       return tarval_bad;
-}
-
 /**
  * Return the value of an unary Minus.
  */
@@ -1234,56 +1193,6 @@ static ir_node *equivalent_node_Proj_CopyB(ir_node *proj)
        return proj;
 }
 
-/**
- * Optimize Bounds(idx, idx, upper) into idx.
- */
-static ir_node *equivalent_node_Proj_Bound(ir_node *proj)
-{
-       ir_node *oldn  = proj;
-       ir_node *bound = get_Proj_pred(proj);
-       ir_node *idx   = get_Bound_index(bound);
-       ir_node *pred  = skip_Proj(idx);
-       int ret_tuple  = 0;
-
-       if (idx == get_Bound_lower(bound))
-               ret_tuple = 1;
-       else if (is_Bound(pred)) {
-               /*
-                * idx was Bounds checked previously, it is still valid if
-                * lower <= pred_lower && pred_upper <= upper.
-                */
-               ir_node *lower = get_Bound_lower(bound);
-               ir_node *upper = get_Bound_upper(bound);
-               if (get_Bound_lower(pred) == lower &&
-                       get_Bound_upper(pred) == upper) {
-                       /*
-                        * One could expect that we simply return the previous
-                        * Bound here. However, this would be wrong, as we could
-                        * add an exception Proj to a new location then.
-                        * So, we must turn in into a tuple.
-                        */
-                       ret_tuple = 1;
-               }
-       }
-       if (ret_tuple) {
-               /* Turn Bound into a tuple (mem, jmp, bad, idx) */
-               switch (get_Proj_proj(proj)) {
-               case pn_Bound_M:
-                       DBG_OPT_EXC_REM(proj);
-                       proj = get_Bound_mem(bound);
-                       break;
-               case pn_Bound_res:
-                       proj = idx;
-                       DBG_OPT_ALGSIM0(oldn, proj, FS_OPT_NOP);
-                       break;
-               default:
-                       /* cannot optimize pn_Bound_X_regular, handled in transform ... */
-                       break;
-               }
-       }
-       return proj;
-}
-
 /**
  * Does all optimizations on nodes that must be done on its Projs
  * because of creating new nodes.
@@ -2167,7 +2076,6 @@ static ir_node *transform_node_bitop_shift(ir_node *n)
                return n;
        }
 
-       irg       = get_irn_irg(n);
        block     = get_nodes_block(n);
        dbg_bitop = get_irn_dbg_info(n);
        dbg_shift = get_irn_dbg_info(left);
@@ -2726,26 +2634,6 @@ restart:
                }
                DBG_OPT_ALGSIM0(oldn, n, FS_OPT_SUB_TO_ADD);
                return n;
-#if 0
-       } else if (is_Mul(b)) { /* a - (b * C) -> a + (b * -C) */
-               ir_node *m_right = get_Mul_right(b);
-               if (is_Const(m_right)) {
-                       ir_node *cnst2 = const_negate(m_right);
-                       if (cnst2 != NULL) {
-                               dbg_info *m_dbg   = get_irn_dbg_info(b);
-                               ir_node  *m_block = get_nodes_block(b);
-                               ir_node  *m_left  = get_Mul_left(b);
-                               ir_mode  *m_mode  = get_irn_mode(b);
-                               ir_node  *mul     = new_rd_Mul(m_dbg, m_block, m_left, cnst2, m_mode);
-                               dbg_info *a_dbg   = get_irn_dbg_info(n);
-                               ir_node  *a_block = get_nodes_block(n);
-
-                               n = new_rd_Add(a_dbg, a_block, a, mul, mode);
-                               DBG_OPT_ALGSIM0(oldn, n, FS_OPT_SUB_TO_ADD);
-                               return n;
-                       }
-               }
-#endif
        }
 
        /* Beware of Sub(P, P) which cannot be optimized into a simple Minus ... */
@@ -3164,34 +3052,22 @@ static ir_node *transform_node_Div(ir_node *n)
                assert(mode_is_float(mode));
 
                /* Optimize x/c to x*(1/c) */
-               if (get_mode_arithmetic(mode) == irma_ieee754) {
-                       ir_tarval *tv = value_of(b);
+               ir_tarval *tv = value_of(b);
 
-                       if (tv != tarval_bad) {
-                               int rem = tarval_fp_ops_enabled();
+               if (tv != tarval_bad) {
+                       tv = tarval_div(get_mode_one(mode), tv);
 
-                               /*
-                                * Floating point constant folding might be disabled here to
-                                * prevent rounding.
-                                * However, as we check for exact result, doing it is safe.
-                                * Switch it on.
-                                */
-                               tarval_enable_fp_ops(1);
-                               tv = tarval_div(get_mode_one(mode), tv);
-                               tarval_enable_fp_ops(rem);
-
-                               /* Do the transformation if the result is either exact or we are
-                                  not using strict rules. */
-                               if (tv != tarval_bad &&
-                                       (tarval_ieee754_get_exact() || (get_irg_fp_model(get_irn_irg(n)) & fp_strict_algebraic) == 0)) {
-                                       ir_node  *block = get_nodes_block(n);
-                                       ir_graph *irg   = get_irn_irg(block);
-                                       ir_node  *c     = new_r_Const(irg, tv);
-                                       dbg_info *dbgi  = get_irn_dbg_info(n);
-                                       value = new_rd_Mul(dbgi, block, a, c, mode);
+                       /* Do the transformation if the result is either exact or we are
+                          not using strict rules. */
+                       if (tv != tarval_bad &&
+                               (tarval_ieee754_get_exact() || (get_irg_fp_model(get_irn_irg(n)) & fp_strict_algebraic) == 0)) {
+                               ir_node  *block = get_nodes_block(n);
+                               ir_graph *irg   = get_irn_irg(block);
+                               ir_node  *c     = new_r_Const(irg, tv);
+                               dbg_info *dbgi  = get_irn_dbg_info(n);
+                               value = new_rd_Mul(dbgi, block, a, c, mode);
 
-                                       goto make_tuple;
-                               }
+                               goto make_tuple;
                        }
                }
        }
@@ -3208,11 +3084,13 @@ make_tuple:
 
                /* skip a potential Pin */
                mem = skip_Pin(mem);
-               turn_into_tuple(n, pn_Div_max+1);
-               set_Tuple_pred(n, pn_Div_M,         mem);
-               set_Tuple_pred(n, pn_Div_X_regular, new_r_Jmp(blk));
-               set_Tuple_pred(n, pn_Div_X_except,  new_r_Bad(irg, mode_X));
-               set_Tuple_pred(n, pn_Div_res,       value);
+               ir_node *const in[] = {
+                       [pn_Div_M]         = mem,
+                       [pn_Div_res]       = value,
+                       [pn_Div_X_regular] = new_r_Jmp(blk),
+                       [pn_Div_X_except]  = new_r_Bad(irg, mode_X),
+               };
+               turn_into_tuple(n, ARRAY_SIZE(in), in);
        }
        return n;
 }
@@ -3300,11 +3178,13 @@ make_tuple:
 
                /* skip a potential Pin */
                mem = skip_Pin(mem);
-               turn_into_tuple(n, pn_Mod_max+1);
-               set_Tuple_pred(n, pn_Mod_M,         mem);
-               set_Tuple_pred(n, pn_Mod_X_regular, new_r_Jmp(blk));
-               set_Tuple_pred(n, pn_Mod_X_except,  new_r_Bad(irg, mode_X));
-               set_Tuple_pred(n, pn_Mod_res,       value);
+               ir_node *const in[] = {
+                       [pn_Mod_M]         = mem,
+                       [pn_Mod_res]       = value,
+                       [pn_Mod_X_regular] = new_r_Jmp(blk),
+                       [pn_Mod_X_except]  = new_r_Bad(irg, mode_X),
+               };
+               turn_into_tuple(n, ARRAY_SIZE(in), in);
        }
        return n;
 }
@@ -3320,7 +3200,6 @@ static ir_node *transform_node_Cond(ir_node *n)
        ir_node   *a   = get_Cond_selector(n);
        ir_graph  *irg = get_irn_irg(n);
        ir_tarval *ta;
-       ir_node   *jmp;
 
        /* we need block info which is not available in floating irgs */
        if (get_irg_pinned(irg) == op_pin_state_floats)
@@ -3333,21 +3212,18 @@ static ir_node *transform_node_Cond(ir_node *n)
                ta = compute_cmp_ext(a);
        }
 
-       if (ta != tarval_bad && get_irn_mode(a) == mode_b) {
-               /* It's a boolean Cond, branching on a boolean constant.
+       if (ta != tarval_bad) {
+               /* It's branching on a boolean constant.
                   Replace it by a tuple (Bad, Jmp) or (Jmp, Bad) */
-               ir_node *blk = get_nodes_block(n);
-               jmp = new_r_Jmp(blk);
-               turn_into_tuple(n, pn_Cond_max+1);
-               if (ta == tarval_b_true) {
-                       set_Tuple_pred(n, pn_Cond_false, new_r_Bad(irg, mode_X));
-                       set_Tuple_pred(n, pn_Cond_true, jmp);
-               } else {
-                       set_Tuple_pred(n, pn_Cond_false, jmp);
-                       set_Tuple_pred(n, pn_Cond_true, new_r_Bad(irg, mode_X));
-               }
-               /* We might generate an endless loop, so keep it alive. */
-               add_End_keepalive(get_irg_end(irg), blk);
+               ir_node *const blk  = get_nodes_block(n);
+               ir_node *const jmp  = new_r_Jmp(blk);
+               ir_node *const bad  = new_r_Bad(irg, mode_X);
+               bool     const cond = ta == tarval_b_true;
+               ir_node *const in[] = {
+                       [pn_Cond_false] = cond ? bad : jmp,
+                       [pn_Cond_true]  = cond ? jmp : bad,
+               };
+               turn_into_tuple(n, ARRAY_SIZE(in), in);
                clear_irg_properties(irg, IR_GRAPH_PROPERTY_NO_UNREACHABLE_CODE);
        }
        return n;
@@ -4838,63 +4714,6 @@ static ir_node *transform_node_Proj_CopyB(ir_node *proj)
        return proj;
 }
 
-/**
- * Optimize Bounds(idx, idx, upper) into idx.
- */
-static ir_node *transform_node_Proj_Bound(ir_node *proj)
-{
-       ir_node *oldn  = proj;
-       ir_node *bound = get_Proj_pred(proj);
-       ir_node *idx   = get_Bound_index(bound);
-       ir_node *pred  = skip_Proj(idx);
-       int ret_tuple  = 0;
-
-       if (idx == get_Bound_lower(bound))
-               ret_tuple = 1;
-       else if (is_Bound(pred)) {
-               /*
-               * idx was Bounds checked previously, it is still valid if
-               * lower <= pred_lower && pred_upper <= upper.
-               */
-               ir_node *lower = get_Bound_lower(bound);
-               ir_node *upper = get_Bound_upper(bound);
-               if (get_Bound_lower(pred) == lower &&
-                       get_Bound_upper(pred) == upper) {
-                       /*
-                        * One could expect that we simply return the previous
-                        * Bound here. However, this would be wrong, as we could
-                        * add an exception Proj to a new location then.
-                        * So, we must turn in into a tuple.
-                        */
-                       ret_tuple = 1;
-               }
-       }
-       if (ret_tuple) {
-               /* Turn Bound into a tuple (mem, jmp, bad, idx) */
-               switch (get_Proj_proj(proj)) {
-               case pn_Bound_M:
-                       DBG_OPT_EXC_REM(proj);
-                       proj = get_Bound_mem(bound);
-                       break;
-               case pn_Bound_X_except:
-                       DBG_OPT_EXC_REM(proj);
-                       proj = new_r_Bad(get_irn_irg(proj), mode_X);
-                       break;
-               case pn_Bound_res:
-                       proj = idx;
-                       DBG_OPT_ALGSIM0(oldn, proj, FS_OPT_NOP);
-                       break;
-               case pn_Bound_X_regular:
-                       DBG_OPT_EXC_REM(proj);
-                       proj = new_r_Jmp(get_nodes_block(bound));
-                       break;
-               default:
-                       break;
-               }
-       }
-       return proj;
-}
-
 /**
  * Does all optimizations on nodes that must be done on its Projs
  * because of creating new nodes.
@@ -5490,16 +5309,8 @@ bool may_leave_out_middle_conv(ir_mode *m0, ir_mode *m1, ir_mode *m2)
 {
        int n_floats = mode_is_float(m0) + mode_is_float(m1) + mode_is_float(m2);
        if (n_floats == 1) {
-#if 0
-               int n_signed = mode_is_signed(m0) + mode_is_signed(m1)
-                            + mode_is_signed(m2);
-               /* we assume that float modes are always signed */
-               if ((n_signed & 1) != 1)
-                       return false;
-#else
                /* because overflow gives strange results we don't touch this case */
                return false;
-#endif
        } else if (n_floats == 2 && !mode_is_float(m1)) {
                return false;
        }
@@ -6076,6 +5887,25 @@ static ir_node *transform_node_Sync(ir_node *n)
        return n;
 }
 
+static ir_node *create_load_replacement_tuple(ir_node *n, ir_node *mem,
+                                              ir_node *res)
+{
+       ir_node  *block = get_nodes_block(n);
+       ir_graph *irg   = get_irn_irg(n);
+       ir_node  *in[pn_Load_max+1];
+       size_t    n_in  = 2;
+       in[pn_Load_M]   = mem;
+       in[pn_Load_res] = res;
+       if (ir_throws_exception(n)) {
+               in[pn_Load_X_regular] = new_r_Jmp(block);
+               in[pn_Load_X_except]  = new_r_Bad(irg, mode_X);
+               n_in                  = 4;
+               assert(pn_Load_max == 4);
+       }
+       ir_node  *tuple = new_r_Tuple(block, n_in, in);
+       return tuple;
+}
+
 static ir_node *transform_node_Load(ir_node *n)
 {
        /* don't touch volatile loads */
@@ -6105,17 +5935,9 @@ static ir_node *transform_node_Load(ir_node *n)
                        return n;
                /* all combinations of aligned/unaligned pred/n should be fine so we do
                 * not compare the unaligned attribute */
-               {
-                       ir_node  *block = get_nodes_block(n);
-                       ir_node  *jmp   = new_r_Jmp(block);
-                       ir_graph *irg   = get_irn_irg(n);
-                       ir_node  *bad   = new_r_Bad(irg, mode_X);
-                       ir_mode  *mode  = get_Load_mode(n);
-                       ir_node  *res   = new_r_Proj(pred_load, mode, pn_Load_res);
-                       ir_node  *in[]  = { mem, res, jmp, bad };
-                       ir_node  *tuple = new_r_Tuple(block, ARRAY_SIZE(in), in);
-                       return tuple;
-               }
+               ir_mode  *mode  = get_Load_mode(n);
+               ir_node  *res   = new_r_Proj(pred_load, mode, pn_Load_res);
+               return create_load_replacement_tuple(n, mem, res);
        } else if (is_Store(mem_pred)) {
                ir_node *pred_store = mem_pred;
                ir_node *value      = get_Store_value(pred_store);
@@ -6126,16 +5948,7 @@ static ir_node *transform_node_Load(ir_node *n)
                        return n;
                /* all combinations of aligned/unaligned pred/n should be fine so we do
                 * not compare the unaligned attribute */
-               {
-                       ir_node  *block = get_nodes_block(n);
-                       ir_node  *jmp   = new_r_Jmp(block);
-                       ir_graph *irg   = get_irn_irg(n);
-                       ir_node  *bad   = new_r_Bad(irg, mode_X);
-                       ir_node  *res   = value;
-                       ir_node  *in[]  = { mem, res, jmp, bad };
-                       ir_node  *tuple = new_r_Tuple(block, ARRAY_SIZE(in), in);
-                       return tuple;
-               }
+               return create_load_replacement_tuple(n, mem, value);
        }
 
        return n;
@@ -6328,8 +6141,6 @@ void ir_register_opt_node_ops(void)
 {
        register_computed_value_func(op_Add,      computed_value_Add);
        register_computed_value_func(op_And,      computed_value_And);
-       register_computed_value_func(op_Borrow,   computed_value_Borrow);
-       register_computed_value_func(op_Carry,    computed_value_Carry);
        register_computed_value_func(op_Cmp,      computed_value_Cmp);
        register_computed_value_func(op_Confirm,  computed_value_Confirm);
        register_computed_value_func(op_Const,    computed_value_Const);
@@ -6368,7 +6179,6 @@ void ir_register_opt_node_ops(void)
        register_equivalent_node_func(op_Shr,     equivalent_node_left_zero);
        register_equivalent_node_func(op_Shrs,    equivalent_node_left_zero);
        register_equivalent_node_func(op_Sub,     equivalent_node_Sub);
-       register_equivalent_node_func_proj(op_Bound, equivalent_node_Proj_Bound);
        register_equivalent_node_func_proj(op_CopyB, equivalent_node_Proj_CopyB);
        register_equivalent_node_func_proj(op_Div,   equivalent_node_Proj_Div);
        register_equivalent_node_func_proj(op_Tuple, equivalent_node_Proj_Tuple);
@@ -6400,7 +6210,6 @@ void ir_register_opt_node_ops(void)
        register_transform_node_func(op_Sub,    transform_node_Sub);
        register_transform_node_func(op_Switch, transform_node_Switch);
        register_transform_node_func(op_Sync,   transform_node_Sync);
-       register_transform_node_func_proj(op_Bound, transform_node_Proj_Bound);
        register_transform_node_func_proj(op_CopyB, transform_node_Proj_CopyB);
        register_transform_node_func_proj(op_Div,   transform_node_Proj_Div);
        register_transform_node_func_proj(op_Load,  transform_node_Proj_Load);