From 9fa6d012c05feb0f76406b9b3d088fd1708bc721 Mon Sep 17 00:00:00 2001 From: Torbjorn Granlund Date: Mon, 3 Apr 1995 23:19:41 +0000 Subject: [PATCH] (force_to_mode, case PLUS): Sign extend masks that are negative in OP_MODE. (simplify_and_const_int): Sign-extend constants when they have the most significant bit set for the target. (merge_outer_ops): Likewise. (simplify_shift_const): Likewise. From-SVN: r9310 --- gcc/combine.c | 74 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 8 deletions(-) diff --git a/gcc/combine.c b/gcc/combine.c index 05ec5d3e8a9..48e5a87c2ac 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -5795,13 +5795,26 @@ force_to_mode (x, mode, mask, reg, just_select) low-order bits (as in an alignment operation) and FOO is already aligned to that boundary, mask C1 to that boundary as well. This may eliminate that PLUS and, later, the AND. */ - if (GET_CODE (XEXP (x, 1)) == CONST_INT - && exact_log2 (- mask) >= 0 - && (nonzero_bits (XEXP (x, 0), mode) & ~ mask) == 0 - && (INTVAL (XEXP (x, 1)) & ~ mask) != 0) - return force_to_mode (plus_constant (XEXP (x, 0), - INTVAL (XEXP (x, 1)) & mask), - mode, mask, reg, next_select); + + { + int width = GET_MODE_BITSIZE (mode); + unsigned HOST_WIDE_INT smask = mask; + + /* If MODE is narrower than HOST_WIDE_INT and mask is a negative + number, sign extend it. */ + + if (width < HOST_BITS_PER_WIDE_INT + && (smask & ((HOST_WIDE_INT) 1 << (width - 1))) != 0) + smask |= (HOST_WIDE_INT) -1 << width; + + if (GET_CODE (XEXP (x, 1)) == CONST_INT + && exact_log2 (- smask) >= 0 + && (nonzero_bits (XEXP (x, 0), mode) & ~ mask) == 0 + && (INTVAL (XEXP (x, 1)) & ~ mask) != 0) + return force_to_mode (plus_constant (XEXP (x, 0), + INTVAL (XEXP (x, 1)) & mask), + mode, mask, reg, next_select); + } /* ... fall through ... */ @@ -6598,6 +6611,7 @@ simplify_and_const_int (x, mode, varop, constop) unsigned HOST_WIDE_INT constop; { unsigned HOST_WIDE_INT nonzero; + int width = GET_MODE_BITSIZE (mode); int i; /* Simplify VAROP knowing that we will be only looking at some of the @@ -6615,6 +6629,19 @@ simplify_and_const_int (x, mode, varop, constop) nonzero = nonzero_bits (varop, mode) & GET_MODE_MASK (mode); + /* If this would be an entire word for the target, but is not for + the host, then sign-extend on the host so that the number will look + the same way on the host that it would on the target. + + For example, when building a 64 bit alpha hosted 32 bit sparc + targeted compiler, then we want the 32 bit unsigned value -1 to be + represented as a 64 bit value -1, and not as 0x00000000ffffffff. + The later confuses the sparc backend. */ + + if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT && BITS_PER_WORD == width + && (nonzero & ((HOST_WIDE_INT) 1 << (width - 1)))) + nonzero |= ((HOST_WIDE_INT) (-1) << width); + /* Turn off all bits in the constant that are known to already be zero. Thus, if the AND isn't needed at all, we will have CONSTOP == NONZERO_BITS which is tested below. */ @@ -7408,6 +7435,7 @@ merge_outer_ops (pop0, pconst0, op1, const1, mode, pcomp_p) { enum rtx_code op0 = *pop0; HOST_WIDE_INT const0 = *pconst0; + int width = GET_MODE_BITSIZE (mode); const0 &= GET_MODE_MASK (mode); const1 &= GET_MODE_MASK (mode); @@ -7497,6 +7525,19 @@ merge_outer_ops (pop0, pconst0, op1, const1, mode, pcomp_p) else if (const0 == GET_MODE_MASK (mode) && op0 == AND) op0 = NIL; + /* If this would be an entire word for the target, but is not for + the host, then sign-extend on the host so that the number will look + the same way on the host that it would on the target. + + For example, when building a 64 bit alpha hosted 32 bit sparc + targeted compiler, then we want the 32 bit unsigned value -1 to be + represented as a 64 bit value -1, and not as 0x00000000ffffffff. + The later confuses the sparc backend. */ + + if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT && BITS_PER_WORD == width + && (const0 & ((HOST_WIDE_INT) 1 << (width - 1)))) + const0 |= ((HOST_WIDE_INT) (-1) << width); + *pop0 = op0; *pconst0 = const0; @@ -8179,7 +8220,24 @@ simplify_shift_const (x, code, result_mode, varop, count) if (outer_op != NIL) { if (GET_MODE_BITSIZE (result_mode) < HOST_BITS_PER_WIDE_INT) - outer_const &= GET_MODE_MASK (result_mode); + { + int width = GET_MODE_BITSIZE (result_mode); + + outer_const &= GET_MODE_MASK (result_mode); + + /* If this would be an entire word for the target, but is not for + the host, then sign-extend on the host so that the number will + look the same way on the host that it would on the target. + + For example, when building a 64 bit alpha hosted 32 bit sparc + targeted compiler, then we want the 32 bit unsigned value -1 to be + represented as a 64 bit value -1, and not as 0x00000000ffffffff. + The later confuses the sparc backend. */ + + if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT && BITS_PER_WORD == width + && (outer_const & ((HOST_WIDE_INT) 1 << (width - 1)))) + outer_const |= ((HOST_WIDE_INT) (-1) << width); + } if (outer_op == AND) x = simplify_and_const_int (NULL_RTX, result_mode, x, outer_const); -- 2.30.2