beifg: Simplify the implementation of be_ifg_foreach_node().
[libfirm] / ir / opt / fp-vrp.c
index 5b9a83b..8f28622 100644 (file)
@@ -1,27 +1,12 @@
 /*
- * Copyright (C) 1995-2010 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   Data-flow driven minimal fixpoint value range propagation
  * @author  Christoph Mallon
- * @version $Id$
  */
 #include "config.h"
 
@@ -44,7 +29,6 @@
 #include "tv.h"
 #include "irpass.h"
 #include "irmemory.h"
-#include "opt_manage.h"
 
 /* TODO:
  * - Implement cleared/set bit calculation for Add, Sub, Minus, Mul, Div, Mod, Shl, Shr, Shrs, Rotl
@@ -437,9 +421,9 @@ undefined:
                                                ir_tarval* const rzn = tarval_or(rz, tarval_neg(rz));
                                                // Concatenate safe lower zeroes.
                                                if (tarval_cmp(lzn, rzn) == ir_relation_less) {
-                                                       z = tarval_mul(tarval_eor(lzn, tarval_shl(lzn, get_tarval_one(m))), rzn);
+                                                       z = tarval_mul(tarval_eor(lzn, tarval_shl_unsigned(lzn, 1)), rzn);
                                                } else {
-                                                       z = tarval_mul(tarval_eor(rzn, tarval_shl(rzn, get_tarval_one(m))), lzn);
+                                                       z = tarval_mul(tarval_eor(rzn, tarval_shl_unsigned(rzn, 1)), lzn);
                                                }
                                                o = get_tarval_null(m);
                                        }
@@ -692,8 +676,6 @@ static void apply_result(ir_node* const irn, void* ctx)
                } else if (m == mode_X) {
                        ir_graph* const irg = get_Block_irg(block);
                        if (z == get_tarval_b_true()) {
-                               // Might produce an endless loop, so keep the block.
-                               add_End_keepalive(get_irg_end(irg), block);
                                n = new_r_Jmp(block);
                        } else {
                                n = new_r_Bad(irg, mode_X);
@@ -716,18 +698,14 @@ exchange_only:
                        ir_node*       const r  = get_And_right(irn);
                        bitinfo const* const bl = get_bitinfo(l);
                        bitinfo const* const br = get_bitinfo(r);
-                       if (bl->z == bl->o) {
-                               if (tarval_is_null(tarval_andnot(br->z, bl->z))) {
-                                       DB((dbg, LEVEL_2, "%+F(%+F, %+F) is superfluous\n", irn, l, r));
-                                       exchange(irn, r);
-                                       env->modified = 1;
-                               }
-                       } else if (br->z == br->o) {
-                               if (tarval_is_null(tarval_andnot(bl->z, br->z))) {
-                                       DB((dbg, LEVEL_2, "%+F(%+F, %+F) is superfluous\n", irn, l, r));
-                                       exchange(irn, l);
-                                       env->modified = 1;
-                               }
+                       if (tarval_is_null(tarval_andnot(br->z, bl->o))) {
+                               DB((dbg, LEVEL_2, "%+F(%+F, %+F) is superfluous\n", irn, l, r));
+                               exchange(irn, r);
+                               env->modified = 1;
+                       } else if (tarval_is_null(tarval_andnot(bl->z, br->o))) {
+                               DB((dbg, LEVEL_2, "%+F(%+F, %+F) is superfluous\n", irn, l, r));
+                               exchange(irn, l);
+                               env->modified = 1;
                        }
                        break;
                }
@@ -754,23 +732,37 @@ exchange_only:
                        break;
                }
 
+               case iro_Minus: {
+                       ir_mode *mode = get_irn_mode(irn);
+
+                       /* If all bits except the highest bit are zero the Minus is superfluous. */
+                       if (get_mode_arithmetic(mode) == irma_twos_complement) {
+                               ir_node         *const op  = get_Minus_op(irn);
+                               bitinfo   const *const b   = get_bitinfo(op);
+                               ir_tarval       *const min = get_mode_min(mode);
+
+                               if (b->z == min) {
+                                       DB((dbg, LEVEL_2, "%+F(%+F) is superfluous\n", irn, op));
+                                       exchange(irn, op);
+                                       env->modified = 1;
+                               }
+                       }
+                       break;
+               }
+
                case iro_Or: {
                        ir_node*       const l  = get_Or_left(irn);
                        ir_node*       const r  = get_Or_right(irn);
                        bitinfo const* const bl = get_bitinfo(l);
                        bitinfo const* const br = get_bitinfo(r);
-                       if (bl->z == bl->o) {
-                               if (tarval_is_null(tarval_andnot(bl->o, br->o))) {
-                                       DB((dbg, LEVEL_2, "%+F(%+F, %+F) is superfluous\n", irn, l, r));
-                                       exchange(irn, r);
-                                       env->modified = 1;
-                               }
-                       } else if (br->z == br->o) {
-                               if (tarval_is_null(tarval_andnot(br->o, bl->o))) {
-                                       DB((dbg, LEVEL_2, "%+F(%+F, %+F) is superfluous\n", irn, l, r));
-                                       exchange(irn, l);
-                                       env->modified = 1;
-                               }
+                       if (tarval_is_null(tarval_andnot(bl->z, br->o))) {
+                               DB((dbg, LEVEL_2, "%+F(%+F, %+F) is superfluous\n", irn, l, r));
+                               exchange(irn, r);
+                               env->modified = 1;
+                       } else if (tarval_is_null(tarval_andnot(br->z, bl->o))) {
+                               DB((dbg, LEVEL_2, "%+F(%+F, %+F) is superfluous\n", irn, l, r));
+                               exchange(irn, l);
+                               env->modified = 1;
                        }
 
                        /* if each bit is guaranteed to be zero on either the left or right
@@ -799,7 +791,6 @@ static void queue_users(pdeq* const q, ir_node* const n)
                /* When the state of a control flow node changes, not only queue its
                 * successor blocks, but also the Phis in these blocks, because the Phis
                 * must reconsider this input path. */
-               ir_edge_t const* e;
                foreach_out_edge(n, e) {
                        ir_node*  const  src = get_edge_src_irn(e);
                        pdeq_putr(q, src);
@@ -811,7 +802,6 @@ static void queue_users(pdeq* const q, ir_node* const n)
                        }
                }
        } else {
-               ir_edge_t const* e;
                foreach_out_edge(n, e) {
                        ir_node* const src = get_edge_src_irn(e);
                        if (get_irn_mode(src) == mode_T) {
@@ -838,14 +828,19 @@ static void build_phi_lists(ir_node *irn, void *env)
                add_Block_phi(get_nodes_block(irn), irn);
 }
 
-static ir_graph_state_t do_fixpoint_vrp(ir_graph* const irg)
+void fixpoint_vrp(ir_graph* const irg)
 {
        environment_t env;
-       ir_graph_state_t res = 0;
 
        FIRM_DBG_REGISTER(dbg, "firm.opt.fp-vrp");
        DB((dbg, LEVEL_1, "===> Performing constant propagation on %+F\n", irg));
 
+       assure_irg_properties(irg,
+               IR_GRAPH_PROPERTY_NO_BADS
+               | IR_GRAPH_PROPERTY_NO_UNREACHABLE_CODE
+               | IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE
+               | IR_GRAPH_PROPERTY_CONSISTENT_OUT_EDGES);
+
        obstack_init(&obst);
 
        ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK | IR_RESOURCE_PHI_LIST);
@@ -880,26 +875,11 @@ static ir_graph_state_t do_fixpoint_vrp(ir_graph* const irg)
        env.modified = 0;
        irg_walk_graph(irg, NULL, apply_result, &env);
 
-       if (! env.modified) {
-               res |= IR_GRAPH_STATE_CONSISTENT_DOMINANCE | IR_GRAPH_STATE_CONSISTENT_ENTITY_USAGE;
-       }
-
        ir_free_resources(irg, IR_RESOURCE_IRN_LINK | IR_RESOURCE_PHI_LIST);
 
        obstack_free(&obst, NULL);
-
-       return res;
-}
-
-static optdesc_t opt_fpvrp = {
-       "fp-vrp",
-       IR_GRAPH_STATE_NO_BADS | IR_GRAPH_STATE_NO_UNREACHABLE_CODE | IR_GRAPH_STATE_CONSISTENT_DOMINANCE | IR_GRAPH_STATE_CONSISTENT_OUT_EDGES,
-       do_fixpoint_vrp,
-};
-
-void fixpoint_vrp(ir_graph* const irg)
-{
-       perform_irg_optimization(irg, &opt_fpvrp);
+       confirm_irg_properties(irg,
+               env.modified ? IR_GRAPH_PROPERTIES_NONE : IR_GRAPH_PROPERTIES_ALL);
 }
 
 ir_graph_pass_t *fixpoint_vrp_irg_pass(const char *name)