aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1994-05-27 13:36:40 -0400
committerRichard Kenner <kenner@gcc.gnu.org>1994-05-27 13:36:40 -0400
commit7e4dc511b073113b428eaa0bd9d7cc4c2c589329 (patch)
tree6ac6fe9f1707286dccb93143ef897fc2d4472c7e
parent5f40cc2da4ba2f44be72bd35a03c3270061472e9 (diff)
downloadgcc-7e4dc511b073113b428eaa0bd9d7cc4c2c589329.zip
gcc-7e4dc511b073113b428eaa0bd9d7cc4c2c589329.tar.gz
gcc-7e4dc511b073113b428eaa0bd9d7cc4c2c589329.tar.bz2
(simplify_comparison): Narrow comparison for AND's that are ZERO_EXTENDs.
Can widen for all comparisons if inputs are both sign extended. From-SVN: r7363
-rw-r--r--gcc/combine.c76
1 files changed, 50 insertions, 26 deletions
diff --git a/gcc/combine.c b/gcc/combine.c
index 861e40c..cec950b 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -8590,32 +8590,58 @@ simplify_comparison (code, pop0, pop1)
and the operand's possibly nonzero bits are 0xffffff01; in that case
if we only care about QImode, we don't need the AND). This case
occurs if the output mode of an scc insn is not SImode and
- STORE_FLAG_VALUE == 1 (e.g., the 386). */
+ STORE_FLAG_VALUE == 1 (e.g., the 386).
+
+ Similarly, check for a case where the AND's are ZERO_EXTEND
+ operations from some narrower mode even though a SUBREG is not
+ present. */
else if (GET_CODE (op0) == AND && GET_CODE (op1) == AND
&& GET_CODE (XEXP (op0, 1)) == CONST_INT
- && GET_CODE (XEXP (op1, 1)) == CONST_INT
- && GET_CODE (XEXP (op0, 0)) == SUBREG
- && GET_CODE (XEXP (op1, 0)) == SUBREG
- && (GET_MODE_SIZE (GET_MODE (XEXP (op0, 0)))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (XEXP (op0, 0)))))
- && (GET_MODE (SUBREG_REG (XEXP (op0, 0)))
- == GET_MODE (SUBREG_REG (XEXP (op1, 0))))
- && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (XEXP (op0, 0))))
- <= HOST_BITS_PER_WIDE_INT)
- && (nonzero_bits (SUBREG_REG (XEXP (op0, 0)),
- GET_MODE (SUBREG_REG (XEXP (op0, 0))))
- & ~ INTVAL (XEXP (op0, 1))) == 0
- && (nonzero_bits (SUBREG_REG (XEXP (op1, 0)),
- GET_MODE (SUBREG_REG (XEXP (op1, 0))))
- & ~ INTVAL (XEXP (op1, 1))) == 0)
+ && GET_CODE (XEXP (op1, 1)) == CONST_INT)
{
- op0 = SUBREG_REG (XEXP (op0, 0));
- op1 = SUBREG_REG (XEXP (op1, 0));
+ rtx inner_op0 = XEXP (op0, 0);
+ rtx inner_op1 = XEXP (op1, 0);
+ HOST_WIDE_INT c0 = INTVAL (XEXP (op0, 1));
+ HOST_WIDE_INT c1 = INTVAL (XEXP (op1, 1));
+ int changed = 0;
+
+ if (GET_CODE (inner_op0) == SUBREG && GET_CODE (inner_op1) == SUBREG
+ && (GET_MODE_SIZE (GET_MODE (inner_op0))
+ > GET_MODE_SIZE (GET_MODE (SUBREG_REG (inner_op0))))
+ && (GET_MODE (SUBREG_REG (inner_op0))
+ == GET_MODE (SUBREG_REG (inner_op1)))
+ && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)))
+ <= HOST_BITS_PER_WIDE_INT)
+ && (0 == (~c0) & nonzero_bits (SUBREG_REG (inner_op0),
+ GET_MODE (SUBREG_REG (op0))))
+ && (0 == (~c1) & nonzero_bits (SUBREG_REG (inner_op1),
+ GET_MODE (SUBREG_REG (inner_op1)))))
+ {
+ op0 = SUBREG_REG (inner_op0);
+ op1 = SUBREG_REG (inner_op1);
+
+ /* The resulting comparison is always unsigned since we masked
+ off the original sign bit. */
+ code = unsigned_condition (code);
+
+ changed = 1;
+ }
- /* the resulting comparison is always unsigned since we masked off
- the original sign bit. */
- code = unsigned_condition (code);
+ else if (c0 == c1)
+ for (tmode = GET_CLASS_NARROWEST_MODE
+ (GET_MODE_CLASS (GET_MODE (op0)));
+ tmode != GET_MODE (op0); tmode = GET_MODE_WIDER_MODE (tmode))
+ if (c0 == GET_MODE_MASK (tmode))
+ {
+ op0 = gen_lowpart_for_combine (tmode, inner_op0);
+ op1 = gen_lowpart_for_combine (tmode, inner_op1);
+ changed = 1;
+ break;
+ }
+
+ if (! changed)
+ break;
}
/* If both operands are NOT, we can strip off the outer operation
@@ -9417,15 +9443,13 @@ simplify_comparison (code, pop0, pop1)
/* If the only nonzero bits in OP0 and OP1 are those in the
narrower mode and this is an equality or unsigned comparison,
we can use the wider mode. Similarly for sign-extended
- values and equality or signed comparisons. */
+ values, in which case it is true for all comparisons. */
if (((code == EQ || code == NE
|| code == GEU || code == GTU || code == LEU || code == LTU)
&& (nonzero_bits (op0, tmode) & ~ GET_MODE_MASK (mode)) == 0
&& (nonzero_bits (op1, tmode) & ~ GET_MODE_MASK (mode)) == 0)
- || ((code == EQ || code == NE
- || code == GE || code == GT || code == LE || code == LT)
- && (num_sign_bit_copies (op0, tmode)
- > GET_MODE_BITSIZE (tmode) - GET_MODE_BITSIZE (mode))
+ || ((num_sign_bit_copies (op0, tmode)
+ > GET_MODE_BITSIZE (tmode) - GET_MODE_BITSIZE (mode))
&& (num_sign_bit_copies (op1, tmode)
> GET_MODE_BITSIZE (tmode) - GET_MODE_BITSIZE (mode))))
{