Skip to content
This repository was archived by the owner on Sep 2, 2018. It is now read-only.

Commit 1ff4f02

Browse files
committed
ARM: don't rely on push/pop reglists being in order when folding SP adjust.
It would be a very nice invariant to rely on, but unfortunately it doesn't necessarily hold (and the causes of mis-sorted reglists appear to be quite varied) so to be robust the frame lowering code can't assume that the first register in the list is also the first one that actually gets pushed. Should fix an issue where we were turning something like: push {r8, r4, r7, lr} sub sp, #24 into nonsense like: push {r2, r3, r4, r5, r6, r7, r8, r4, r7, lr} git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@285232 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 73235dc commit 1ff4f02

File tree

2 files changed

+33
-8
lines changed

2 files changed

+33
-8
lines changed

lib/Target/ARM/ARMBaseInstrInfo.cpp

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2077,29 +2077,40 @@ bool llvm::tryFoldSPUpdateIntoPushPop(const ARMSubtarget &Subtarget,
20772077
int RegListIdx = IsT1PushPop ? 2 : 4;
20782078

20792079
// Calculate the space we'll need in terms of registers.
2080-
unsigned FirstReg = MI->getOperand(RegListIdx).getReg();
2081-
unsigned RD0Reg, RegsNeeded;
2080+
unsigned RegsNeeded;
2081+
const TargetRegisterClass *RegClass;
20822082
if (IsVFPPushPop) {
2083-
RD0Reg = ARM::D0;
20842083
RegsNeeded = NumBytes / 8;
2084+
RegClass = &ARM::DPRRegClass;
20852085
} else {
2086-
RD0Reg = ARM::R0;
20872086
RegsNeeded = NumBytes / 4;
2087+
RegClass = &ARM::GPRRegClass;
20882088
}
20892089

20902090
// We're going to have to strip all list operands off before
20912091
// re-adding them since the order matters, so save the existing ones
20922092
// for later.
20932093
SmallVector<MachineOperand, 4> RegList;
2094-
for (int i = MI->getNumOperands() - 1; i >= RegListIdx; --i)
2095-
RegList.push_back(MI->getOperand(i));
2094+
2095+
// We're also going to need the first register transferred by this
2096+
// instruction, which won't necessarily be the first register in the list.
2097+
unsigned FirstRegEnc = -1;
20962098

20972099
const TargetRegisterInfo *TRI = MF.getRegInfo().getTargetRegisterInfo();
2100+
for (int i = MI->getNumOperands() - 1; i >= RegListIdx; --i) {
2101+
MachineOperand &MO = MI->getOperand(i);
2102+
RegList.push_back(MO);
2103+
2104+
if (MO.isReg() && TRI->getEncodingValue(MO.getReg()) < FirstRegEnc)
2105+
FirstRegEnc = TRI->getEncodingValue(MO.getReg());
2106+
}
2107+
20982108
const MCPhysReg *CSRegs = TRI->getCalleeSavedRegs(&MF);
20992109

21002110
// Now try to find enough space in the reglist to allocate NumBytes.
2101-
for (unsigned CurReg = FirstReg - 1; CurReg >= RD0Reg && RegsNeeded;
2102-
--CurReg) {
2111+
for (int CurRegEnc = FirstRegEnc - 1; CurRegEnc >= 0 && RegsNeeded;
2112+
--CurRegEnc) {
2113+
unsigned CurReg = RegClass->getRegister(CurRegEnc);
21032114
if (!IsPop) {
21042115
// Pushing any register is completely harmless, mark the
21052116
// register involved as undef since we don't care about it in

test/CodeGen/ARM/fold-stack-adjust.ll

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,4 +218,18 @@ exit: ; preds = %if.then, %entry
218218
ret float %call1
219219
}
220220

221+
declare void @use_arr(i32*)
222+
define void @test_fold_reuse() minsize {
223+
; CHECK-LABEL: test_fold_reuse:
224+
; CHECK: push.w {r4, r7, r8, lr}
225+
; CHECK: sub sp, #24
226+
; [...]
227+
; CHECK: add sp, #24
228+
; CHECK: pop.w {r4, r7, r8, pc}
229+
%arr = alloca i8, i32 24
230+
call void asm sideeffect "", "~{r8},~{r4}"()
231+
call void @bar(i8* %arr)
232+
ret void
233+
}
234+
221235
declare void @llvm.va_start(i8*) nounwind

0 commit comments

Comments
 (0)