* @file
* @brief Data-flow driven minimal fixpoint value range propagation
* @author Christoph Mallon
- * @version $Id$
*/
#include "config.h"
ir_tarval* z;
ir_tarval* o;
+ if (is_Bad(irn)) return 0;
+
if (m == mode_X) {
bitinfo* const b = get_bitinfo(get_nodes_block(irn));
} else if (is_Cond(pred)) {
ir_node* const selector = get_Cond_selector(pred);
bitinfo* const b = get_bitinfo(selector);
- if (is_undefined(b)) {
+ if (is_undefined(b))
goto unreachable_X;
- } else if (get_irn_mode(selector) == mode_b) {
- if (b->z == b->o) {
- if ((b->z == t) == get_Proj_proj(irn)) {
- z = o = t;
- } else {
- z = o = f;
- }
+ if (b->z == b->o) {
+ if ((b->z == t) == get_Proj_proj(irn)) {
+ z = o = t;
} else {
- goto result_unknown_X;
+ z = o = f;
}
} else {
- long const val = get_Proj_proj(irn);
- if (val != get_Cond_default_proj(pred)) {
- ir_tarval* const tv = new_tarval_from_long(val, get_irn_mode(selector));
- if (!tarval_is_null(tarval_andnot(tv, b->z)) ||
- !tarval_is_null(tarval_andnot(b->o, tv))) {
- // At least one bit differs.
- z = o = f;
-#if 0 // TODO must handle default Proj
- } else if (b->z == b->o && b->z == tv) {
- z = o = t;
-#endif
- } else {
- goto result_unknown_X;
- }
- } else {
- goto cannot_analyse_X;
- }
+ goto result_unknown_X;
}
+ } else if (is_Switch(pred)) {
+ ir_node* const selector = get_Switch_selector(pred);
+ bitinfo* const b = get_bitinfo(selector);
+ if (is_undefined(b))
+ goto unreachable_X;
+ /* TODO */
+ goto cannot_analyse_X;
} else {
goto cannot_analyse_X;
}
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);
}
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;
+ }
+
+ case iro_Eor: {
+ ir_node* const l = get_Eor_left(irn);
+ ir_node* const r = get_Eor_right(irn);
+ bitinfo const* const bl = get_bitinfo(l);
+ bitinfo const* const br = get_bitinfo(r);
+ /* if each bit is guaranteed to be zero on either the left or right
+ * then an Add will have the same effect as the Eor. Change it for
+ * normalisation */
+ if (tarval_is_null(tarval_and(bl->z, br->z))) {
+ dbg_info *dbgi = get_irn_dbg_info(irn);
+ ir_node *block = get_nodes_block(irn);
+ ir_mode *mode = get_irn_mode(irn);
+ ir_node *new_node = new_rd_Add(dbgi, block, l, r, mode);
+ bitinfo const *bi = get_bitinfo(irn);
+ DB((dbg, LEVEL_2, "%+F(%+F, %+F) normalised to Add\n", irn, l, r));
+ set_bitinfo(new_node, bi->z, bi->o);
+ exchange(irn, new_node);
+ env->modified = 1;
}
break;
}
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
+ * then an Add will have the same effect as the Or. Change it for
+ * normalisation */
+ if (tarval_is_null(tarval_and(bl->z, br->z))) {
+ dbg_info *dbgi = get_irn_dbg_info(irn);
+ ir_node *block = get_nodes_block(irn);
+ ir_mode *mode = get_irn_mode(irn);
+ ir_node *new_node = new_rd_Add(dbgi, block, l, r, mode);
+ bitinfo const *bi = get_bitinfo(irn);
+ DB((dbg, LEVEL_2, "%+F(%+F, %+F) normalised to Add\n", irn, l, r));
+ set_bitinfo(new_node, bi->z, bi->o);
+ exchange(irn, new_node);
+ env->modified = 1;
}
+
break;
}
}
/* 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) {
FIRM_DBG_REGISTER(dbg, "firm.opt.fp-vrp");
DB((dbg, LEVEL_1, "===> Performing constant propagation on %+F\n", irg));
- obstack_init(&obst);
-
- /* HACK: to avoid finding dead code */
- edges_deactivate(irg);
- edges_activate(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);
- edges_assure(irg);
- assure_doms(irg);
+ 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) {
- /* control flow might changed */
- set_irg_extblk_inconsistent(irg);
- set_irg_doms_inconsistent(irg);
- set_irg_entity_usage_state(irg, ir_entity_usage_not_computed);
- }
-
ir_free_resources(irg, IR_RESOURCE_IRN_LINK | IR_RESOURCE_PHI_LIST);
obstack_free(&obst, NULL);
+ 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)