Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit 39bf520

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 bb2b6fd commit 39bf520

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
@@ -2069,29 +2069,40 @@ bool llvm::tryFoldSPUpdateIntoPushPop(const ARMSubtarget &Subtarget,
20692069
int RegListIdx = IsT1PushPop ? 2 : 4;
20702070

20712071
// Calculate the space we'll need in terms of registers.
2072-
unsigned FirstReg = MI->getOperand(RegListIdx).getReg();
2073-
unsigned RD0Reg, RegsNeeded;
2072+
unsigned RegsNeeded;
2073+
const TargetRegisterClass *RegClass;
20742074
if (IsVFPPushPop) {
2075-
RD0Reg = ARM::D0;
20762075
RegsNeeded = NumBytes / 8;
2076+
RegClass = &ARM::DPRRegClass;
20772077
} else {
2078-
RD0Reg = ARM::R0;
20792078
RegsNeeded = NumBytes / 4;
2079+
RegClass = &ARM::GPRRegClass;
20802080
}
20812081

20822082
// We're going to have to strip all list operands off before
20832083
// re-adding them since the order matters, so save the existing ones
20842084
// for later.
20852085
SmallVector<MachineOperand, 4> RegList;
2086-
for (int i = MI->getNumOperands() - 1; i >= RegListIdx; --i)
2087-
RegList.push_back(MI->getOperand(i));
2086+
2087+
// We're also going to need the first register transferred by this
2088+
// instruction, which won't necessarily be the first register in the list.
2089+
unsigned FirstRegEnc = -1;
20882090

20892091
const TargetRegisterInfo *TRI = MF.getRegInfo().getTargetRegisterInfo();
2092+
for (int i = MI->getNumOperands() - 1; i >= RegListIdx; --i) {
2093+
MachineOperand &MO = MI->getOperand(i);
2094+
RegList.push_back(MO);
2095+
2096+
if (MO.isReg() && TRI->getEncodingValue(MO.getReg()) < FirstRegEnc)
2097+
FirstRegEnc = TRI->getEncodingValue(MO.getReg());
2098+
}
2099+
20902100
const MCPhysReg *CSRegs = TRI->getCalleeSavedRegs(&MF);
20912101

20922102
// Now try to find enough space in the reglist to allocate NumBytes.
2093-
for (unsigned CurReg = FirstReg - 1; CurReg >= RD0Reg && RegsNeeded;
2094-
--CurReg) {
2103+
for (int CurRegEnc = FirstRegEnc - 1; CurRegEnc >= 0 && RegsNeeded;
2104+
--CurRegEnc) {
2105+
unsigned CurReg = RegClass->getRegister(CurRegEnc);
20952106
if (!IsPop) {
20962107
// Pushing any register is completely harmless, mark the
20972108
// 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 {r4, r7, lr}
225+
; CHECK: sub sp, #24
226+
; [...]
227+
; CHECK: add sp, #24
228+
; CHECK: pop {r4, r7, 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)