/*
- * 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"
#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
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);
}
} 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);
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;
}
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
/* 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);
}
}
} 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) {
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);
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)