diff options
Diffstat (limited to 'gcc/combine.c')
-rw-r--r-- | gcc/combine.c | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/gcc/combine.c b/gcc/combine.c index ff250aad6a1..064e4f97d01 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -11322,8 +11322,15 @@ change_zero_ext (rtx pat) x = gen_rtx_LSHIFTRT (inner_mode, XEXP (x, 0), GEN_INT (start)); else x = XEXP (x, 0); + if (mode != inner_mode) - x = gen_lowpart_SUBREG (mode, x); + { + if (REG_P (x) && HARD_REGISTER_P (x) + && !can_change_dest_mode (x, 0, mode)) + continue; + + x = gen_lowpart_SUBREG (mode, x); + } } else if (GET_CODE (x) == ZERO_EXTEND && SCALAR_INT_MODE_P (mode) @@ -11335,7 +11342,13 @@ change_zero_ext (rtx pat) size = GET_MODE_PRECISION (GET_MODE (XEXP (x, 0))); x = SUBREG_REG (XEXP (x, 0)); if (GET_MODE (x) != mode) - x = gen_lowpart_SUBREG (mode, x); + { + if (REG_P (x) && HARD_REGISTER_P (x) + && !can_change_dest_mode (x, 0, mode)) + continue; + + x = gen_lowpart_SUBREG (mode, x); + } } else if (GET_CODE (x) == ZERO_EXTEND && SCALAR_INT_MODE_P (mode) @@ -13081,8 +13094,11 @@ record_dead_and_set_regs_1 (rtx dest, const_rtx setter, void *data) if (REG_P (dest)) { /* If we are setting the whole register, we know its value. Otherwise - show that we don't know the value. We can handle SUBREG in - some cases. */ + show that we don't know the value. We can handle a SUBREG if it's + the low part, but we must be careful with paradoxical SUBREGs on + RISC architectures because we cannot strip e.g. an extension around + a load and record the naked load since the RTL middle-end considers + that the upper bits are defined according to LOAD_EXTEND_OP. */ if (GET_CODE (setter) == SET && dest == SET_DEST (setter)) record_value_for_reg (dest, record_dead_insn, SET_SRC (setter)); else if (GET_CODE (setter) == SET @@ -13091,8 +13107,11 @@ record_dead_and_set_regs_1 (rtx dest, const_rtx setter, void *data) && GET_MODE_PRECISION (GET_MODE (dest)) <= BITS_PER_WORD && subreg_lowpart_p (SET_DEST (setter))) record_value_for_reg (dest, record_dead_insn, - gen_lowpart (GET_MODE (dest), - SET_SRC (setter))); + WORD_REGISTER_OPERATIONS + && paradoxical_subreg_p (SET_DEST (setter)) + ? SET_SRC (setter) + : gen_lowpart (GET_MODE (dest), + SET_SRC (setter))); else record_value_for_reg (dest, record_dead_insn, NULL_RTX); } |