mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-15 23:57:48 +00:00
ARM: fix bug in -Oz stack adjustment folding
Previously, we clobbered callee-saved registers when folding an "add sp, #N" into a "pop {rD, ...}" instruction. This change checks whether a register we're going to add to the "pop" could actually be live outside the function before doing so and should fix the issue. This should fix PR18081. llvm-svn: 196046
This commit is contained in:
parent
68c312e788
commit
bcd72d7348
@ -1909,29 +1909,40 @@ bool llvm::tryFoldSPUpdateIntoPushPop(MachineFunction &MF,
|
||||
|
||||
MachineBasicBlock *MBB = MI->getParent();
|
||||
const TargetRegisterInfo *TRI = MF.getRegInfo().getTargetRegisterInfo();
|
||||
const MCPhysReg *CSRegs = TRI->getCalleeSavedRegs(&MF);
|
||||
|
||||
// Now try to find enough space in the reglist to allocate NumBytes.
|
||||
for (unsigned CurReg = FirstReg - 1; CurReg >= RD0Reg && RegsNeeded;
|
||||
--CurReg, --RegsNeeded) {
|
||||
--CurReg) {
|
||||
if (!IsPop) {
|
||||
// Pushing any register is completely harmless, mark the
|
||||
// register involved as undef since we don't care about it in
|
||||
// the slightest.
|
||||
RegList.push_back(MachineOperand::CreateReg(CurReg, false, false,
|
||||
false, false, true));
|
||||
--RegsNeeded;
|
||||
continue;
|
||||
}
|
||||
|
||||
// However, we can only pop an extra register if it's not live. Otherwise we
|
||||
// might clobber a return value register. We assume that once we find a live
|
||||
// return register all lower ones will be too so there's no use proceeding.
|
||||
if (MBB->computeRegisterLiveness(TRI, CurReg, MI) !=
|
||||
MachineBasicBlock::LQR_Dead)
|
||||
return false;
|
||||
// However, we can only pop an extra register if it's not live. For
|
||||
// registers live within the function we might clobber a return value
|
||||
// register; the other way a register can be live here is if it's
|
||||
// callee-saved.
|
||||
if (isCalleeSavedRegister(CurReg, CSRegs) ||
|
||||
MBB->computeRegisterLiveness(TRI, CurReg, MI) !=
|
||||
MachineBasicBlock::LQR_Dead) {
|
||||
// VFP pops don't allow holes in the register list, so any skip is fatal
|
||||
// for our transformation. GPR pops do, so we should just keep looking.
|
||||
if (IsVFPPushPop)
|
||||
return false;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
// Mark the unimportant registers as <def,dead> in the POP.
|
||||
RegList.push_back(MachineOperand::CreateReg(CurReg, true, false, false,
|
||||
true));
|
||||
--RegsNeeded;
|
||||
}
|
||||
|
||||
if (RegsNeeded > 0)
|
||||
|
@ -72,6 +72,14 @@ static inline bool isARMArea3Register(unsigned Reg, bool isIOS) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool isCalleeSavedRegister(unsigned Reg,
|
||||
const MCPhysReg *CSRegs) {
|
||||
for (unsigned i = 0; CSRegs[i]; ++i)
|
||||
if (Reg == CSRegs[i])
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
class ARMBaseRegisterInfo : public ARMGenRegisterInfo {
|
||||
protected:
|
||||
const ARMSubtarget &STI;
|
||||
|
@ -82,13 +82,6 @@ ARMFrameLowering::canSimplifyCallFramePseudos(const MachineFunction &MF) const {
|
||||
return hasReservedCallFrame(MF) || MF.getFrameInfo()->hasVarSizedObjects();
|
||||
}
|
||||
|
||||
static bool isCalleeSavedRegister(unsigned Reg, const uint16_t *CSRegs) {
|
||||
for (unsigned i = 0; CSRegs[i]; ++i)
|
||||
if (Reg == CSRegs[i])
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isCSRestore(MachineInstr *MI,
|
||||
const ARMBaseInstrInfo &TII,
|
||||
const uint16_t *CSRegs) {
|
||||
|
@ -215,13 +215,6 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF) const {
|
||||
AFI->setShouldRestoreSPFromFP(true);
|
||||
}
|
||||
|
||||
static bool isCalleeSavedRegister(unsigned Reg, const uint16_t *CSRegs) {
|
||||
for (unsigned i = 0; CSRegs[i]; ++i)
|
||||
if (Reg == CSRegs[i])
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isCSRestore(MachineInstr *MI, const uint16_t *CSRegs) {
|
||||
if (MI->getOpcode() == ARM::tLDRspi &&
|
||||
MI->getOperand(1).isFI() &&
|
||||
|
@ -15,7 +15,7 @@ define void @check_simple() minsize {
|
||||
; CHECK-NOT: sub sp, sp,
|
||||
; ...
|
||||
; CHECK-NOT: add sp, sp,
|
||||
; CHECK: pop.w {r7, r8, r9, r10, r11, pc}
|
||||
; CHECK: pop.w {r0, r1, r2, r3, r11, pc}
|
||||
|
||||
; CHECK-T1-LABEL: check_simple:
|
||||
; CHECK-T1: push {r3, r4, r5, r6, r7, lr}
|
||||
@ -23,7 +23,7 @@ define void @check_simple() minsize {
|
||||
; CHECK-T1-NOT: sub sp, sp,
|
||||
; ...
|
||||
; CHECK-T1-NOT: add sp, sp,
|
||||
; CHECK-T1: pop {r3, r4, r5, r6, r7, pc}
|
||||
; CHECK-T1: pop {r0, r1, r2, r3, r7, pc}
|
||||
|
||||
; iOS always has a frame pointer and messing with the push affects
|
||||
; how it's set in the prologue. Make sure we get that right.
|
||||
|
Loading…
Reference in New Issue
Block a user