From: Michael Beck Date: Thu, 13 Sep 2007 16:36:06 +0000 (+0000) Subject: add more algebraic optimizations X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=cb024ed4f9499e4654574a3af70d7f0daf336996;p=libfirm add more algebraic optimizations [r15791] --- diff --git a/include/libfirm/firmstat.h b/include/libfirm/firmstat.h index 94953d90b..e909a0aff 100644 --- a/include/libfirm/firmstat.h +++ b/include/libfirm/firmstat.h @@ -57,9 +57,11 @@ enum firmstat_optimizations_t { 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 */ @@ -83,6 +85,7 @@ enum firmstat_optimizations_t { 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 */ diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c index 5306e88ba..3870ba9e0 100644 --- a/ir/ir/iropt.c +++ b/ir/ir/iropt.c @@ -1121,7 +1121,7 @@ static ir_node *equivalent_node_Or(ir_node *n) { } /* 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; @@ -1132,13 +1132,35 @@ static ir_node *equivalent_node_And(ir_node *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 */ @@ -2001,23 +2023,33 @@ static ir_node *transform_node_Add(ir_node *n) { } } } - /* 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); @@ -2270,11 +2302,26 @@ restart: 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 */ @@ -2812,7 +2859,6 @@ static ir_node *transform_bitwise_distributive(ir_node *n, set_binop_right(n, c); } - DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_SHIFT_AND); return n; } @@ -2825,14 +2871,14 @@ static ir_node *transform_bitwise_distributive(ir_node *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) { @@ -2847,6 +2893,45 @@ static ir_node *transform_node_And(ir_node *n) { 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); @@ -3299,6 +3384,8 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) { changed |= 1; } break; + default: + break; } } diff --git a/ir/stat/stat_dmp.c b/ir/stat/stat_dmp.c index b652af86e..944f3e82b 100644 --- a/ir/stat/stat_dmp.c +++ b/ir/stat/stat_dmp.c @@ -75,9 +75,11 @@ static const struct { { 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" }, @@ -101,6 +103,7 @@ static const struct { { 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" },