From: Michael Beck Date: Wed, 28 Jun 2006 15:21:40 +0000 (+0000) Subject: Add Sub(Sub(x, y), b) -> Sub(x, Add(y,b)) Transformation X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=11514f0e1c557ad9df469a2042a3ea7be39f6789;hp=54473f46aefff029b5dc2908ec4d9ec0765221a5;p=libfirm Add Sub(Sub(x, y), b) -> Sub(x, Add(y,b)) Transformation [r7962] --- diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c index dc1e2dadc..000038bdf 100644 --- a/ir/ir/iropt.c +++ b/ir/ir/iropt.c @@ -1881,6 +1881,7 @@ static ir_node *transform_node_Add(ir_node *n) * Do the AddSub optimization, then Transform * Sub(0,a) -> Minus(a) * Sub(Mul(a, x), a) -> Mul(a, x-1) + * Sub(Sub(x, y), b) -> Sub(x, Add(y,b)) */ static ir_node *transform_node_Sub(ir_node *n) { @@ -1938,6 +1939,37 @@ static ir_node *transform_node_Sub(ir_node *n) DBG_OPT_ALGSIM0(oldn, n, FS_OPT_SUB_MUL_A_X_A); } } + else if (get_irn_op(a) == op_Sub) { + ir_node *x = get_Sub_left(a); + ir_node *y = get_Sub_right(a); + ir_node *blk = get_irn_n(n, -1); + ir_mode *m_b = get_irn_mode(b); + ir_mode *m_y = get_irn_mode(y); + ir_node *add; + + /* Determine the right mode for the Add. */ + if (m_b == m_y) + mode = m_b; + else if (mode_is_reference(m_b)) + mode = m_b; + else if (mode_is_reference(m_y)) + mode = m_y; + else { + /* + * Both modes are different but none is reference, + * happens for instance in SubP(SubP(P, Iu), Is). + * We have two possibilities here: Cast or ignore. + * Currently we ignore this case. + */ + return n; + } + + 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); + } return n; } diff --git a/ir/stat/firmstat.h b/ir/stat/firmstat.h index 1974dd96d..8667a3a42 100644 --- a/ir/stat/firmstat.h +++ b/ir/stat/firmstat.h @@ -43,6 +43,7 @@ enum firmstat_optimizations_t { FS_OPT_ADD_MUL_A_X_A, /**< a * x + a = a * (x + 1) */ FS_OPT_SUB_0_A, /**< 0 - a = -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_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 */ diff --git a/ir/stat/stat_dmp.c b/ir/stat/stat_dmp.c index 9f70d5b28..36bf98bc8 100644 --- a/ir/stat/stat_dmp.c +++ b/ir/stat/stat_dmp.c @@ -57,6 +57,7 @@ static const struct { { FS_OPT_ADD_MUL_A_X_A, "algebraic simplification: a * x + a = a * (x + 1)" }, { FS_OPT_SUB_0_A, "algebraic simplification: 0 - a = -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_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" },