diff --git a/lib/Target/ARM/ARMMachineFunctionInfo.h b/lib/Target/ARM/ARMMachineFunctionInfo.h index 6b3ac21d527..cf4c105fe17 100644 --- a/lib/Target/ARM/ARMMachineFunctionInfo.h +++ b/lib/Target/ARM/ARMMachineFunctionInfo.h @@ -40,6 +40,10 @@ class ARMFunctionInfo : public MachineFunctionInfo { /// far jump. bool LRForceSpilled; + /// R3IsLiveIn - True if R3 is live in to this function. + /// + bool R3IsLiveIn; + /// FramePtrSpillOffset - If HasStackFrame, this records the frame pointer /// spill stack offset. unsigned FramePtrSpillOffset; @@ -75,13 +79,15 @@ class ARMFunctionInfo : public MachineFunctionInfo { public: ARMFunctionInfo() : isThumb(false), - VarArgsRegSaveSize(0), HasStackFrame(false), LRForceSpilled(false), + VarArgsRegSaveSize(0), HasStackFrame(false), + LRForceSpilled(false), R3IsLiveIn(false), FramePtrSpillOffset(0), GPRCS1Offset(0), GPRCS2Offset(0), DPRCSOffset(0), GPRCS1Size(0), GPRCS2Size(0), DPRCSSize(0), JumpTableUId(0) {} ARMFunctionInfo(MachineFunction &MF) : isThumb(MF.getTarget().getSubtarget().isThumb()), - VarArgsRegSaveSize(0), HasStackFrame(false), LRForceSpilled(false), + VarArgsRegSaveSize(0), HasStackFrame(false), + LRForceSpilled(false), R3IsLiveIn(false), FramePtrSpillOffset(0), GPRCS1Offset(0), GPRCS2Offset(0), DPRCSOffset(0), GPRCS1Size(0), GPRCS2Size(0), DPRCSSize(0), JumpTableUId(0) {} @@ -96,6 +102,9 @@ public: bool isLRForceSpilled() const { return LRForceSpilled; } void setLRIsForceSpilled(bool s) { LRForceSpilled = s; } + bool isR3IsLiveIn() const { return R3IsLiveIn; } + void setR3IsLiveIn(bool l) { R3IsLiveIn = l; } + unsigned getFramePtrSpillOffset() const { return FramePtrSpillOffset; } void setFramePtrSpillOffset(unsigned o) { FramePtrSpillOffset = o; } diff --git a/lib/Target/ARM/ARMRegisterInfo.cpp b/lib/Target/ARM/ARMRegisterInfo.cpp index 644fcec63c5..ac2ed8ebab5 100644 --- a/lib/Target/ARM/ARMRegisterInfo.cpp +++ b/lib/Target/ARM/ARMRegisterInfo.cpp @@ -401,7 +401,10 @@ void emitThumbRegPlusConstPool(MachineBasicBlock &MBB, if (NumBytes <= 255 && NumBytes >= 0) BuildMI(MBB, MBBI, TII.get(ARM::tMOVri8), LdReg).addImm(NumBytes); - else + else if (NumBytes < 0 && NumBytes >= -255) { + BuildMI(MBB, MBBI, TII.get(ARM::tMOVri8), LdReg).addImm(NumBytes); + BuildMI(MBB, MBBI, TII.get(ARM::tNEG), LdReg).addReg(LdReg); + } else emitLoadConstPool(MBB, MBBI, LdReg, NumBytes, TII); // Emit add / sub. @@ -811,7 +814,7 @@ void ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const{ // being storing here. If that's the case, we do the following: // r12 = r2 // Use r2 to materialize sp + offset - // str r12, r2 + // str r3, r2 // r2 = r12 unsigned ValReg = MI.getOperand(0).getReg(); unsigned TmpReg = ARM::R3; @@ -820,6 +823,8 @@ void ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const{ BuildMI(MBB, II, TII.get(ARM::tMOVrr), ARM::R12).addReg(ARM::R2); TmpReg = ARM::R2; } + if (TmpReg == ARM::R3 && AFI->isR3IsLiveIn()) + BuildMI(MBB, II, TII.get(ARM::tMOVrr), ARM::R12).addReg(ARM::R3); if (Opcode == ARM::tSpill) { if (FrameReg == ARM::SP) emitThumbRegPlusConstPool(MBB, II, TmpReg, FrameReg,Offset,false,TII); @@ -835,10 +840,12 @@ void ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const{ MI.addRegOperand(FrameReg, false); // Use [reg, reg] addrmode. else MI.addRegOperand(0, false); // tSTR has an extra register operand. - if (ValReg == ARM::R3) { - MachineBasicBlock::iterator NII = next(II); + + MachineBasicBlock::iterator NII = next(II); + if (ValReg == ARM::R3) BuildMI(MBB, NII, TII.get(ARM::tMOVrr), ARM::R2).addReg(ARM::R12); - } + if (TmpReg == ARM::R3 && AFI->isR3IsLiveIn()) + BuildMI(MBB, NII, TII.get(ARM::tMOVrr), ARM::R3).addReg(ARM::R12); } else assert(false && "Unexpected opcode!"); } else { @@ -1032,6 +1039,15 @@ void ARMRegisterInfo::emitPrologue(MachineFunction &MF) const { const std::vector &CSI = MFI->getCalleeSavedInfo(); if (isThumb) { + // Check if R3 is live in. It might have to be used as a scratch register. + for (MachineFunction::livein_iterator I=MF.livein_begin(),E=MF.livein_end(); + I != E; ++I) { + if ((*I).first == ARM::R3) { + AFI->setR3IsLiveIn(true); + break; + } + } + // Thumb add/sub sp, imm8 instructions implicitly multiply the offset by 4. NumBytes = (NumBytes + 3) & ~3; MFI->setStackSize(NumBytes);