From: Manolis Tsamis <manolis.tsa...@vrull.eu> Fixes: 6a2e8dcbbd4bab3
Propagation for the stack pointer in regcprop was enabled in 6a2e8dcbbd4bab3, 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 110308 gcc/ChangeLog: * regcprop.cc (maybe_mode_change): Check stack_pointer_rtx mode. (find_oldest_value_reg): Special handling of stack_pointer_rtx. (copyprop_hardreg_forward_1): Ditto. gcc/testsuite/ChangeLog: * g++.dg/torture/pr110308.C: New test. Signed-off-by: Manolis Tsamis <manolis.tsa...@vrull.eu> Signed-off-by: Philipp Tomsich <philipp.toms...@vrull.eu> --- This addresses both the PRs (110308 and 110313) and was confirmed to resolve the AArch64 bootstrap issue reported by Thiago. OK for trunk? gcc/regcprop.cc | 43 +++++++++++++++++-------- gcc/testsuite/g++.dg/torture/pr110308.C | 30 +++++++++++++++++ 2 files changed, 60 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/g++.dg/torture/pr110308.C diff --git a/gcc/regcprop.cc b/gcc/regcprop.cc index 6cbfadb181f..fe75b7f1fa0 100644 --- a/gcc/regcprop.cc +++ b/gcc/regcprop.cc @@ -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; @@ -487,9 +487,14 @@ 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); + if (new_rtx != stack_pointer_rtx) + { + ORIGINAL_REGNO (new_rtx) = ORIGINAL_REGNO (reg); + REG_ATTRS (new_rtx) = REG_ATTRS (reg); + REG_POINTER (new_rtx) = REG_POINTER (reg); + } + else if (REG_POINTER (new_rtx) != REG_POINTER (reg)) + return NULL_RTX; return new_rtx; } } @@ -965,15 +970,27 @@ 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; + bool can_change; + if (new_rtx != stack_pointer_rtx) + { + ORIGINAL_REGNO (new_rtx) = ORIGINAL_REGNO (src); + REG_ATTRS (new_rtx) = REG_ATTRS (src); + REG_POINTER (new_rtx) = REG_POINTER (src); + can_change = true; + } + else + can_change + = (REG_POINTER (new_rtx) == REG_POINTER (src)); + + if (can_change) + { + 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. */ diff --git a/gcc/testsuite/g++.dg/torture/pr110308.C b/gcc/testsuite/g++.dg/torture/pr110308.C new file mode 100644 index 00000000000..ddd30d4fc3f --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr110308.C @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-g2 -O2" } */ + +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; +} \ No newline at end of file -- 2.34.1