Commit c1f8b785 authored by Bill Wendling's avatar Bill Wendling
Browse files

Merging r196046:

------------------------------------------------------------------------
r196046 | tnorthover | 2013-12-01 06:16:24 -0800 (Sun, 01 Dec 2013) | 8 lines

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: 196074
parent 63fa617d
Loading
Loading
Loading
Loading
+18 −7
Original line number Diff line number Diff line
@@ -1913,29 +1913,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)
    // 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)
+8 −0
Original line number Diff line number Diff line
@@ -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;
+0 −7
Original line number Diff line number Diff line
@@ -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) {
+0 −7
Original line number Diff line number Diff line
@@ -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() &&
+2 −2
Original line number Diff line number Diff line
@@ -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.