FS_OPT_MINUS_SUB, /**< - (a - b) = b - a */
FS_OPT_SUB_MUL_A_X_A, /**< a * x - a = a * (x - 1) */
FS_OPT_SUB_SUB_X_Y_Z, /**< (x - y) - z = x - (y + z) */
+ FS_OPT_SUB_C_NOT_X, /**< c - ~a = a + (c+1) */
FS_OPT_MUL_MINUS_1, /**< a * -1 = -a */
FS_OPT_OR, /**< a | a = a | 0 = 0 | a = a */
FS_OPT_AND, /**< a & 0b1...1 = 0b1...1 & a = a & a = a */
+ FS_OPT_TO_EOR, /**< (a|b) & ~(a&b) = a^b */
FS_OPT_EOR_A_A, /**< a ^ a = 0 */
FS_OPT_EOR_TO_NOT_BOOL, /**< bool ^ 1 = !bool */
FS_OPT_EOR_TO_NOT, /**< x ^ 0b1..1 = ~x */
FS_OPT_MINUS_NOT, /**< -(~x) = x + 1 */
FS_OPT_NOT_MINUS_1, /**< ~(x - 1) = -x */
FS_OPT_NOT_PLUS_1, /**< ~x + 1 = -x */
+ FS_OPT_ADD_X_NOT_X, /**< ~x + x = -1 */
FS_OPT_FP_INV_MUL, /**< x / y = x * (1.0/y) */
FS_OPT_CONST_PHI, /**< Constant evaluation on Phi */
FS_BE_IA32_LEA, /**< Lea was created */
} /* equivalent_node_Or */
/**
- * Optimize a & 0b1...1 = 0b1...1 & a = a & a = a.
+ * Optimize a & 0b1...1 = 0b1...1 & a = a & a = (a|X) & a = a.
*/
static ir_node *equivalent_node_And(ir_node *n) {
ir_node *oldn = n;
if (a == b) {
n = a; /* And has it's own neutral element */
DBG_OPT_ALGSIM0(oldn, n, FS_OPT_AND);
- } else if (classify_tarval(value_of(a)) == TV_CLASSIFY_ALL_ONE) {
+ return n;
+ }
+ if (classify_tarval(value_of(a)) == TV_CLASSIFY_ALL_ONE) {
n = b;
DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_AND);
- } else if (classify_tarval(value_of(b)) == TV_CLASSIFY_ALL_ONE) {
+ return n;
+ }
+ if (classify_tarval(value_of(b)) == TV_CLASSIFY_ALL_ONE) {
n = a;
DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_AND);
+ return n;
+ }
+ if (is_Or(a)) {
+ if (b == get_Or_left(a) || b == get_Or_right(a)) {
+ /* (a|X) & a */
+ n = b;
+ DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_AND);
+ return n;
+ }
}
+ if (is_Or(b)) {
+ if (a == get_Or_left(b) || a == get_Or_right(b)) {
+ /* a & (a|X) */
+ n = a;
+ DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_AND);
+ return n;
+ }
+ }
+
return n;
} /* equivalent_node_And */
}
}
}
- /* Here we rely on constants be on the RIGHT side */
- if (get_mode_arithmetic(mode) == irma_twos_complement &&
- is_Not(a) && classify_Const(b) == CNST_ONE) {
- /* ~x + 1 = -x */
- ir_node *op = get_Not_op(a);
- ir_node *blk = get_irn_n(n, -1);
- n = new_rd_Minus(get_irn_dbg_info(n), current_ir_graph, blk, op, mode);
- DBG_OPT_ALGSIM0(oldn, n, FS_OPT_NOT_PLUS_1);
- return n;
+ if (get_mode_arithmetic(mode) == irma_twos_complement) {
+ /* Here we rely on constants be on the RIGHT side */
+ if (is_Not(a)) {
+ ir_node *op = get_Not_op(a);
+
+ if (classify_Const(b) == CNST_ONE) {
+ /* ~x + 1 = -x */
+ ir_node *blk = get_irn_n(n, -1);
+ n = new_rd_Minus(get_irn_dbg_info(n), current_ir_graph, blk, op, mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_NOT_PLUS_1);
+ return n;
+ }
+ if (a == b) {
+ /* ~x + x = -1 */
+ ir_node *blk = get_irn_n(n, -1);
+ n = new_r_Const(current_ir_graph, blk, mode, get_mode_minus_one(mode));
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_X_NOT_X);
+ return n;
+ }
+ }
}
}
return n;
} /* transform_node_Add */
/* returns -cnst */
-static ir_node* const_negate(ir_node* cnst)
-{
+static ir_node *const_negate(ir_node *cnst) {
tarval *tv = tarval_neg(get_Const_tarval(cnst));
dbg_info *dbgi = get_irn_dbg_info(cnst);
ir_graph *irg = get_irn_irg(cnst);
add = new_r_Add(current_ir_graph, blk, y, b, mode);
- set_Sub_left(n, x);
- set_Sub_right(n, add);
- DBG_OPT_ALGSIM0(n, n, FS_OPT_SUB_SUB_X_Y_Z);
+ n = new_rd_Sub(get_irn_dbg_info(n), current_ir_graph, blk, x, add, mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_SUB_SUB_X_Y_Z);
return n;
}
+
+ if (get_mode_arithmetic(mode) == irma_twos_complement) {
+ if (is_Const(a) && is_Not(b)) {
+ /* c - ~X = X + (c+1) */
+ tarval *tv = get_Const_tarval(a);
+
+ tv = tarval_add(tv, get_mode_one(mode));
+ if (tv != tarval_bad) {
+ ir_node *blk = get_irn_n(n, -1);
+ ir_node *c = new_r_Const(current_ir_graph, blk, mode, tv);
+ n = new_rd_Add(get_irn_dbg_info(n), current_ir_graph, blk, get_Not_op(b), c, mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_SUB_C_NOT_X);
+ return n;
+ }
+ }
+ }
return n;
} /* transform_node_Sub */
set_binop_right(n, c);
}
-
DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_SHIFT_AND);
return n;
}
* Transform an And.
*/
static ir_node *transform_node_And(ir_node *n) {
- ir_node *c, *oldn;
+ ir_node *c, *oldn = n;
ir_node *a = get_And_left(n);
ir_node *b = get_And_right(n);
HANDLE_BINOP_PHI(tarval_and, a,b,c);
/* we can evaluate 2 Projs of the same Cmp */
- if(get_irn_mode(n) == mode_b && is_Proj(a) && is_Proj(b)) {
+ if (get_irn_mode(n) == mode_b && is_Proj(a) && is_Proj(b)) {
ir_node *pred_a = get_Proj_pred(a);
ir_node *pred_b = get_Proj_pred(b);
if(pred_a == pred_b) {
new_pnc);
}
}
+ if (is_Or(a)) {
+ if (is_Not(b)) {
+ ir_node *op = get_Not_op(b);
+ if (is_And(op)) {
+ ir_node *ba = get_And_left(op);
+ ir_node *bb = get_And_right(op);
+
+ /* it's enough to test the following cases due to normalization! */
+ if (get_Or_left(a) == ba && get_Or_right(a) == bb) {
+ /* (a|b) & ~(a&b) = a^b */
+ ir_node *block = get_nodes_block(n);
+
+ n = new_rd_Eor(get_irn_dbg_info(n), current_ir_graph, block, ba, bb, get_irn_mode(n));
+ DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_TO_EOR);
+ return n;
+ }
+ }
+ }
+ }
+ if (is_Or(b)) {
+ if (is_Not(a)) {
+ ir_node *op = get_Not_op(a);
+ if (is_And(op)) {
+ ir_node *aa = get_And_left(op);
+ ir_node *ab = get_And_right(op);
+
+ /* it's enough to test the following cases due to normalization! */
+ if (get_Or_left(b) == aa && get_Or_right(b) == ab) {
+ /* (a|b) & ~(a&b) = a^b */
+ ir_node *block = get_nodes_block(n);
+
+ n = new_rd_Eor(get_irn_dbg_info(n), current_ir_graph, block, aa, ab, get_irn_mode(n));
+ DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_TO_EOR);
+ return n;
+ }
+ }
+ }
+
+ }
n = transform_bitwise_distributive(n, transform_node_And);
changed |= 1;
}
break;
+ default:
+ break;
}
}
{ FS_OPT_MINUS_SUB, "algebraic simplification: -(a - b) = b - a" },
{ FS_OPT_SUB_MUL_A_X_A, "algebraic simplification: a * x - a = a * (x - 1)" },
{ FS_OPT_SUB_SUB_X_Y_Z, "algebraic simplification: (x - y) - z = x - (y + z)" },
+ { FS_OPT_SUB_C_NOT_X, "algebraic simplification: c - ~a = a + (c+1)" },
{ FS_OPT_MUL_MINUS_1, "algebraic simplification: a * -1 = -a" },
{ FS_OPT_OR, "algebraic simplification: a | a = a | 0 = 0 | a = a" },
- { FS_OPT_AND, "algebraic simplification: a & 0b1...1 = 0b1...1 & a = a & a = a" },
+ { FS_OPT_AND, "algebraic simplification: a & 0b1...1 = 0b1...1 & a = a & a = (a|X) & a = a" },
+ { FS_OPT_TO_EOR, "algebraic simplification: (a|b) & ~(a&b) = a^b" },
{ FS_OPT_EOR_A_A, "algebraic simplification: a ^ a = 0" },
{ FS_OPT_EOR_TO_NOT_BOOL,"algebraic simplification: bool ^ 1 = !bool" },
{ FS_OPT_EOR_TO_NOT, "algebraic simplification: x ^ 0b1..1 = ~x" },
{ FS_OPT_MINUS_NOT, "algebraic simplification: -(~x) = x + 1" },
{ FS_OPT_NOT_MINUS_1, "algebraic simplification: ~(x - 1) = -x" },
{ FS_OPT_NOT_PLUS_1, "algebraic simplification: ~x + 1 = -x" },
+ { FS_OPT_ADD_X_NOT_X, "algebraic simplification: ~x + x = -1" },
{ FS_OPT_FP_INV_MUL, "algebraic simplification: x / y = x * (1.0/y)" },
{ FS_OPT_CONST_PHI, "constant evaluation on Phi node" },
{ FS_BE_IA32_LEA, "ia32 Backend transformation: Lea was created" },