if (classify_tarval(value_of(b)) == TV_CLASSIFY_ONE) { /* div(x, 1) == x */
/* Turn Div into a tuple (mem, bad, a) */
ir_node *mem = get_Div_mem(n);
- turn_into_tuple(n, 3);
+ turn_into_tuple(n, pn_Div_max);
set_Tuple_pred(n, pn_Div_M, mem);
set_Tuple_pred(n, pn_Div_X_except, new_Bad()); /* no exception */
set_Tuple_pred(n, pn_Div_res, a);
ir_node *mem = get_Div_mem(n);
ir_mode *mode = get_irn_mode(b);
- turn_into_tuple(n, 4);
+ turn_into_tuple(n, pn_DivMod_max);
set_Tuple_pred(n, pn_DivMod_M, mem);
set_Tuple_pred(n, pn_DivMod_X_except, new_Bad()); /* no exception */
set_Tuple_pred(n, pn_DivMod_res_div, a);
}
/**
- * optimize Proj(Tuple) and gigo() for ProjX in Bad block
+ * optimize Proj(Tuple) and gigo() for ProjX in Bad block,
+ * ProjX(Load) and ProjX(Store)
*/
static ir_node *equivalent_node_Proj(ir_node *n)
{
/* Remove dead control flow -- early gigo(). */
n = new_Bad();
}
+ else if (get_opt_ldst_only_null_ptr_exceptions()) {
+ ir_op *op = get_irn_op(a);
+
+ if (op == op_Load || op == op_Store) {
+ /* get the load/store address */
+ ir_node *addr = get_irn_n(a, 1);
+ if (value_not_null(addr)) {
+ /* this node may float */
+ set_irn_pinned(a, op_pin_state_floats);
+ DBG_OPT_EXC_REM(n);
+ return new_Bad();
+ }
+ }
+ }
}
return n;
* rare case: two identical Confirms one after another,
* replace the second one with the first.
*/
- return pred;
+ n = pred;
}
if (pnc == pn_Cmp_Eq) {
ir_node *bound = get_Confirm_bound(n);
return n;
}
+/**
+ * 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);
+ 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, bad, idx) */
+ ret_tuple = 1;
+ }
+ else {
+ ir_node *pred = skip_Proj(idx);
+
+ if (get_irn_op(pred) == op_Bound) {
+ /*
+ * idx was Bounds_check previously, it is still valid if
+ * lower <= pred_lower && pred_upper <= upper.
+ */
+ ir_node *upper = get_Bound_upper(n);
+ if (get_Bound_lower(pred) == lower &&
+ get_Bound_upper(pred) == upper) {
+ /*
+ * One could expect that we simple return the previous
+ * Bound here. However, this would be wrong, as we could
+ * add an exception Proj to a new location than.
+ * So, we must turn in into a tuple
+ */
+ ret_tuple = 1;
+ }
+ }
+ }
+ if (ret_tuple) {
+ /* Turn Bound into a tuple (mem, bad, idx) */
+ ir_node *mem = get_Bound_mem(n);
+ turn_into_tuple(n, pn_Bound_max);
+ set_Tuple_pred(n, pn_Bound_M_regular, mem);
+ set_Tuple_pred(n, pn_Bound_X_except, new_Bad()); /* no exception */
+ set_Tuple_pred(n, pn_Bound_res, idx);
+ set_Tuple_pred(n, pn_Bound_M_except, mem);
+ }
+ return n;
+}
+
/**
* equivalent_node() returns a node equivalent to input n. It skips all nodes that
* perform no actual computation, as, e.g., the Id nodes. It does not create
CASE(Cmp);
CASE(Confirm);
CASE(CopyB);
+ CASE(Bound);
default:
/* leave NULL */;
}
}
/**
- * Do the AddSub optimization, then Transform Add(a,a) into Mul(a, 2)
+ * Do the AddSub optimization, then Transform
+ * Add(a,a) -> Mul(a, 2)
+ * Add(Mul(a, x), a) -> Mul(a, x+1)
* if the mode is integer or float.
* Transform Add(a,-b) into Sub(a,b).
* Reassociation might fold this further.
mode = get_irn_mode(n);
if (mode_is_num(mode)) {
ir_node *a = get_Add_left(n);
+ ir_node *b = get_Add_right(n);
- if (a == get_Add_right(n)) {
+ if (a == b) {
ir_node *block = get_irn_n(n, -1);
n = new_rd_Mul(
mode);
DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_A_A);
}
- else {
- ir_node *b = get_Add_right(n);
-
- if (get_irn_op(a) == op_Minus) {
- n = new_rd_Sub(
- get_irn_dbg_info(n),
- current_ir_graph,
- get_irn_n(n, -1),
- b,
- get_Minus_op(a),
- mode);
- DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_A_MINUS_B);
+ else if (get_irn_op(a) == op_Minus) {
+ n = new_rd_Sub(
+ get_irn_dbg_info(n),
+ current_ir_graph,
+ get_irn_n(n, -1),
+ b,
+ get_Minus_op(a),
+ mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_A_MINUS_B);
+ }
+ else if (get_irn_op(b) == op_Minus) {
+ n = new_rd_Sub(
+ get_irn_dbg_info(n),
+ current_ir_graph,
+ get_irn_n(n, -1),
+ a,
+ get_Minus_op(b),
+ mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_A_MINUS_B);
+ }
+ /* 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);
+
+ if (b == ma) {
+ ir_node *blk = get_irn_n(n, -1);
+ n = new_rd_Mul(
+ get_irn_dbg_info(n), current_ir_graph, blk,
+ ma,
+ new_rd_Add(
+ get_irn_dbg_info(n), current_ir_graph, blk,
+ mb,
+ new_r_Const_long(current_ir_graph, blk, mode, 1),
+ mode),
+ mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_MUL_A_X_A);
}
- else if (get_irn_op(b) == op_Minus) {
- n = new_rd_Sub(
- get_irn_dbg_info(n),
- current_ir_graph,
- get_irn_n(n, -1),
- a,
- get_Minus_op(b),
- mode);
- DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_A_MINUS_B);
+ else if (b == mb) {
+ ir_node *blk = get_irn_n(n, -1);
+ n = new_rd_Mul(
+ get_irn_dbg_info(n), current_ir_graph, blk,
+ mb,
+ new_rd_Add(
+ get_irn_dbg_info(n), current_ir_graph, blk,
+ ma,
+ new_r_Const_long(current_ir_graph, blk, mode, 1),
+ mode),
+ mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_MUL_A_X_A);
+ }
+ }
+ /* 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);
+
+ if (a == ma) {
+ ir_node *blk = get_irn_n(n, -1);
+ n = new_rd_Mul(
+ get_irn_dbg_info(n), current_ir_graph, blk,
+ ma,
+ new_rd_Add(
+ get_irn_dbg_info(n), current_ir_graph, blk,
+ mb,
+ new_r_Const_long(current_ir_graph, blk, mode, 1),
+ mode),
+ mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_MUL_A_X_A);
+ }
+ else if (a == mb) {
+ ir_node *blk = get_irn_n(n, -1);
+ n = new_rd_Mul(
+ get_irn_dbg_info(n), current_ir_graph, blk,
+ mb,
+ new_rd_Add(
+ get_irn_dbg_info(n), current_ir_graph, blk,
+ ma,
+ new_r_Const_long(current_ir_graph, blk, mode, 1),
+ mode),
+ mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_MUL_A_X_A);
}
}
}
}
/**
- * Do the AddSub optimization, then Transform Sub(0,a) into Minus(a).
+ * Do the AddSub optimization, then Transform
+ * Sub(0,a) -> Minus(a)
+ * Sub(Mul(a, x), a) -> Mul(a, x-1)
*/
static ir_node *transform_node_Sub(ir_node *n)
{
ir_mode *mode;
ir_node *oldn = n;
+ ir_node *a, *b;
n = transform_node_AddSub(n);
mode = get_irn_mode(n);
- if (mode_is_num(mode) && (classify_Const(get_Sub_left(n)) == CNST_NULL)) {
+ a = get_Sub_left(n);
+ b = get_Sub_right(n);
+ if (mode_is_num(mode) && (classify_Const(a) == CNST_NULL)) {
n = new_rd_Minus(
get_irn_dbg_info(n),
current_ir_graph,
get_irn_n(n, -1),
- get_Sub_right(n),
+ b,
mode);
DBG_OPT_ALGSIM0(oldn, n, FS_OPT_SUB_0_A);
}
+ /* 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);
+
+ if (ma == b) {
+ ir_node *blk = get_irn_n(n, -1);
+ n = new_rd_Mul(
+ get_irn_dbg_info(n),
+ current_ir_graph, blk,
+ ma,
+ new_rd_Sub(
+ get_irn_dbg_info(n),
+ current_ir_graph, blk,
+ mb,
+ new_r_Const_long(current_ir_graph, blk, mode, 1),
+ mode),
+ mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_SUB_MUL_A_X_A);
+ }
+ else if (mb == b) {
+ ir_node *blk = get_irn_n(n, -1);
+ n = new_rd_Mul(
+ get_irn_dbg_info(n),
+ current_ir_graph, blk,
+ mb,
+ new_rd_Sub(
+ get_irn_dbg_info(n),
+ current_ir_graph, blk,
+ ma,
+ new_r_Const_long(current_ir_graph, blk, mode, 1),
+ mode),
+ mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_SUB_MUL_A_X_A);
+ }
+ }
return n;
}
/* Turn Mod into a tuple (mem, bad, value) */
ir_node *mem = get_Mod_mem(n);
- turn_into_tuple(n, 3);
+ turn_into_tuple(n, pn_Mod_max);
set_Tuple_pred(n, pn_Mod_M, mem);
set_Tuple_pred(n, pn_Mod_X_except, new_Bad());
set_Tuple_pred(n, pn_Mod_res, value);
if (evaluated) { /* replace by tuple */
ir_node *mem = get_DivMod_mem(n);
- turn_into_tuple(n, 4);
+ turn_into_tuple(n, pn_DivMod_max);
set_Tuple_pred(n, pn_DivMod_M, mem);
set_Tuple_pred(n, pn_DivMod_X_except, new_Bad()); /* no exception */
set_Tuple_pred(n, pn_DivMod_res_div, a);
/* 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));
- turn_into_tuple(n, 2);
+ 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, jmp);
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 */
if (proj_nr == pn_Mod_X_except) {
/* we found an exception handler, remove it */
+ DBG_OPT_EXC_REM(proj);
return new_Bad();
} else if (proj_nr == pn_Mod_M) {
/* the memory Proj can be removed */
if (proj_nr == pn_DivMod_X_except) {
/* we found an exception handler, remove it */
+ DBG_OPT_EXC_REM(proj);
return new_Bad();
}
else if (proj_nr == pn_DivMod_M) {
* 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;
* 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;