cprop_hardreg: fix ORIGINAL_REGNO/REG_ATTRS/REG_POINTER handling
Fixes:6a2e8dcbbd
Propagation for the stack pointer in regcprop was enabled in6a2e8dcbbd
, but set ORIGINAL_REGNO/REG_ATTRS/REG_POINTER for stack_pointer_rtx which caused regression (e.g., PR 110313, PR 110308). This fix adds special handling for stack_pointer_rtx in the places where maybe_mode_change is called. This also adds an check in maybe_mode_change to return the stack pointer only when the requested mode matches the mode of stack_pointer_rtx. PR debug/110308 gcc/ChangeLog: * regcprop.cc (maybe_mode_change): Check stack_pointer_rtx mode. (maybe_copy_reg_attrs): New function. (find_oldest_value_reg): Use maybe_copy_reg_attrs. (copyprop_hardreg_forward_1): Ditto. gcc/testsuite/ChangeLog: * g++.dg/torture/pr110308.C: New test. Signed-off-by: Manolis Tsamis <manolis.tsamis@vrull.eu> Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
This commit is contained in:
parent
4bf76b5b6d
commit
893883f2f8
2 changed files with 65 additions and 16 deletions
|
@ -423,7 +423,7 @@ maybe_mode_change (machine_mode orig_mode, machine_mode copy_mode,
|
|||
It's unclear if we need to do the same for other special registers. */
|
||||
if (regno == STACK_POINTER_REGNUM)
|
||||
{
|
||||
if (orig_mode == new_mode)
|
||||
if (orig_mode == new_mode && new_mode == GET_MODE (stack_pointer_rtx))
|
||||
return stack_pointer_rtx;
|
||||
else
|
||||
return NULL_RTX;
|
||||
|
@ -451,6 +451,31 @@ maybe_mode_change (machine_mode orig_mode, machine_mode copy_mode,
|
|||
return NULL_RTX;
|
||||
}
|
||||
|
||||
/* Helper function to copy attributes when replacing OLD_REG with NEW_REG.
|
||||
If the changes required for NEW_REG are invalid return NULL_RTX, otherwise
|
||||
return NEW_REG. This is intended to be used with maybe_mode_change. */
|
||||
|
||||
static rtx
|
||||
maybe_copy_reg_attrs (rtx new_reg, rtx old_reg)
|
||||
{
|
||||
if (new_reg != stack_pointer_rtx)
|
||||
{
|
||||
/* NEW_REG is assumed to be a register copy resulting from
|
||||
maybe_mode_change. */
|
||||
ORIGINAL_REGNO (new_reg) = ORIGINAL_REGNO (old_reg);
|
||||
REG_ATTRS (new_reg) = REG_ATTRS (old_reg);
|
||||
REG_POINTER (new_reg) = REG_POINTER (old_reg);
|
||||
}
|
||||
else if (REG_POINTER (new_reg) != REG_POINTER (old_reg))
|
||||
{
|
||||
/* Only a single instance of STACK_POINTER_RTX must exist and we cannot
|
||||
modify it. Allow propagation if REG_POINTER for OLD_REG matches and
|
||||
don't touch ORIGINAL_REGNO and REG_ATTRS. */
|
||||
return NULL_RTX;
|
||||
}
|
||||
return new_reg;
|
||||
}
|
||||
|
||||
/* Find the oldest copy of the value contained in REGNO that is in
|
||||
register class CL and has mode MODE. If found, return an rtx
|
||||
of that oldest register, otherwise return NULL. */
|
||||
|
@ -486,12 +511,7 @@ find_oldest_value_reg (enum reg_class cl, rtx reg, struct value_data *vd)
|
|||
|
||||
new_rtx = maybe_mode_change (oldmode, vd->e[regno].mode, mode, i, regno);
|
||||
if (new_rtx)
|
||||
{
|
||||
ORIGINAL_REGNO (new_rtx) = ORIGINAL_REGNO (reg);
|
||||
REG_ATTRS (new_rtx) = REG_ATTRS (reg);
|
||||
REG_POINTER (new_rtx) = REG_POINTER (reg);
|
||||
return new_rtx;
|
||||
}
|
||||
return maybe_copy_reg_attrs (new_rtx, reg);
|
||||
}
|
||||
|
||||
return NULL_RTX;
|
||||
|
@ -965,15 +985,15 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
|
|||
|
||||
if (validate_change (insn, &SET_SRC (set), new_rtx, 0))
|
||||
{
|
||||
ORIGINAL_REGNO (new_rtx) = ORIGINAL_REGNO (src);
|
||||
REG_ATTRS (new_rtx) = REG_ATTRS (src);
|
||||
REG_POINTER (new_rtx) = REG_POINTER (src);
|
||||
if (dump_file)
|
||||
fprintf (dump_file,
|
||||
"insn %u: replaced reg %u with %u\n",
|
||||
INSN_UID (insn), regno, REGNO (new_rtx));
|
||||
changed = true;
|
||||
goto did_replacement;
|
||||
if (maybe_copy_reg_attrs (new_rtx, src))
|
||||
{
|
||||
if (dump_file)
|
||||
fprintf (dump_file,
|
||||
"insn %u: replaced reg %u with %u\n",
|
||||
INSN_UID (insn), regno, REGNO (new_rtx));
|
||||
changed = true;
|
||||
goto did_replacement;
|
||||
}
|
||||
}
|
||||
/* We need to re-extract as validate_change clobbers
|
||||
recog_data. */
|
||||
|
|
29
gcc/testsuite/g++.dg/torture/pr110308.C
Normal file
29
gcc/testsuite/g++.dg/torture/pr110308.C
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* { dg-do compile } */
|
||||
|
||||
int channelCount, decodeBlock_outputLength;
|
||||
struct BlockCodec {
|
||||
virtual int decodeBlock(const unsigned char *, short *);
|
||||
};
|
||||
struct ms_adpcm_state {
|
||||
char predictorIndex;
|
||||
int sample1;
|
||||
ms_adpcm_state();
|
||||
};
|
||||
bool decodeBlock_ok;
|
||||
void encodeBlock() { ms_adpcm_state(); }
|
||||
struct MSADPCM : BlockCodec {
|
||||
int decodeBlock(const unsigned char *, short *);
|
||||
};
|
||||
void decodeSample(ms_adpcm_state, bool *);
|
||||
int MSADPCM::decodeBlock(const unsigned char *, short *) {
|
||||
ms_adpcm_state decoderState[2];
|
||||
ms_adpcm_state *state[2];
|
||||
state[0] = &decoderState[0];
|
||||
if (channelCount == 2)
|
||||
state[1] = &decoderState[0];
|
||||
short m_coefficients[state[1]->predictorIndex];
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
++state[i]->sample1;
|
||||
decodeSample(*state[1], &decodeBlock_ok);
|
||||
return decodeBlock_outputLength;
|
||||
}
|
Loading…
Add table
Reference in a new issue