static ir_node *equivalent_node_Block(ir_node *n)
{
ir_node *oldn = n;
- int n_preds = get_Block_n_cfgpreds(n);
+ int n_preds;
- /* The Block constructor does not call optimize, but mature_immBlock
- calls the optimization. */
+ /* don't optimize dead blocks */
+ if (is_Block_dead(n))
+ return n;
+
+ n_preds = get_Block_n_cfgpreds(n);
+
+ /* The Block constructor does not call optimize, but mature_immBlock()
+ calls the optimization. */
assert(get_Block_matured(n));
/* Straightening: a single entry Block following a single exit Block
/**
- * Optimize an "idempotent unary op", ie op(op(n)) = n.
+ * Optimize an "self-inverse unary op", ie op(op(n)) = n.
*
* @todo
* -(-a) == a, but might overflow two times.
int i, n_preds;
ir_node *oldn = n;
- ir_node *block = NULL; /* to shutup gcc */
+ ir_node *block;
ir_node *first_val = NULL; /* to shutup gcc */
if (!get_opt_normalize()) return n;
n_preds = get_Phi_n_preds(n);
block = get_nodes_block(n);
- /* @@@ fliegt 'raus, sollte aber doch immer wahr sein!!!
- assert(get_irn_arity(block) == n_preds && "phi in wrong block!"); */
if ((is_Block_dead(block)) || /* Control dead */
(block == get_irg_start_block(current_ir_graph))) /* There should be no Phi nodes */
return new_Bad(); /* in the Start Block. */
* themselves.
*/
static ir_node *equivalent_node_Sync(ir_node *n) {
- int i, n_preds;
-
- ir_node *oldn = n;
- ir_node *first_val = NULL; /* to shutup gcc */
-
- if (!get_opt_normalize()) return n;
+ int arity = get_Sync_n_preds(n);
+ int i;
- n_preds = get_Sync_n_preds(n);
+ for (i = 0; i < arity;) {
+ ir_node *pred = get_Sync_pred(n, i);
+ int j;
- /* Find first non-self-referencing input */
- for (i = 0; i < n_preds; ++i) {
- first_val = get_Sync_pred(n, i);
- if ((first_val != n) /* not self pointer */ &&
- (! is_Bad(first_val))
- ) { /* value not dead */
- break; /* then found first value. */
+ /* Remove Bad predecessors */
+ if (is_Bad(pred)) {
+ del_Sync_n(n, i);
+ --arity;
+ continue;
}
- }
- if (i >= n_preds)
- /* A totally Bad or self-referencing Sync (we didn't break the above loop) */
- return new_Bad();
-
- /* search the rest of inputs, determine if any of these
- are non-self-referencing */
- while (++i < n_preds) {
- ir_node *scnd_val = get_Sync_pred(n, i);
- if ((scnd_val != n) &&
- (scnd_val != first_val) &&
- (! is_Bad(scnd_val))
- )
- break;
+ /* Remove duplicate predecessors */
+ for (j = 0;; ++j) {
+ if (j >= i) {
+ ++i;
+ break;
+ }
+ if (get_Sync_pred(n, j) == pred) {
+ del_Sync_n(n, i);
+ --arity;
+ break;
+ }
+ }
}
- if (i >= n_preds) {
- /* Fold, if no multiple distinct non-self-referencing inputs */
- n = first_val;
- DBG_OPT_SYNC(oldn, n);
- }
+ if (arity == 0) return new_Bad();
+ if (arity == 1) return get_Sync_pred(n, 0);
return n;
} /* equivalent_node_Sync */
else if (is_Proj(sel) && !mode_honor_signed_zeros(get_irn_mode(n))) {
ir_node *cmp = get_Proj_pred(sel);
long proj_nr = get_Proj_proj(sel);
- ir_node *b = get_Mux_false(n);
- ir_node *a = get_Mux_true(n);
+ ir_node *f = get_Mux_false(n);
+ ir_node *t = get_Mux_true(n);
/*
- * Note: normalization puts the constant on the right site,
- * so we check only one case.
- *
* Note further that these optimization work even for floating point
* with NaN's because -NaN == NaN.
* However, if +0 and -0 is handled differently, we cannot use the first one.
*/
- if (is_Cmp(cmp) && get_Cmp_left(cmp) == a) {
- ir_node *cmp_r = get_Cmp_right(cmp);
- if (is_Const(cmp_r) && is_Const_null(cmp_r)) {
- /* Mux(a CMP 0, X, a) */
- if (is_Minus(b) && get_Minus_op(b) == a) {
- /* Mux(a CMP 0, -a, a) */
- if (proj_nr == pn_Cmp_Eq) {
- /* Mux(a == 0, -a, a) ==> -a */
- n = b;
+ if (is_Cmp(cmp)) {
+ ir_node *const cmp_l = get_Cmp_left(cmp);
+ ir_node *const cmp_r = get_Cmp_right(cmp);
+
+ switch (proj_nr) {
+ case pn_Cmp_Eq:
+ if ((cmp_l == t && cmp_r == f) || /* Psi(t == f, t, f) -> f */
+ (cmp_l == f && cmp_r == t)) { /* Psi(f == t, t, f) -> f */
+ n = f;
DBG_OPT_ALGSIM0(oldn, n, FS_OPT_MUX_TRANSFORM);
- } else if (proj_nr == pn_Cmp_Lg || proj_nr == pn_Cmp_Ne) {
- /* Mux(a != 0, -a, a) ==> a */
- n = a;
+ return n;
+ }
+ break;
+
+ case pn_Cmp_Lg:
+ case pn_Cmp_Ne:
+ if ((cmp_l == t && cmp_r == f) || /* Psi(t != f, t, f) -> t */
+ (cmp_l == f && cmp_r == t)) { /* Psi(f != t, t, f) -> t */
+ n = t;
DBG_OPT_ALGSIM0(oldn, n, FS_OPT_MUX_TRANSFORM);
+ return n;
}
- } else if (is_Const(b) && is_Const_null(b)) {
- /* Mux(a CMP 0, 0, a) */
- if (proj_nr == pn_Cmp_Lg || proj_nr == pn_Cmp_Ne) {
- /* Mux(a != 0, 0, a) ==> a */
- n = a;
+ break;
+ }
+
+ /*
+ * Note: normalization puts the constant on the right side,
+ * so we check only one case.
+ */
+ if (cmp_l == t && is_Const(cmp_r) && is_Const_null(cmp_r)) {
+ /* Mux(t CMP 0, X, t) */
+ if (is_Minus(f) && get_Minus_op(f) == t) {
+ /* Mux(t CMP 0, -t, t) */
+ if (proj_nr == pn_Cmp_Eq) {
+ /* Mux(t == 0, -t, t) ==> -t */
+ n = f;
DBG_OPT_ALGSIM0(oldn, n, FS_OPT_MUX_TRANSFORM);
- } else if (proj_nr == pn_Cmp_Eq) {
- /* Mux(a == 0, 0, a) ==> 0 */
- n = b;
+ } else if (proj_nr == pn_Cmp_Lg || proj_nr == pn_Cmp_Ne) {
+ /* Mux(t != 0, -t, t) ==> t */
+ n = t;
DBG_OPT_ALGSIM0(oldn, n, FS_OPT_MUX_TRANSFORM);
}
}
* Optimize Bounds(idx, idx, upper) into idx.
*/
static ir_node *equivalent_node_Bound(ir_node *n) {
- ir_node *idx = get_Bound_index(n);
- ir_node *lower = get_Bound_lower(n);
+ ir_node *idx = get_Bound_index(n);
+ ir_node *pred = skip_Proj(idx);
int ret_tuple = 0;
- /* By definition lower < upper, so if idx == lower -->
- lower <= idx && idx < upper */
- if (idx == lower) {
- /* Turn Bound into a tuple (mem, jmp, bad, idx) */
- ret_tuple = 1;
- } else {
- ir_node *pred = skip_Proj(idx);
-
- if (get_irn_op(pred) == op_Bound) {
+ if (is_Bound(pred)) {
+ /*
+ * idx was Bounds checked in the same MacroBlock previously,
+ * it is still valid if lower <= pred_lower && pred_upper <= upper.
+ */
+ ir_node *lower = get_Bound_lower(n);
+ ir_node *upper = get_Bound_upper(n);
+ if (get_Bound_lower(pred) == lower &&
+ get_Bound_upper(pred) == upper &&
+ get_irn_MacroBlock(n) == get_irn_MacroBlock(pred)) {
/*
- * idx was Bounds_check previously, it is still valid if
- * lower <= pred_lower && pred_upper <= 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.
*/
- ir_node *upper = get_Bound_upper(n);
- 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;
- }
+ ret_tuple = 1;
}
}
if (ret_tuple) {
int i, n;
if (get_nodes_block(a) != get_nodes_block(b))
- return NULL;
+ return NULL;
n = get_irn_arity(a);
NEW_ARR_A(void *, res, n);
ir_mode *mode = get_irn_mode(n);
if (mode_is_reference(mode)) {
- ir_node *left = get_binop_left(n);
- ir_node *right = get_binop_right(n);
- int ref_bits = get_mode_size_bits(mode);
+ ir_node *left = get_binop_left(n);
+ ir_node *right = get_binop_right(n);
+ unsigned ref_bits = get_mode_size_bits(mode);
if (is_Conv(left)) {
- ir_mode *mode = get_irn_mode(left);
- int bits = get_mode_size_bits(mode);
+ ir_mode *lmode = get_irn_mode(left);
+ unsigned bits = get_mode_size_bits(lmode);
if (ref_bits == bits &&
- mode_is_int(mode) &&
- get_mode_arithmetic(mode) == irma_twos_complement) {
+ mode_is_int(lmode) &&
+ get_mode_arithmetic(lmode) == irma_twos_complement) {
ir_node *pre = get_Conv_op(left);
ir_mode *pre_mode = get_irn_mode(pre);
}
if (is_Conv(right)) {
- ir_mode *mode = get_irn_mode(right);
- int bits = get_mode_size_bits(mode);
+ ir_mode *rmode = get_irn_mode(right);
+ unsigned bits = get_mode_size_bits(rmode);
if (ref_bits == bits &&
- mode_is_int(mode) &&
- get_mode_arithmetic(mode) == irma_twos_complement) {
+ mode_is_int(rmode) &&
+ get_mode_arithmetic(rmode) == irma_twos_complement) {
ir_node *pre = get_Conv_op(right);
ir_mode *pre_mode = get_irn_mode(pre);
}
}
}
+
+ /* let address arithmetic use unsigned modes */
+ if (is_Const(right)) {
+ ir_mode *rmode = get_irn_mode(right);
+
+ if (mode_is_signed(rmode) && get_mode_arithmetic(rmode) == irma_twos_complement) {
+ /* convert a AddP(P, *s) into AddP(P, *u) */
+ ir_mode *nm = get_reference_mode_unsigned_eq(mode);
+
+ ir_node *pre = new_r_Conv(current_ir_graph, get_nodes_block(n), right, nm);
+ set_binop_right(n, pre);
+ }
+ }
}
return n;
} /* transform_node_AddSub */
/*
* We can replace the Abs by -x here.
- * We even could add a new Confirm here.
+ * We even could add a new Confirm here
+ * (if not twos complement)
*
* Note that -x would create a new node, so we could
* not run it in the equivalent_node() context.
(get_opt_unreachable_code())) {
/* It's a boolean Cond, branching on a boolean constant.
Replace it by a tuple (Bad, Jmp) or (Jmp, Bad) */
- jmp = new_r_Jmp(current_ir_graph, get_nodes_block(n));
+ ir_node *blk = get_nodes_block(n);
+ jmp = new_r_Jmp(current_ir_graph, blk);
turn_into_tuple(n, pn_Cond_max);
if (ta == tarval_b_true) {
set_Tuple_pred(n, pn_Cond_false, new_Bad());
set_Tuple_pred(n, pn_Cond_true, new_Bad());
}
/* We might generate an endless loop, so keep it alive. */
- add_End_keepalive(get_irg_end(current_ir_graph), get_nodes_block(n));
+ add_End_keepalive(get_irg_end(current_ir_graph), blk);
}
return n;
} /* transform_node_Cond */
-typedef ir_node* (*recursive_transform) (ir_node *n);
+/**
+ * Prototype of a recursive transform function
+ * for bitwise distributive transformations.
+ */
+typedef ir_node* (*recursive_transform)(ir_node *n);
/**
* makes use of distributive laws for and, or, eor
n = new_rd_And(dbgi, irg, blk, new_n, c, mode);
} else {
n = exact_copy(a);
- set_irn_n(n, -1, blk);
+ set_nodes_block(n, blk);
set_binop_left(n, new_n);
set_binop_right(n, c);
add_identities(current_ir_graph->value_table, n);
if (is_Const(c)) {
tarval *tv = get_Const_tarval(c);
- if (tarval_is_long(tv) && get_tarval_long(tv) == get_mode_size_bits(mode) - 1) {
+ if (tarval_is_long(tv) && get_tarval_long(tv) == (int) get_mode_size_bits(mode) - 1) {
/* -(a >>u (size-1)) = a >>s (size-1) */
ir_node *v = get_Shr_left(a);
if (is_Const(c)) {
tarval *tv = get_Const_tarval(c);
- if (tarval_is_long(tv) && get_tarval_long(tv) == get_mode_size_bits(mode) - 1) {
+ if (tarval_is_long(tv) && get_tarval_long(tv) == (int) get_mode_size_bits(mode) - 1) {
/* -(a >>s (size-1)) = a >>u (size-1) */
ir_node *v = get_Shrs_left(a);
ir_node *mul_r = get_Mul_right(a);
if (is_Const(mul_r)) {
tarval *tv = tarval_neg(get_Const_tarval(mul_r));
- ir_node *cnst = new_Const(mode, tv);
- dbg_info *dbg = get_irn_dbg_info(a);
- ir_graph *irg = current_ir_graph;
- ir_node *block = get_nodes_block(a);
- n = new_rd_Mul(dbg, irg, block, mul_l, cnst, mode);
- DBG_OPT_ALGSIM2(oldn, a, n, FS_OPT_MINUS_MUL_C);
- return n;
+ if(tv != tarval_bad) {
+ ir_node *cnst = new_Const(mode, tv);
+ dbg_info *dbg = get_irn_dbg_info(a);
+ ir_graph *irg = current_ir_graph;
+ ir_node *block = get_nodes_block(a);
+ n = new_rd_Mul(dbg, irg, block, mul_l, cnst, mode);
+ DBG_OPT_ALGSIM2(oldn, a, n, FS_OPT_MINUS_MUL_C);
+ return n;
+ }
}
}
break;
}
- /* remove Casts */
- if (is_Cast(left))
- left = get_Cast_op(left);
- if (is_Cast(right))
- right = get_Cast_op(right);
+ /* remove Casts of both sides */
+ left = skip_Cast(left);
+ right = skip_Cast(right);
/* Remove unnecessary conversions */
/* TODO handle constants */
}
}
- /* remove operation of both sides if possible */
+ /* remove operation on both sides if possible */
if (proj_nr == pn_Cmp_Eq || proj_nr == pn_Cmp_Lg) {
/*
* The following operations are NOT safe for floating point operations, for instance
return or;
if (get_tarval_long(tv1) + get_tarval_long(tv2)
- != get_mode_size_bits(mode))
+ != (int) get_mode_size_bits(mode))
return or;
/* yet, condition met */
if (! tarval_is_long(tv1))
return or;
- if (get_tarval_long(tv1) != get_mode_size_bits(mode))
+ if (get_tarval_long(tv1) != (int) get_mode_size_bits(mode))
return or;
/* yet, condition met */
if (! tarval_is_long(tv1))
return or;
- if (get_tarval_long(tv1) != get_mode_size_bits(mode))
+ if (get_tarval_long(tv1) != (int) get_mode_size_bits(mode))
return or;
/* yet, condition met */
* of the other sync to our own inputs
*/
static ir_node *transform_node_Sync(ir_node *n) {
- int i, arity;
+ int arity = get_Sync_n_preds(n);
+ int i;
+
+ for (i = 0; i < arity;) {
+ ir_node *pred = get_Sync_pred(n, i);
+ int pred_arity;
+ int j;
- arity = get_irn_arity(n);
- for(i = 0; i < get_irn_arity(n); /*empty*/) {
- int i2, arity2;
- ir_node *in = get_irn_n(n, i);
- if(!is_Sync(in)) {
+ if (!is_Sync(pred)) {
++i;
continue;
}
- /* set sync input 0 instead of the sync */
- set_irn_n(n, i, get_irn_n(in, 0));
- /* so we check this input again for syncs */
-
- /* append all other inputs of the sync to our sync */
- arity2 = get_irn_arity(in);
- for(i2 = 1; i2 < arity2; ++i2) {
- ir_node *in_in = get_irn_n(in, i2);
- add_irn_n(n, in_in);
- /* increase arity so we also check the new inputs for syncs */
- arity++;
+ del_Sync_n(n, i);
+ --arity;
+
+ pred_arity = get_Sync_n_preds(pred);
+ for (j = 0; j < pred_arity; ++j) {
+ ir_node *pred_pred = get_Sync_pred(pred, j);
+ int k;
+
+ for (k = 0;; ++k) {
+ if (k >= arity) {
+ add_irn_n(n, pred_pred);
+ ++arity;
+ break;
+ }
+ if (get_Sync_pred(n, k) == pred_pred) break;
+ }
}
}
static int node_cmp_attr_SymConst(ir_node *a, ir_node *b) {
const symconst_attr *pa = get_irn_symconst_attr(a);
const symconst_attr *pb = get_irn_symconst_attr(b);
- return (pa->num != pb->num)
+ return (pa->kind != pb->kind)
|| (pa->sym.type_p != pb->sym.type_p)
|| (pa->tp != pb->tp);
} /* node_cmp_attr_SymConst */
/** Compares the attributes of two Call nodes. */
static int node_cmp_attr_Call(ir_node *a, ir_node *b) {
- return (get_irn_call_attr(a) != get_irn_call_attr(b));
+ return get_irn_call_attr(a) != get_irn_call_attr(b);
} /* node_cmp_attr_Call */
/** Compares the attributes of two Sel nodes. */
/* we can only enter this function if both nodes have the same number of inputs,
hence it is enough to check if one of them is a Phi0 */
if (is_Phi0(a)) {
- /* check the Phi0 attribute */
- return get_irn_phi0_attr(a) != get_irn_phi0_attr(b);
+ /* check the Phi0 pos attribute */
+ return get_irn_phi_attr(a)->u.pos != get_irn_phi_attr(b)->u.pos;
}
return 0;
} /* node_cmp_attr_Phi */
get_Store_volatility(b) == volatility_is_volatile);
} /* node_cmp_attr_Store */
+/** Compares two exception attributes */
+static int node_cmp_exception(ir_node *a, ir_node *b) {
+ const except_attr *ea = get_irn_except_attr(a);
+ const except_attr *eb = get_irn_except_attr(b);
+
+ return ea->pin_state != eb->pin_state;
+}
+
+#define node_cmp_attr_Bound node_cmp_exception
+
+/** Compares the attributes of two Div nodes. */
+static int node_cmp_attr_Div(ir_node *a, ir_node *b) {
+ const divmod_attr *ma = get_irn_divmod_attr(a);
+ const divmod_attr *mb = get_irn_divmod_attr(b);
+ return ma->exc.pin_state != mb->exc.pin_state ||
+ ma->res_mode != mb->res_mode ||
+ ma->no_remainder != mb->no_remainder;
+} /* node_cmp_attr_Div */
+
+/** Compares the attributes of two DivMod nodes. */
+static int node_cmp_attr_DivMod(ir_node *a, ir_node *b) {
+ const divmod_attr *ma = get_irn_divmod_attr(a);
+ const divmod_attr *mb = get_irn_divmod_attr(b);
+ return ma->exc.pin_state != mb->exc.pin_state ||
+ ma->res_mode != mb->res_mode;
+} /* node_cmp_attr_DivMod */
+
+/** Compares the attributes of two Mod nodes. */
+static int node_cmp_attr_Mod(ir_node *a, ir_node *b) {
+ const divmod_attr *ma = get_irn_divmod_attr(a);
+ const divmod_attr *mb = get_irn_divmod_attr(b);
+ return ma->exc.pin_state != mb->exc.pin_state ||
+ ma->res_mode != mb->res_mode;
+} /* node_cmp_attr_Mod */
+
+/** Compares the attributes of two Quot nodes. */
+static int node_cmp_attr_Quot(ir_node *a, ir_node *b) {
+ const divmod_attr *ma = get_irn_divmod_attr(a);
+ const divmod_attr *mb = get_irn_divmod_attr(b);
+ return ma->exc.pin_state != mb->exc.pin_state ||
+ ma->res_mode != mb->res_mode;
+} /* node_cmp_attr_Quot */
+
/** Compares the attributes of two Confirm nodes. */
static int node_cmp_attr_Confirm(ir_node *a, ir_node *b) {
return (get_Confirm_cmp(a) != get_Confirm_cmp(b));
CASE(Store);
CASE(Confirm);
CASE(ASM);
+ CASE(Div);
+ CASE(DivMod);
+ CASE(Mod);
+ CASE(Quot);
+ CASE(Bound);
+ /* FIXME CopyB */
default:
/* leave NULL */;
}
} /* firm_set_default_node_cmp_attr */
/*
- * Compare function for two nodes in the hash table. Gets two
- * nodes as parameters. Returns 0 if the nodes are a cse.
+ * Compare function for two nodes in the value table. Gets two
+ * nodes as parameters. Returns 0 if the nodes are a Common Sub Expression.
*/
int identities_cmp(const void *elt, const void *key) {
- ir_node *a, *b;
+ ir_node *a = (ir_node *)elt;
+ ir_node *b = (ir_node *)key;
int i, irn_arity_a;
- a = (void *)elt;
- b = (void *)key;
-
if (a == b) return 0;
if ((get_irn_op(a) != get_irn_op(b)) ||
(get_irn_mode(a) != get_irn_mode(b))) return 1;
/* compare if a's in and b's in are of equal length */
- irn_arity_a = get_irn_intra_arity (a);
+ irn_arity_a = get_irn_intra_arity(a);
if (irn_arity_a != get_irn_intra_arity(b))
return 1;
- /* for block-local cse and op_pin_state_pinned nodes: */
- if (!get_opt_global_cse() || (get_irn_pinned(a) == op_pin_state_pinned)) {
+ if (get_irn_pinned(a) == op_pin_state_pinned) {
+ /* for pinned nodes, the block inputs must be equal */
if (get_irn_intra_n(a, -1) != get_irn_intra_n(b, -1))
return 1;
+ } else if (! get_opt_global_cse()) {
+ /* for block-local CSE both nodes must be in the same MacroBlock */
+ if (get_irn_MacroBlock(a) != get_irn_MacroBlock(b))
+ return 1;
}
/* compare a->in[0..ins] with b->in[0..ins] */
/**
* Normalize a node by putting constants (and operands with larger
- * node index) on the right
+ * node index) on the right (operator side).
*
* @param n The node to normalize
*/
}
} /* normalize_node */
+/**
+ * Update the nodes after a match in the value table. If both nodes have
+ * the same MacroBlock but different Blocks, we must ensure that the node
+ * with the dominating Block (the node that is near to the MacroBlock header
+ * is stored in the table.
+ * Because a MacroBlock has only one "non-exception" flow, we don't need
+ * dominance info here: We known, that one block must dominate the other and
+ * following the only block input will allow to find it.
+ */
+static void update_known_irn(ir_node *known_irn, const ir_node *new_ir_node) {
+ ir_node *known_blk, *new_block, *block, *mbh;
+
+ if (get_opt_global_cse()) {
+ /* Block inputs are meaning less */
+ return;
+ }
+ known_blk = get_irn_n(known_irn, -1);
+ new_block = get_irn_n(new_ir_node, -1);
+ if (known_blk == new_block) {
+ /* already in the same block */
+ return;
+ }
+ /*
+ * We expect the typical case when we built the graph. In that case, the
+ * known_irn is already the upper one, so checking this should be faster.
+ */
+ block = new_block;
+ mbh = get_Block_MacroBlock(new_block);
+ for (;;) {
+ if (block == known_blk) {
+ /* ok, we have found it: known_block dominates new_block as expected */
+ return;
+ }
+ if (block == mbh) {
+ /*
+ * We have reached the MacroBlock header NOT founding
+ * the known_block. new_block must dominate known_block.
+ * Update known_irn.
+ */
+ set_irn_n(known_irn, -1, new_block);
+ return;
+ }
+ assert(get_Block_n_cfgpreds(block) == 1);
+ block = get_Block_cfgpred_block(block, 0);
+ }
+} /* update_value_table */
+
/**
* Return the canonical node computing the same value as n.
*
normalize_node(n);
o = pset_find(value_table, n, ir_node_hash(n));
- if (!o) return n;
+ if (o == NULL)
+ return n;
+ update_known_irn(o, n);
DBG_OPT_CSE(n, o);
return o;
* During construction we set the op_pin_state_pinned flag in the graph right when the
* optimization is performed. The flag turning on procedure global cse could
* be changed between two allocations. This way we are safe.
+ *
+ * @param value_table The value table
+ * @param n The node to lookup
*/
static INLINE ir_node *identify_cons(pset *value_table, ir_node *n) {
ir_node *old = n;
n = identify(value_table, n);
- if (get_irn_n(old, -1) != get_irn_n(n, -1))
+ if (n != old && get_irn_MacroBlock(old) != get_irn_MacroBlock(n))
set_irg_pinned(current_ir_graph, op_pin_state_floats);
return n;
} /* identify_cons */
* Return the canonical node computing the same value as n.
* Looks up the node in a hash table, enters it in the table
* if it isn't there yet.
+ *
+ * @param value_table the HashSet containing all nodes in the
+ * current IR graph
+ * @param n the node to look up
+ *
+ * @return a node that computes the same value as n or n if no such
+ * node could be found
*/
ir_node *identify_remember(pset *value_table, ir_node *n) {
ir_node *o = NULL;
o = pset_insert(value_table, n, ir_node_hash(n));
if (o != n) {
+ update_known_irn(o, n);
DBG_OPT_CSE(n, o);
}
ir_node *block = get_nodes_block(skip_Proj(node));
/* Don't optimize nodes in immature blocks. */
- if (!get_Block_matured(block)) return node;
+ if (!get_Block_matured(block))
+ return node;
/* Don't optimize End, may have Bads. */
if (op == op_End) return node;
if (is_Block(block)) {
- irn_arity = get_irn_arity(block);
- for (i = 0; i < irn_arity; i++) {
+ if (is_Block_dead(block)) {
+ /* control flow from dead block is dead */
+ return new_Bad();
+ }
+
+ for (i = get_irn_arity(block) - 1; i >= 0; --i) {
if (!is_Bad(get_irn_n(block, i)))
break;
}
- if (i == irn_arity) {
+ if (i < 0) {
ir_graph *irg = get_irn_irg(block);
/* the start block is never dead */
if (block != get_irg_start_block(irg)
- && block != get_irg_end_block(irg))
+ && block != get_irg_end_block(irg)) {
+ /*
+ * Do NOT kill control flow without setting
+ * the block to dead of bad things can happen:
+ * We get a Block that is not reachable be irg_block_walk()
+ * but can be found by irg_walk()!
+ */
+ set_Block_dead(block);
return new_Bad();
+ }
}
}
}
* Beware: we can only read the block of a non-floating node.
*/
if (is_irn_pinned_in_irg(node) &&
- is_Block_dead(get_nodes_block(node)))
+ is_Block_dead(get_nodes_block(skip_Proj(node))))
return new_Bad();
for (i = 0; i < irn_arity; i++) {