#include "irdom.h"
#include "iredges.h"
#include "irgmod.h"
-#include "irgraph.h"
+#include "irgraph_t.h"
#include "irgwalk.h"
-#include "irnode.h"
+#include "irnode_t.h"
#include "iroptimize.h"
#include "irtools.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* z;
ir_tarval* o;
+ if (is_Bad(irn)) return 0;
+
if (m == mode_X) {
bitinfo* const b = get_bitinfo(get_nodes_block(irn));
/* TODO Use bound and relation. */
z = b->z;
o = b->o;
+ if ((get_Confirm_relation(irn) & ~ir_relation_unordered) == ir_relation_equal) {
+ bitinfo* const bound_b = get_bitinfo(get_Confirm_bound(irn));
+ z = tarval_and(z, bound_b->z);
+ o = tarval_or( o, bound_b->o);
+ }
break;
}
}
}
+static ir_node *make_bad_block(ir_graph *irg)
+{
+ ir_node *bad = new_r_Bad(irg, mode_BB);
+ bitinfo *bb = get_bitinfo(bad);
+ if (bb == NULL) {
+ ir_tarval* const f = get_tarval_b_false();
+ ir_tarval* const t = get_tarval_b_true();
+ set_bitinfo(bad, f, t); /* Undefined. */
+ }
+ return bad;
+}
+
static void apply_result(ir_node* const irn, void* ctx)
{
environment_t* env = (environment_t*)ctx;
block_b = get_bitinfo(irn);
/* Trivially unreachable blocks have no info. */
if (block_b == NULL || block_b->z == get_tarval_b_false()) {
- exchange(irn, get_irg_bad(get_Block_irg(irn)));
+ ir_node *bad = make_bad_block(get_irn_irg(irn));
+ exchange(irn, bad);
env->modified = 1;
}
return;
/* Trivially unreachable blocks have no info. */
if (block_b == NULL || block_b->z == get_tarval_b_false()) {
/* Unreachable blocks might be replaced before the nodes in them. */
- exchange(irn, is_Bad(block) ? block : get_irg_bad(get_Block_irg(block)));
+ ir_mode *mode = get_irn_mode(irn);
+ ir_graph *irg = get_irn_irg(irn);
+ ir_node *bad = new_r_Bad(irg, mode);
+ exchange(irn, bad);
env->modified = 1;
return;
}
add_End_keepalive(get_irg_end(irg), block);
n = new_r_Jmp(block);
} else {
- n = new_r_Bad(irg);
+ n = new_r_Bad(irg, mode_X);
/* Transferring analysis information to the bad node makes it a
* candidate for replacement. */
goto exchange_only;
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;
+ }
+
case iro_Or: {
ir_node* const l = get_Or_left(irn);
ir_node* const r = get_Or_right(irn);
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;
}
}
add_Block_phi(get_nodes_block(irn), irn);
}
-void fixpoint_vrp(ir_graph* const irg)
+static ir_graph_state_t do_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));
obstack_init(&obst);
- /* HACK: to avoid finding dead code */
- edges_deactivate(irg);
- edges_activate(irg);
-
- edges_assure(irg);
- assure_doms(irg);
-
ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK | IR_RESOURCE_PHI_LIST);
{
pdeq* const q = new_pdeq();
- /* We need this extra step because the dom tree does not contain unreachable
- blocks in Firm. Moreover build phi list. */
+ /* We need this extra step because the dom tree does not contain
+ * unreachable blocks in Firm. Moreover build phi list. */
irg_walk_anchors(irg, clear_links, build_phi_lists, NULL);
- { ir_tarval* const f = get_tarval_b_false();
+ {
+ ir_tarval* const f = get_tarval_b_false();
ir_tarval* const t = get_tarval_b_true();
- set_bitinfo(get_irg_bad(irg), f, t); /* Undefined. */
set_bitinfo(get_irg_end_block(irg), t, f); /* Reachable. */
}
env.modified = 0;
irg_walk_graph(irg, NULL, apply_result, &env);
- if (env.modified) {
- /* control flow might changed */
- set_irg_outs_inconsistent(irg);
- set_irg_extblk_inconsistent(irg);
- set_irg_doms_inconsistent(irg);
- set_irg_loopinfo_inconsistent(irg);
- set_irg_entity_usage_state(irg, ir_entity_usage_not_computed);
+ 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);
}
ir_graph_pass_t *fixpoint_vrp_irg_pass(const char *name)