diff options
author | Richard Kenner <kenner@gcc.gnu.org> | 1993-12-24 21:24:39 -0500 |
---|---|---|
committer | Richard Kenner <kenner@gcc.gnu.org> | 1993-12-24 21:24:39 -0500 |
commit | 30d69925b65208f1de5af08fd05918ad0b6c805c (patch) | |
tree | 11fd584dd2aeb54d5f0eea97a64cd6dbed7eebfd /gcc | |
parent | 6e7f952e96c08b97602e80d0961265090c707242 (diff) | |
download | gcc-30d69925b65208f1de5af08fd05918ad0b6c805c.zip gcc-30d69925b65208f1de5af08fd05918ad0b6c805c.tar.gz gcc-30d69925b65208f1de5af08fd05918ad0b6c805c.tar.bz2 |
(simplify_binary_operation, case PLUS, MINUS):
Simplify such things as (X >> 1) - X.
From-SVN: r6308
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cse.c | 108 |
1 files changed, 108 insertions, 0 deletions
@@ -3477,6 +3477,60 @@ simplify_binary_operation (code, mode, op0, op1) && GET_CODE (op0) == CONST_INT) return plus_constant (op1, INTVAL (op0)); + /* See if this is something like X * C - X or vice versa or + if the multiplication is written as a shift. If so, we can + distribute and make a new multiply, shift, or maybe just + have X (if C is 2 in the example above). But don't make + real multiply if we didn't have one before. */ + + if (! FLOAT_MODE_P (mode)) + { + HOST_WIDE_INT coeff0 = 1, coeff1 = 1; + rtx lhs = op0, rhs = op1; + int had_mult = 0; + + if (GET_CODE (lhs) == NEG) + coeff0 = -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); + had_mult = 1; + } + 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)); + lhs = XEXP (lhs, 0); + } + + if (GET_CODE (rhs) == NEG) + coeff1 = -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); + had_mult = 1; + } + 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)); + rhs = XEXP (rhs, 0); + } + + if (rtx_equal_p (lhs, rhs)) + { + tem = cse_gen_binary (MULT, mode, lhs, + GEN_INT (coeff0 + coeff1)); + return (GET_CODE (tem) == MULT && ! had_mult) ? 0 : tem; + } + } + /* If one of the operands is a PLUS or a MINUS, see if we can simplify this by the associative law. Don't use the associative law for floating point. @@ -3532,6 +3586,60 @@ simplify_binary_operation (code, mode, op0, op1) if (op1 == CONST0_RTX (mode)) return op0; + /* See if this is something like X * C - X or vice versa or + if the multiplication is written as a shift. If so, we can + distribute and make a new multiply, shift, or maybe just + have X (if C is 2 in the example above). But don't make + real multiply if we didn't have one before. */ + + if (! FLOAT_MODE_P (mode)) + { + HOST_WIDE_INT coeff0 = 1, coeff1 = 1; + rtx lhs = op0, rhs = op1; + int had_mult = 0; + + if (GET_CODE (lhs) == NEG) + coeff0 = -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); + had_mult = 1; + } + 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)); + lhs = XEXP (lhs, 0); + } + + if (GET_CODE (rhs) == NEG) + coeff1 = - 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); + had_mult = 1; + } + 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)); + rhs = XEXP (rhs, 0); + } + + if (rtx_equal_p (lhs, rhs)) + { + tem = cse_gen_binary (MULT, mode, lhs, + GEN_INT (coeff0 - coeff1)); + return (GET_CODE (tem) == MULT && ! had_mult) ? 0 : tem; + } + } + /* (a - (-b)) -> (a + b). */ if (GET_CODE (op1) == NEG) return cse_gen_binary (PLUS, mode, op0, XEXP (op1, 0)); |