X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fsimplify-rtx.c;h=ae1fea7e2e47246f652401dcd7ff04977e4ae0ab;hb=59ad801a2550282fa31d5aeb058fd10c8092a08d;hp=c6b0ec812797f5f65427c4ebe1f13d656ecbcffa;hpb=3b723a041d69757c7040407899f739e728aec76d;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index c6b0ec81279..ae1fea7e2e4 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -16,8 +16,8 @@ for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ +Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301, USA. */ #include "config.h" @@ -145,6 +145,7 @@ avoid_constant_pool_reference (rtx x) { rtx c, tmp, addr; enum machine_mode cmode; + HOST_WIDE_INT offset = 0; switch (GET_CODE (x)) { @@ -173,26 +174,40 @@ avoid_constant_pool_reference (rtx x) /* Call target hook to avoid the effects of -fpic etc.... */ addr = targetm.delegitimize_address (addr); + /* Split the address into a base and integer offset. */ + if (GET_CODE (addr) == CONST + && GET_CODE (XEXP (addr, 0)) == PLUS + && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT) + { + offset = INTVAL (XEXP (XEXP (addr, 0), 1)); + addr = XEXP (XEXP (addr, 0), 0); + } + if (GET_CODE (addr) == LO_SUM) addr = XEXP (addr, 1); - if (GET_CODE (addr) != SYMBOL_REF - || ! CONSTANT_POOL_ADDRESS_P (addr)) - return x; - - c = get_pool_constant (addr); - cmode = get_pool_mode (addr); - - /* If we're accessing the constant in a different mode than it was - originally stored, attempt to fix that up via subreg simplifications. - If that fails we have no choice but to return the original memory. */ - if (cmode != GET_MODE (x)) + /* If this is a constant pool reference, we can turn it into its + constant and hope that simplifications happen. */ + if (GET_CODE (addr) == SYMBOL_REF + && CONSTANT_POOL_ADDRESS_P (addr)) { - c = simplify_subreg (GET_MODE (x), c, cmode, 0); - return c ? c : x; + c = get_pool_constant (addr); + cmode = get_pool_mode (addr); + + /* If we're accessing the constant in a different mode than it was + originally stored, attempt to fix that up via subreg simplifications. + If that fails we have no choice but to return the original memory. */ + if (offset != 0 || cmode != GET_MODE (x)) + { + rtx tem = simplify_subreg (GET_MODE (x), c, cmode, offset); + if (tem && CONSTANT_P (tem)) + return tem; + } + else + return c; } - return c; + return x; } /* Make a unary operation by first seeing if it folds and otherwise making @@ -570,7 +585,7 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) target mode is the same as the variable's promotion. */ if (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op) - && SUBREG_PROMOTED_UNSIGNED_P (op) + && SUBREG_PROMOTED_UNSIGNED_P (op) > 0 && GET_MODE (XEXP (op, 0)) == mode) return XEXP (op, 0); @@ -829,9 +844,7 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode, gcc_unreachable (); } - val = trunc_int_for_mode (val, mode); - - return GEN_INT (val); + return gen_int_mode (val, mode); } /* We can do some operations on integer CONST_DOUBLEs. Also allow @@ -1257,46 +1270,69 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, have X (if C is 2 in the example above). But don't make something more expensive than we had before. */ - if (! FLOAT_MODE_P (mode)) + if (SCALAR_INT_MODE_P (mode)) { - HOST_WIDE_INT coeff0 = 1, coeff1 = 1; + HOST_WIDE_INT coeff0h = 0, coeff1h = 0; + unsigned HOST_WIDE_INT coeff0l = 1, coeff1l = 1; rtx lhs = op0, rhs = op1; if (GET_CODE (lhs) == NEG) - coeff0 = -1, lhs = XEXP (lhs, 0); + { + coeff0l = -1; + coeff0h = -1; + lhs = XEXP (lhs, 0); + } else if (GET_CODE (lhs) == MULT && GET_CODE (XEXP (lhs, 1)) == CONST_INT) - coeff0 = INTVAL (XEXP (lhs, 1)), lhs = XEXP (lhs, 0); + { + coeff0l = INTVAL (XEXP (lhs, 1)); + coeff0h = INTVAL (XEXP (lhs, 1)) < 0 ? -1 : 0; + lhs = XEXP (lhs, 0); + } else if (GET_CODE (lhs) == ASHIFT && GET_CODE (XEXP (lhs, 1)) == CONST_INT && INTVAL (XEXP (lhs, 1)) >= 0 && INTVAL (XEXP (lhs, 1)) < HOST_BITS_PER_WIDE_INT) { - coeff0 = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (lhs, 1)); + coeff0l = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (lhs, 1)); + coeff0h = 0; lhs = XEXP (lhs, 0); } if (GET_CODE (rhs) == NEG) - coeff1 = -1, rhs = XEXP (rhs, 0); + { + coeff1l = -1; + coeff1h = -1; + rhs = XEXP (rhs, 0); + } else if (GET_CODE (rhs) == MULT && GET_CODE (XEXP (rhs, 1)) == CONST_INT) { - coeff1 = INTVAL (XEXP (rhs, 1)), rhs = XEXP (rhs, 0); + coeff1l = INTVAL (XEXP (rhs, 1)); + coeff1h = INTVAL (XEXP (rhs, 1)) < 0 ? -1 : 0; + rhs = XEXP (rhs, 0); } else if (GET_CODE (rhs) == ASHIFT && GET_CODE (XEXP (rhs, 1)) == CONST_INT && INTVAL (XEXP (rhs, 1)) >= 0 && INTVAL (XEXP (rhs, 1)) < HOST_BITS_PER_WIDE_INT) { - coeff1 = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (rhs, 1)); + coeff1l = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (rhs, 1)); + coeff1h = 0; rhs = XEXP (rhs, 0); } if (rtx_equal_p (lhs, rhs)) { rtx orig = gen_rtx_PLUS (mode, op0, op1); - tem = simplify_gen_binary (MULT, mode, lhs, - GEN_INT (coeff0 + coeff1)); + rtx coeff; + unsigned HOST_WIDE_INT l; + HOST_WIDE_INT h; + + add_double (coeff0l, coeff0h, coeff1l, coeff1h, &l, &h); + coeff = immed_double_const (l, h, mode); + + tem = simplify_gen_binary (MULT, mode, lhs, coeff); return rtx_cost (tem, SET) <= rtx_cost (orig, SET) ? tem : 0; } @@ -1405,48 +1441,69 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, have X (if C is 2 in the example above). But don't make something more expensive than we had before. */ - if (! FLOAT_MODE_P (mode)) + if (SCALAR_INT_MODE_P (mode)) { - HOST_WIDE_INT coeff0 = 1, coeff1 = 1; + HOST_WIDE_INT coeff0h = 0, negcoeff1h = -1; + unsigned HOST_WIDE_INT coeff0l = 1, negcoeff1l = -1; rtx lhs = op0, rhs = op1; if (GET_CODE (lhs) == NEG) - coeff0 = -1, lhs = XEXP (lhs, 0); + { + coeff0l = -1; + coeff0h = -1; + lhs = XEXP (lhs, 0); + } else if (GET_CODE (lhs) == MULT && GET_CODE (XEXP (lhs, 1)) == CONST_INT) { - coeff0 = INTVAL (XEXP (lhs, 1)), lhs = XEXP (lhs, 0); + coeff0l = INTVAL (XEXP (lhs, 1)); + coeff0h = INTVAL (XEXP (lhs, 1)) < 0 ? -1 : 0; + lhs = XEXP (lhs, 0); } else if (GET_CODE (lhs) == ASHIFT && GET_CODE (XEXP (lhs, 1)) == CONST_INT && INTVAL (XEXP (lhs, 1)) >= 0 && INTVAL (XEXP (lhs, 1)) < HOST_BITS_PER_WIDE_INT) { - coeff0 = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (lhs, 1)); + coeff0l = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (lhs, 1)); + coeff0h = 0; lhs = XEXP (lhs, 0); } if (GET_CODE (rhs) == NEG) - coeff1 = - 1, rhs = XEXP (rhs, 0); + { + negcoeff1l = 1; + negcoeff1h = 0; + rhs = XEXP (rhs, 0); + } else if (GET_CODE (rhs) == MULT && GET_CODE (XEXP (rhs, 1)) == CONST_INT) { - coeff1 = INTVAL (XEXP (rhs, 1)), rhs = XEXP (rhs, 0); + negcoeff1l = -INTVAL (XEXP (rhs, 1)); + negcoeff1h = INTVAL (XEXP (rhs, 1)) <= 0 ? 0 : -1; + rhs = XEXP (rhs, 0); } else if (GET_CODE (rhs) == ASHIFT && GET_CODE (XEXP (rhs, 1)) == CONST_INT && INTVAL (XEXP (rhs, 1)) >= 0 && INTVAL (XEXP (rhs, 1)) < HOST_BITS_PER_WIDE_INT) { - coeff1 = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (rhs, 1)); + negcoeff1l = -(((HOST_WIDE_INT) 1) << INTVAL (XEXP (rhs, 1))); + negcoeff1h = -1; rhs = XEXP (rhs, 0); } if (rtx_equal_p (lhs, rhs)) { rtx orig = gen_rtx_MINUS (mode, op0, op1); - tem = simplify_gen_binary (MULT, mode, lhs, - GEN_INT (coeff0 - coeff1)); + rtx coeff; + unsigned HOST_WIDE_INT l; + HOST_WIDE_INT h; + + add_double (coeff0l, coeff0h, negcoeff1l, negcoeff1h, &l, &h); + coeff = immed_double_const (l, h, mode); + + tem = simplify_gen_binary (MULT, mode, lhs, coeff); return rtx_cost (tem, SET) <= rtx_cost (orig, SET) ? tem : 0; } @@ -1533,6 +1590,16 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, || val != HOST_BITS_PER_WIDE_INT - 1)) return simplify_gen_binary (ASHIFT, mode, op0, GEN_INT (val)); + /* Likewise for multipliers wider than a word. */ + else if (GET_CODE (trueop1) == CONST_DOUBLE + && (GET_MODE (trueop1) == VOIDmode + || GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_INT) + && GET_MODE (op0) == mode + && CONST_DOUBLE_LOW (trueop1) == 0 + && (val = exact_log2 (CONST_DOUBLE_HIGH (trueop1))) >= 0) + return simplify_gen_binary (ASHIFT, mode, op0, + GEN_INT (val + HOST_BITS_PER_WIDE_INT)); + /* x*2 is x+x and x*(-1) is -x */ if (GET_CODE (trueop1) == CONST_DOUBLE && GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_FLOAT @@ -1572,7 +1639,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, if (((GET_CODE (op0) == NOT && rtx_equal_p (XEXP (op0, 0), op1)) || (GET_CODE (op1) == NOT && rtx_equal_p (XEXP (op1, 0), op0))) && ! side_effects_p (op0) - && GET_MODE_CLASS (mode) != MODE_CC) + && SCALAR_INT_MODE_P (mode)) return constm1_rtx; tem = simplify_associative_operation (code, mode, op0, op1); if (tem) @@ -1589,7 +1656,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, if (trueop0 == trueop1 && ! side_effects_p (op0) && GET_MODE_CLASS (mode) != MODE_CC) - return const0_rtx; + return CONST0_RTX (mode); /* Canonicalize XOR of the most significant bit to PLUS. */ if ((GET_CODE (op1) == CONST_INT @@ -1613,8 +1680,8 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, break; case AND: - if (trueop1 == const0_rtx && ! side_effects_p (op0)) - return const0_rtx; + if (trueop1 == CONST0_RTX (mode) && ! side_effects_p (op0)) + return trueop1; /* If we are turning off bits already known off in OP0, we need not do an AND. */ if (GET_CODE (trueop1) == CONST_INT @@ -1629,7 +1696,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, || (GET_CODE (op1) == NOT && rtx_equal_p (XEXP (op1, 0), op0))) && ! side_effects_p (op0) && GET_MODE_CLASS (mode) != MODE_CC) - return const0_rtx; + return CONST0_RTX (mode); /* Transform (and (extend X) C) into (zero_extend (and X C)) if there are no nonzero bits of C outside of X's mode. */ @@ -1700,26 +1767,20 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, case UDIV: /* 0/x is 0 (or x&0 if x has side-effects). */ - if (trueop0 == const0_rtx) - return side_effects_p (op1) - ? simplify_gen_binary (AND, mode, op1, const0_rtx) - : const0_rtx; - /* x/1 is x. */ - if (trueop1 == const1_rtx) - { - /* Handle narrowing UDIV. */ - rtx x = gen_lowpart_common (mode, op0); - if (x) - return x; - if (mode != GET_MODE (op0) && GET_MODE (op0) != VOIDmode) - return gen_lowpart_SUBREG (mode, op0); - return op0; - } - /* Convert divide by power of two into shift. */ - if (GET_CODE (trueop1) == CONST_INT - && (val = exact_log2 (INTVAL (trueop1))) > 0) - return simplify_gen_binary (LSHIFTRT, mode, op0, GEN_INT (val)); - break; + if (trueop0 == CONST0_RTX (mode)) + { + if (side_effects_p (op1)) + return simplify_gen_binary (AND, mode, op1, trueop0); + return trueop0; + } + /* x/1 is x. */ + if (trueop1 == CONST1_RTX (mode)) + return rtl_hooks.gen_lowpart_no_emit (mode, op0); + /* Convert divide by power of two into shift. */ + if (GET_CODE (trueop1) == CONST_INT + && (val = exact_log2 (INTVAL (trueop1))) > 0) + return simplify_gen_binary (LSHIFTRT, mode, op0, GEN_INT (val)); + break; case DIV: /* Handle floating point and integers separately. */ @@ -1764,28 +1825,19 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, else { /* 0/x is 0 (or x&0 if x has side-effects). */ - if (trueop0 == const0_rtx) - return side_effects_p (op1) - ? simplify_gen_binary (AND, mode, op1, const0_rtx) - : const0_rtx; - /* x/1 is x. */ - if (trueop1 == const1_rtx) + if (trueop0 == CONST0_RTX (mode)) { - /* Handle narrowing DIV. */ - rtx x = gen_lowpart_common (mode, op0); - if (x) - return x; - if (mode != GET_MODE (op0) && GET_MODE (op0) != VOIDmode) - return gen_lowpart_SUBREG (mode, op0); - return op0; + if (side_effects_p (op1)) + return simplify_gen_binary (AND, mode, op1, trueop0); + return trueop0; } + /* x/1 is x. */ + if (trueop1 == CONST1_RTX (mode)) + return rtl_hooks.gen_lowpart_no_emit (mode, op0); /* x/-1 is -x. */ if (trueop1 == constm1_rtx) { - rtx x = gen_lowpart_common (mode, op0); - if (!x) - x = (mode != GET_MODE (op0) && GET_MODE (op0) != VOIDmode) - ? gen_lowpart_SUBREG (mode, op0) : op0; + rtx x = rtl_hooks.gen_lowpart_no_emit (mode, op0); return simplify_gen_unary (NEG, mode, x, mode); } } @@ -1793,34 +1845,42 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, case UMOD: /* 0%x is 0 (or x&0 if x has side-effects). */ - if (trueop0 == const0_rtx) - return side_effects_p (op1) - ? simplify_gen_binary (AND, mode, op1, const0_rtx) - : const0_rtx; - /* x%1 is 0 (of x&0 if x has side-effects). */ - if (trueop1 == const1_rtx) - return side_effects_p (op0) - ? simplify_gen_binary (AND, mode, op0, const0_rtx) - : const0_rtx; - /* Implement modulus by power of two as AND. */ - if (GET_CODE (trueop1) == CONST_INT - && exact_log2 (INTVAL (trueop1)) > 0) - return simplify_gen_binary (AND, mode, op0, - GEN_INT (INTVAL (op1) - 1)); - break; + if (trueop0 == CONST0_RTX (mode)) + { + if (side_effects_p (op1)) + return simplify_gen_binary (AND, mode, op1, trueop0); + return trueop0; + } + /* x%1 is 0 (of x&0 if x has side-effects). */ + if (trueop1 == CONST1_RTX (mode)) + { + if (side_effects_p (op0)) + return simplify_gen_binary (AND, mode, op0, CONST0_RTX (mode)); + return CONST0_RTX (mode); + } + /* Implement modulus by power of two as AND. */ + if (GET_CODE (trueop1) == CONST_INT + && exact_log2 (INTVAL (trueop1)) > 0) + return simplify_gen_binary (AND, mode, op0, + GEN_INT (INTVAL (op1) - 1)); + break; case MOD: /* 0%x is 0 (or x&0 if x has side-effects). */ - if (trueop0 == const0_rtx) - return side_effects_p (op1) - ? simplify_gen_binary (AND, mode, op1, const0_rtx) - : const0_rtx; - /* x%1 and x%-1 is 0 (or x&0 if x has side-effects). */ - if (trueop1 == const1_rtx || trueop1 == constm1_rtx) - return side_effects_p (op0) - ? simplify_gen_binary (AND, mode, op0, const0_rtx) - : const0_rtx; - break; + if (trueop0 == CONST0_RTX (mode)) + { + if (side_effects_p (op1)) + return simplify_gen_binary (AND, mode, op1, trueop0); + return trueop0; + } + /* x%1 and x%-1 is 0 (or x&0 if x has side-effects). */ + if (trueop1 == CONST1_RTX (mode) || trueop1 == constm1_rtx) + { + if (side_effects_p (op0)) + return simplify_gen_binary (AND, mode, op0, CONST0_RTX (mode)); + return CONST0_RTX (mode); + } + break; case ROTATERT: case ROTATE: @@ -1835,9 +1895,9 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, case ASHIFT: case LSHIFTRT: - if (trueop1 == const0_rtx) + if (trueop1 == CONST0_RTX (mode)) return op0; - if (trueop0 == const0_rtx && ! side_effects_p (op1)) + if (trueop0 == CONST0_RTX (mode) && ! side_effects_p (op1)) return op0; break; @@ -1869,7 +1929,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, break; case UMIN: - if (trueop1 == const0_rtx && ! side_effects_p (op0)) + if (trueop1 == CONST0_RTX (mode) && ! side_effects_p (op0)) return op1; if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) return op0; @@ -2491,8 +2551,7 @@ simplify_const_binary_operation (enum rtx_code code, enum machine_mode mode, gcc_unreachable (); } - val = trunc_int_for_mode (val, mode); - return GEN_INT (val); + return gen_int_mode (val, mode); } return NULL_RTX; @@ -2885,7 +2944,7 @@ simplify_relational_operation_1 (enum rtx_code code, enum machine_mode mode, /* If op0 is a comparison, extract the comparison arguments form it. */ if (code == NE) { - if (GET_MODE (op0) == cmp_mode) + if (GET_MODE (op0) == mode) return simplify_rtx (op0); else return simplify_gen_relational (GET_CODE (op0), mode, VOIDmode,