diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index 21b8e6b8705..4c69a90c4b6 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -1866,6 +1866,15 @@ void llvm::emitARMRegPlusImmediate(MachineBasicBlock &MBB, } } +static bool isAnySubRegLive(unsigned Reg, const TargetRegisterInfo *TRI, + MachineInstr *MI) { + for (MCSubRegIterator Subreg(Reg, TRI, /* IncludeSelf */ true); + Subreg.isValid(); ++Subreg) + if (MI->getParent()->computeRegisterLiveness(TRI, *Subreg, MI) != + MachineBasicBlock::LQR_Dead) + return true; + return false; +} bool llvm::tryFoldSPUpdateIntoPushPop(const ARMSubtarget &Subtarget, MachineFunction &MF, MachineInstr *MI, unsigned NumBytes) { @@ -1920,7 +1929,6 @@ bool llvm::tryFoldSPUpdateIntoPushPop(const ARMSubtarget &Subtarget, for (int i = MI->getNumOperands() - 1; i >= RegListIdx; --i) RegList.push_back(MI->getOperand(i)); - MachineBasicBlock *MBB = MI->getParent(); const TargetRegisterInfo *TRI = MF.getRegInfo().getTargetRegisterInfo(); const MCPhysReg *CSRegs = TRI->getCalleeSavedRegs(&MF); @@ -1941,9 +1949,11 @@ bool llvm::tryFoldSPUpdateIntoPushPop(const ARMSubtarget &Subtarget, // 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. + // TODO: Currently, computeRegisterLiveness() does not report "live" if a + // sub reg is live. When computeRegisterLiveness() works for sub reg, it + // can replace isAnySubRegLive(). if (isCalleeSavedRegister(CurReg, CSRegs) || - MBB->computeRegisterLiveness(TRI, CurReg, MI) != - MachineBasicBlock::LQR_Dead) { + isAnySubRegLive(CurReg, TRI, MI)) { // 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) diff --git a/test/CodeGen/ARM/fold-stack-adjust.ll b/test/CodeGen/ARM/fold-stack-adjust.ll index feac793f4f8..695a20b5976 100644 --- a/test/CodeGen/ARM/fold-stack-adjust.ll +++ b/test/CodeGen/ARM/fold-stack-adjust.ll @@ -1,6 +1,7 @@ ; RUN: llc -mtriple=thumbv7-apple-none-macho < %s | FileCheck %s ; RUN: llc -mtriple=thumbv6m-apple-none-macho -disable-fp-elim < %s | FileCheck %s --check-prefix=CHECK-T1 ; RUN: llc -mtriple=thumbv7-apple-darwin-ios -disable-fp-elim < %s | FileCheck %s --check-prefix=CHECK-IOS +; RUN: llc -mtriple=thumbv7--linux-gnueabi -disable-fp-elim < %s | FileCheck %s --check-prefix=CHECK-LINUX declare void @bar(i8*) @@ -185,3 +186,33 @@ define void @test_varsize(...) minsize { call void @bar(i8* %var) ret void } + +%"MyClass" = type { i8*, i32, i32, float, float, float, [2 x i8], i32, i32* } + +declare float @foo() + +declare void @bar3() + +declare %"MyClass"* @bar2(%"MyClass"* returned, i16*, i32, float, float, i32, i32, i1 zeroext, i1 zeroext, i32) + +define fastcc float @check_vfp_no_return_clobber2(i16* %r, i16* %chars, i32 %length, i1 zeroext %flag) minsize { +entry: +; CHECK-LINUX-LABEL: check_vfp_no_return_clobber2 +; CHECK-LINUX: vpush {d0, d1, d2, d3, d4, d5, d6, d7, d8} +; CHECK-NOT: sub sp, +; ... +; CHECK-LINUX: add sp +; CHECK-LINUX: vpop {d8} + %run = alloca %"MyClass", align 4 + %call = call %"MyClass"* @bar2(%"MyClass"* %run, i16* %chars, i32 %length, float 0.000000e+00, float 0.000000e+00, i32 1, i32 1, i1 zeroext false, i1 zeroext true, i32 3) + %call1 = call float @foo() + %cmp = icmp eq %"MyClass"* %run, null + br i1 %cmp, label %exit, label %if.then + +if.then: ; preds = %entry + call void @bar3() + br label %exit + +exit: ; preds = %if.then, %entry + ret float %call1 +}