return tarval_bad;
}
+/**
+ * return the value of a Carry
+ * Special : a op 0, 0 op b
+ */
+static tarval *computed_value_Carry(ir_node *n)
+{
+ ir_node *a = get_binop_left(n);
+ ir_node *b = get_binop_right(n);
+ ir_mode *m = get_irn_mode(n);
+
+ tarval *ta = value_of(a);
+ tarval *tb = value_of(b);
+
+ if ((ta != tarval_bad) && (tb != tarval_bad)) {
+ tarval_add(ta, tb);
+ return tarval_carry() ? get_mode_one(m) : get_mode_null(m);
+ } else {
+ if ( (classify_tarval(ta) == TV_CLASSIFY_NULL)
+ || (classify_tarval(tb) == TV_CLASSIFY_NULL))
+ return get_mode_null(m);
+ }
+ return tarval_bad;
+}
+
+/**
+ * return the value of a Borrow
+ * Special : a op 0
+ */
+static tarval *computed_value_Borrow(ir_node *n)
+{
+ ir_node *a = get_binop_left(n);
+ ir_node *b = get_binop_right(n);
+ ir_mode *m = get_irn_mode(n);
+
+ tarval *ta = value_of(a);
+ tarval *tb = value_of(b);
+
+ if ((ta != tarval_bad) && (tb != tarval_bad)) {
+ return tarval_cmp(ta, tb) == pn_Cmp_Lt ? get_mode_one(m) : get_mode_null(m);
+ } else if (classify_tarval(ta) == TV_CLASSIFY_NULL) {
+ return get_mode_null(m);
+ }
+ return tarval_bad;
+}
+
/**
* return the value of an unary Minus
*/
return tarval_bad;
}
+/**
+ * Calculate the value of a Psi: can be evaluated, if a condition is true
+ * and all previous conditions are false. If all conditions are false
+ * we evaluate to the default one.
+ */
+static tarval *computed_value_Psi(ir_node *n)
+{
+ return tarval_bad;
+}
+
/**
* calculate the value of a Confirm: can be evaluated,
* if it has the form Confirm(x, '=', Const).
CASE(Shr);
CASE(Shrs);
CASE(Rot);
+ CASE(Carry);
+ CASE(Borrow);
CASE(Conv);
CASE(Proj);
CASE(Mux);
+ CASE(Psi);
CASE(Confirm);
default:
/* leave NULL */;
#undef CASE
}
-#if 0
-/* returns 1 if the a and b are pointers to different locations. */
-static bool
-different_identity (ir_node *a, ir_node *b)
-{
- assert (mode_is_reference(get_irn_mode (a))
- && mode_is_reference(get_irn_mode (b)));
-
- if (get_irn_op (a) == op_Proj && get_irn_op(b) == op_Proj) {
- ir_node *a1 = get_Proj_pred (a);
- ir_node *b1 = get_Proj_pred (b);
- if (a1 != b1 && get_irn_op (a1) == op_Alloc
- && get_irn_op (b1) == op_Alloc)
- return 1;
- }
- return 0;
-}
-#endif
-
/**
* Returns a equivalent block for another block.
* If the block has only one predecessor, this is
}
}
else if (get_opt_unreachable_code() &&
- (n != current_ir_graph->start_block) &&
- (n != current_ir_graph->end_block) ) {
+ (n != get_irg_start_block(current_ir_graph)) &&
+ (n != get_irg_end_block(current_ir_graph)) ) {
int i;
/* If all inputs are dead, this block is dead too, except if it is
return n;
}
-/* Several optimizations:
+/**
+ Several optimizations:
- no Phi in start block.
- remove Id operators that are inputs to Phi
- fold Phi-nodes, iff they have only one predecessor except
themselves.
-*/
+ */
static ir_node *equivalent_node_Phi(ir_node *n)
{
int i, n_preds;
ir_node *oldn = n;
ir_node *block = NULL; /* to shutup gcc */
ir_node *first_val = NULL; /* to shutup gcc */
- ir_node *scnd_val = NULL; /* to shutup gcc */
if (!get_opt_normalize()) return 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 == current_ir_graph->start_block)) /* There should be no Phi nodes */
- return new_Bad(); /* in the Start Block. */
+ (block == get_irg_start_block(current_ir_graph))) /* There should be no Phi nodes */
+ return new_Bad(); /* in the Start Block. */
if (n_preds == 0) return n; /* Phi of dead Region without predecessors. */
return new_Bad();
}
- scnd_val = NULL;
-
- /* follow_Id () for rest of inputs, determine if any of these
+ /* search for rest of inputs, determine if any of these
are non-self-referencing */
while (++i < n_preds) {
- scnd_val = get_Phi_pred(n, i);
+ ir_node *scnd_val = get_Phi_pred(n, i);
if ( (scnd_val != n)
&& (scnd_val != first_val)
#if 1
/* Fold, if no multiple distinct non-self-referencing inputs */
n = first_val;
DBG_OPT_PHI(oldn, n);
- } else {
- /* skip the remaining Ids (done in get_Phi_pred). */
- /* superfluous, since we walk all to propagate Block's Bads.
- while (++i < n_preds) get_Phi_pred(n, i); */
+ }
+ return n;
+}
+
+/**
+ Several optimizations:
+ - no Sync in start block.
+ - fold Sync-nodes, iff they have only one predecessor except
+ themselves.
+ @fixme: are there loop's in Sync's
+ */
+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;
+
+ n_preds = get_Sync_n_preds(n);
+
+ /* 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. */
+ }
+ }
+
+ 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;
+ }
+
+ if (i >= n_preds) {
+ /* Fold, if no multiple distinct non-self-referencing inputs */
+ n = first_val;
+ DBG_OPT_SYNC(oldn, n);
}
return n;
}
/* get the load/store address */
ir_node *addr = get_irn_n(a, 1);
if (value_not_null(addr)) {
- /* this node may float */
+ /* this node may float if it did not depend on a Confirm */
set_irn_pinned(a, op_pin_state_floats);
DBG_OPT_EXC_REM(n);
return new_Bad();
return n;
}
+/**
+ * Returns a equivalent node of a Psi: if a condition is true
+ * and all previous conditions are false we know its value.
+ * If all conditions are false its value is the default one.
+ */
+static ir_node *equivalent_node_Psi(ir_node *n) {
+ return n;
+}
+
/**
* Optimize -a CMP -b into b CMP a.
* This works only for for modes where unary Minus
turn_into_tuple(n, pn_CopyB_max);
set_Tuple_pred(n, pn_CopyB_M, mem);
set_Tuple_pred(n, pn_CopyB_X_except, new_Bad()); /* no exception */
- set_Tuple_pred(n, pn_Call_M_except, new_Bad());
+ set_Tuple_pred(n, pn_CopyB_M_except, new_Bad());
}
return n;
}
CASE(Conv);
CASE(Cast);
CASE(Phi);
+ CASE(Sync);
CASE(Proj);
CASE(Id);
CASE(Mux);
+ CASE(Psi);
CASE(Cmp);
CASE(Confirm);
CASE(CopyB);
mode);
DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_A_MINUS_B);
}
- else if (get_irn_op(a) == op_Mul) {
+ /* do NOT execute this code if reassociation is enabled, it does the inverse! */
+ else if (!get_opt_reassociation() && get_irn_op(a) == op_Mul) {
ir_node *ma = get_Mul_left(a);
ir_node *mb = get_Mul_right(a);
DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_MUL_A_X_A);
}
}
- else if (get_irn_op(b) == op_Mul) {
+ /* do NOT execute this code if reassociation is enabled, it does the inverse! */
+ else if (!get_opt_reassociation() && get_irn_op(b) == op_Mul) {
ir_node *ma = get_Mul_left(b);
ir_node *mb = get_Mul_right(b);
mode);
DBG_OPT_ALGSIM0(oldn, n, FS_OPT_SUB_0_A);
}
- else if (get_irn_op(a) == op_Mul) {
+ /* do NOT execute this code if reassociation is enabled, it does the inverse! */
+ else if (get_opt_reassociation() && get_irn_op(a) == op_Mul) {
ir_node *ma = get_Mul_left(a);
ir_node *mb = get_Mul_right(a);
/* div(x, y) && y != 0 */
proj_nr = get_Proj_proj(proj);
- /* this node may float */
+ /* this node may float if it did not depend on a Confirm */
set_irn_pinned(n, op_pin_state_floats);
if (proj_nr == pn_Div_X_except) {
/* we found an exception handler, remove it */
DBG_OPT_EXC_REM(proj);
return new_Bad();
- } else if (proj_nr == pn_Div_M) {
- /* the memory Proj can be removed */
+ }
+ else if (proj_nr == pn_Div_M) {
ir_node *res = get_Div_mem(n);
- set_Div_mem(n, get_irg_no_mem(current_ir_graph));
-
+ /* the memory Proj can only be removed if we divide by a
+ real constant, but the node never produce a new memory */
+ if (value_of(b) != tarval_bad) {
+ /* this is a Div by a const, we can remove the memory edge */
+ set_Div_mem(n, get_irg_no_mem(current_ir_graph));
+ }
return res;
}
}
/* mod(x, y) && y != 0 */
proj_nr = get_Proj_proj(proj);
- /* this node may float */
+ /* this node may float if it did not depend on a Confirm */
set_irn_pinned(n, op_pin_state_floats);
if (proj_nr == pn_Mod_X_except) {
DBG_OPT_EXC_REM(proj);
return new_Bad();
} else if (proj_nr == pn_Mod_M) {
- /* the memory Proj can be removed */
ir_node *res = get_Mod_mem(n);
- set_Mod_mem(n, get_irg_no_mem(current_ir_graph));
-
+ /* the memory Proj can only be removed if we divide by a
+ real constant, but the node never produce a new memory */
+ if (value_of(b) != tarval_bad) {
+ /* this is a Mod by a const, we can remove the memory edge */
+ set_Mod_mem(n, get_irg_no_mem(current_ir_graph));
+ }
return res;
}
else if (proj_nr == pn_Mod_res && get_Mod_left(n) == b) {
/* DivMod(x, y) && y != 0 */
proj_nr = get_Proj_proj(proj);
- /* this node may float */
+ /* this node may float if it did not depend on a Confirm */
set_irn_pinned(n, op_pin_state_floats);
if (proj_nr == pn_DivMod_X_except) {
return new_Bad();
}
else if (proj_nr == pn_DivMod_M) {
- /* the memory Proj can be removed */
ir_node *res = get_DivMod_mem(n);
- set_DivMod_mem(n, get_irg_no_mem(current_ir_graph));
-
+ /* the memory Proj can only be removed if we divide by a
+ real constant, but the node never produce a new memory */
+ if (value_of(b) != tarval_bad) {
+ /* this is a DivMod by a const, we can remove the memory edge */
+ set_DivMod_mem(n, get_irg_no_mem(current_ir_graph));
+ }
return res;
}
else if (proj_nr == pn_DivMod_res_mod && get_DivMod_left(n) == b) {
proj_nr = get_inversed_pnc(proj_nr);
changed |= 1;
}
- else if (left > right) {
+ else if (get_irn_idx(left) > get_irn_idx(right)) {
ir_node *t = left;
left = right;
}
}
} /* mode_is_int */
- }
+
+ /*
+ * optimization for AND:
+ * Optimize:
+ * And(x, C) == C ==> And(x, C) != 0
+ * And(x, C) != C ==> And(X, C) == 0
+ *
+ * if C is a single Bit constant.
+ */
+ if ((proj_nr == pn_Cmp_Eq || proj_nr == pn_Cmp_Lg) &&
+ (get_irn_op(left) == op_And)) {
+ if (is_single_bit_tarval(tv)) {
+ /* check for Constant's match. We have check hare the tarvals,
+ because our const might be changed */
+ ir_node *la = get_And_left(left);
+ ir_node *ra = get_And_right(left);
+ if ((is_Const(la) && get_Const_tarval(la) == tv) ||
+ (is_Const(ra) && get_Const_tarval(ra) == tv)) {
+ /* fine: do the transformation */
+ tv = get_mode_null(get_tarval_mode(tv));
+ proj_nr ^= pn_Cmp_Leg;
+ changed |= 2;
+ }
+ }
+ }
+ } /* tarval != bad */
}
if (changed) {
return arch_transform_node_Mux(n);
}
+/**
+ * Optimize a Psi into some simpler cases.
+ */
+static ir_node *transform_node_Psi(ir_node *n) {
+ if (is_Mux(n))
+ return transform_node_Mux(n);
+
+ return n;
+}
+
/**
* Tries several [inplace] [optimizing] transformations and returns an
* equivalent node. The difference to equivalent_node() is that these
CASE(Shl);
CASE(End);
CASE(Mux);
+ CASE(Psi);
default:
/* leave NULL */;
}
* Compare function for two nodes in the hash table. Gets two
* nodes as parameters. Returns 0 if the nodes are a cse.
*/
-static int identities_cmp(const void *elt, const void *key)
+int identities_cmp(const void *elt, const void *key)
{
ir_node *a, *b;
int i, irn_arity_a;
ir_node *r = get_binop_right(n);
/* for commutative operators perform a OP b == b OP a */
- if (l > r) {
+ if (get_irn_idx(l) > get_irn_idx(r)) {
set_binop_left(n, r);
set_binop_right(n, l);
}
* Looks up the node in a hash table, enters it in the table
* if it isn't there yet.
*/
-static ir_node *
+ir_node *
identify_remember (pset *value_table, ir_node *n)
{
ir_node *o = NULL;
if (is_Bad(pred))
return new_Bad();
+#if 0
+ /* Propagating Unknowns here seems to be a bad idea, because
+ sometimes we need a node as a input and did not want that
+ it kills it's user.
+ However, i might be useful to move this into a later phase
+ (it you thing optimizing such code is useful). */
if (is_Unknown(pred) && mode_is_data(get_irn_mode(node)))
return new_Unknown(get_irn_mode(node));
+#endif
}
}
#if 0
edges_node_deleted(n, current_ir_graph);
/* evaluation was successful -- replace the node. */
- obstack_free(current_ir_graph->obst, n);
+ irg_kill_node(current_ir_graph, n);
nw = new_Const(get_tarval_mode (tv), tv);
if (old_tp && get_type_mode(old_tp) == get_tarval_mode (tv))
edges_node_deleted(oldn, current_ir_graph);
/* We found an existing, better node, so we can deallocate the old node. */
- obstack_free (current_ir_graph->obst, oldn);
-
+ irg_kill_node(current_ir_graph, oldn);
return n;
}