aboutsummaryrefslogtreecommitdiff
path: root/gcc/combine.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/combine.c')
-rw-r--r--gcc/combine.c31
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);
}