diff options
Diffstat (limited to 'gcc/combine.c')
-rw-r--r-- | gcc/combine.c | 64 |
1 files changed, 41 insertions, 23 deletions
diff --git a/gcc/combine.c b/gcc/combine.c index de3bcef..9a9d648 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -10955,38 +10955,56 @@ simplify_comparison (code, pop0, pop1) /* Now make any compound operations involved in this comparison. Then, check for an outmost SUBREG on OP0 that is not doing anything or is - paradoxical. The latter case can only occur when it is known that the - "extra" bits will be zero. Therefore, it is safe to remove the SUBREG. - We can never remove a SUBREG for a non-equality comparison because the - sign bit is in a different place in the underlying object. */ + paradoxical. The latter transformation must only be performed when + it is known that the "extra" bits will be the same in op0 and op1 or + that they don't matter. There are three cases to consider: + + 1. SUBREG_REG (op0) is a register. In this case the bits are don't + care bits and we can assume they have any convenient value. So + making the transformation is safe. + + 2. SUBREG_REG (op0) is a memory and LOAD_EXTEND_OP is not defined. + In this case the upper bits of op0 are undefined. We should not make + the simplification in that case as we do not know the contents of + those bits. + + 3. SUBREG_REG (op0) is a memory and LOAD_EXTEND_OP is defined and not + NIL. In that case we know those bits are zeros or ones. We must + also be sure that they are the same as the upper bits of op1. + + We can never remove a SUBREG for a non-equality comparison because + the sign bit is in a different place in the underlying object. */ op0 = make_compound_operation (op0, op1 == const0_rtx ? COMPARE : SET); op1 = make_compound_operation (op1, SET); if (GET_CODE (op0) == SUBREG && subreg_lowpart_p (op0) + /* Case 3 above, to sometimes allow (subreg (mem x)), isn't + implemented. */ + && GET_CODE (SUBREG_REG (op0)) == REG && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op0))) == MODE_INT - && (code == NE || code == EQ) - && ((GET_MODE_SIZE (GET_MODE (op0)) - > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)))))) + && (code == NE || code == EQ)) { - op0 = SUBREG_REG (op0); - op1 = gen_lowpart_for_combine (GET_MODE (op0), op1); - } + if (GET_MODE_SIZE (GET_MODE (op0)) + > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)))) + { + op0 = SUBREG_REG (op0); + op1 = gen_lowpart_for_combine (GET_MODE (op0), op1); + } + else if ((GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0))) + <= HOST_BITS_PER_WIDE_INT) + && (nonzero_bits (SUBREG_REG (op0), + GET_MODE (SUBREG_REG (op0))) + & ~GET_MODE_MASK (GET_MODE (op0))) == 0) + { + tem = gen_lowpart_for_combine (GET_MODE (SUBREG_REG (op0)), op1); - else if (GET_CODE (op0) == SUBREG && subreg_lowpart_p (op0) - && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT - && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op0))) == MODE_INT - && (code == NE || code == EQ) - && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0))) - <= HOST_BITS_PER_WIDE_INT) - && (nonzero_bits (SUBREG_REG (op0), GET_MODE (SUBREG_REG (op0))) - & ~GET_MODE_MASK (GET_MODE (op0))) == 0 - && (tem = gen_lowpart_for_combine (GET_MODE (SUBREG_REG (op0)), - op1), - (nonzero_bits (tem, GET_MODE (SUBREG_REG (op0))) - & ~GET_MODE_MASK (GET_MODE (op0))) == 0)) - op0 = SUBREG_REG (op0), op1 = tem; + if ((nonzero_bits (tem, GET_MODE (SUBREG_REG (op0))) + & ~GET_MODE_MASK (GET_MODE (op0))) == 0) + op0 = SUBREG_REG (op0), op1 = tem; + } + } /* We now do the opposite procedure: Some machines don't have compare insns in all modes. If OP0's mode is an integer mode smaller than a |