Thumb1FrameLowering.cpp revision 221345
1218885Sdim//======- Thumb1FrameLowering.cpp - Thumb1 Frame Information ---*- C++ -*-====// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10218885Sdim// This file contains the Thumb1 implementation of TargetFrameLowering class. 11218885Sdim// 12218885Sdim//===----------------------------------------------------------------------===// 13218885Sdim 14218885Sdim#include "Thumb1FrameLowering.h" 15218885Sdim#include "ARMBaseInstrInfo.h" 16218885Sdim#include "ARMMachineFunctionInfo.h" 17218885Sdim#include "llvm/CodeGen/MachineFrameInfo.h" 18218885Sdim#include "llvm/CodeGen/MachineFunction.h" 19218885Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 20218885Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 21218885Sdim 22218885Sdimusing namespace llvm; 23218885Sdim 24218885Sdimbool Thumb1FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { 25218885Sdim const MachineFrameInfo *FFI = MF.getFrameInfo(); 26218885Sdim unsigned CFSize = FFI->getMaxCallFrameSize(); 27218885Sdim // It's not always a good idea to include the call frame as part of the 28218885Sdim // stack frame. ARM (especially Thumb) has small immediate offset to 29218885Sdim // address the stack frame. So a large call frame can cause poor codegen 30218885Sdim // and may even makes it impossible to scavenge a register. 31218885Sdim if (CFSize >= ((1 << 8) - 1) * 4 / 2) // Half of imm8 * 4 32218885Sdim return false; 33218885Sdim 34218885Sdim return !MF.getFrameInfo()->hasVarSizedObjects(); 35218885Sdim} 36218885Sdim 37221345Sdimstatic void 38221345SdimemitSPUpdate(MachineBasicBlock &MBB, 39221345Sdim MachineBasicBlock::iterator &MBBI, 40221345Sdim const TargetInstrInfo &TII, DebugLoc dl, 41221345Sdim const Thumb1RegisterInfo &MRI, 42221345Sdim int NumBytes, unsigned MIFlags = MachineInstr::NoFlags) { 43221345Sdim emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes, TII, 44221345Sdim MRI, MIFlags); 45218885Sdim} 46218885Sdim 47218885Sdimvoid Thumb1FrameLowering::emitPrologue(MachineFunction &MF) const { 48218885Sdim MachineBasicBlock &MBB = MF.front(); 49218885Sdim MachineBasicBlock::iterator MBBI = MBB.begin(); 50218885Sdim MachineFrameInfo *MFI = MF.getFrameInfo(); 51218885Sdim ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 52218885Sdim const Thumb1RegisterInfo *RegInfo = 53218885Sdim static_cast<const Thumb1RegisterInfo*>(MF.getTarget().getRegisterInfo()); 54218885Sdim const Thumb1InstrInfo &TII = 55218885Sdim *static_cast<const Thumb1InstrInfo*>(MF.getTarget().getInstrInfo()); 56218885Sdim 57218885Sdim unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize(); 58218885Sdim unsigned NumBytes = MFI->getStackSize(); 59218885Sdim const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); 60218885Sdim DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 61218885Sdim unsigned FramePtr = RegInfo->getFrameRegister(MF); 62218885Sdim unsigned BasePtr = RegInfo->getBaseRegister(); 63218885Sdim 64218885Sdim // Thumb add/sub sp, imm8 instructions implicitly multiply the offset by 4. 65218885Sdim NumBytes = (NumBytes + 3) & ~3; 66218885Sdim MFI->setStackSize(NumBytes); 67218885Sdim 68218885Sdim // Determine the sizes of each callee-save spill areas and record which frame 69218885Sdim // belongs to which callee-save spill areas. 70218885Sdim unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0; 71218885Sdim int FramePtrSpillFI = 0; 72218885Sdim 73218885Sdim if (VARegSaveSize) 74221345Sdim emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -VARegSaveSize, 75221345Sdim MachineInstr::FrameSetup); 76218885Sdim 77218885Sdim if (!AFI->hasStackFrame()) { 78218885Sdim if (NumBytes != 0) 79221345Sdim emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -NumBytes, 80221345Sdim MachineInstr::FrameSetup); 81218885Sdim return; 82218885Sdim } 83218885Sdim 84218885Sdim for (unsigned i = 0, e = CSI.size(); i != e; ++i) { 85218885Sdim unsigned Reg = CSI[i].getReg(); 86218885Sdim int FI = CSI[i].getFrameIdx(); 87218885Sdim switch (Reg) { 88218885Sdim case ARM::R4: 89218885Sdim case ARM::R5: 90218885Sdim case ARM::R6: 91218885Sdim case ARM::R7: 92218885Sdim case ARM::LR: 93218885Sdim if (Reg == FramePtr) 94218885Sdim FramePtrSpillFI = FI; 95218885Sdim AFI->addGPRCalleeSavedArea1Frame(FI); 96218885Sdim GPRCS1Size += 4; 97218885Sdim break; 98218885Sdim case ARM::R8: 99218885Sdim case ARM::R9: 100218885Sdim case ARM::R10: 101218885Sdim case ARM::R11: 102218885Sdim if (Reg == FramePtr) 103218885Sdim FramePtrSpillFI = FI; 104218885Sdim if (STI.isTargetDarwin()) { 105218885Sdim AFI->addGPRCalleeSavedArea2Frame(FI); 106218885Sdim GPRCS2Size += 4; 107218885Sdim } else { 108218885Sdim AFI->addGPRCalleeSavedArea1Frame(FI); 109218885Sdim GPRCS1Size += 4; 110218885Sdim } 111218885Sdim break; 112218885Sdim default: 113218885Sdim AFI->addDPRCalleeSavedAreaFrame(FI); 114218885Sdim DPRCSSize += 8; 115218885Sdim } 116218885Sdim } 117218885Sdim 118218885Sdim if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPUSH) { 119218885Sdim ++MBBI; 120218885Sdim if (MBBI != MBB.end()) 121218885Sdim dl = MBBI->getDebugLoc(); 122218885Sdim } 123218885Sdim 124218885Sdim // Determine starting offsets of spill areas. 125218885Sdim unsigned DPRCSOffset = NumBytes - (GPRCS1Size + GPRCS2Size + DPRCSSize); 126218885Sdim unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize; 127218885Sdim unsigned GPRCS1Offset = GPRCS2Offset + GPRCS2Size; 128218885Sdim AFI->setFramePtrSpillOffset(MFI->getObjectOffset(FramePtrSpillFI) + NumBytes); 129218885Sdim AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset); 130218885Sdim AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset); 131218885Sdim AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset); 132218885Sdim NumBytes = DPRCSOffset; 133218885Sdim 134218885Sdim // Adjust FP so it point to the stack slot that contains the previous FP. 135218885Sdim if (hasFP(MF)) { 136218885Sdim BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), FramePtr) 137221345Sdim .addFrameIndex(FramePtrSpillFI).addImm(0) 138221345Sdim .setMIFlags(MachineInstr::FrameSetup); 139218885Sdim if (NumBytes > 7) 140218885Sdim // If offset is > 7 then sp cannot be adjusted in a single instruction, 141218885Sdim // try restoring from fp instead. 142218885Sdim AFI->setShouldRestoreSPFromFP(true); 143218885Sdim } 144218885Sdim 145218885Sdim if (NumBytes) 146218885Sdim // Insert it after all the callee-save spills. 147221345Sdim emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -NumBytes, 148221345Sdim MachineInstr::FrameSetup); 149218885Sdim 150218885Sdim if (STI.isTargetELF() && hasFP(MF)) 151218885Sdim MFI->setOffsetAdjustment(MFI->getOffsetAdjustment() - 152218885Sdim AFI->getFramePtrSpillOffset()); 153218885Sdim 154218885Sdim AFI->setGPRCalleeSavedArea1Size(GPRCS1Size); 155218885Sdim AFI->setGPRCalleeSavedArea2Size(GPRCS2Size); 156218885Sdim AFI->setDPRCalleeSavedAreaSize(DPRCSSize); 157218885Sdim 158218885Sdim // If we need a base pointer, set it up here. It's whatever the value 159218885Sdim // of the stack pointer is at this point. Any variable size objects 160218885Sdim // will be allocated after this, so we can still use the base pointer 161218885Sdim // to reference locals. 162218885Sdim if (RegInfo->hasBasePointer(MF)) 163218885Sdim BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), BasePtr).addReg(ARM::SP); 164221345Sdim 165218885Sdim // If the frame has variable sized objects then the epilogue must restore 166218885Sdim // the sp from fp. We can assume there's an FP here since hasFP already 167218885Sdim // checks for hasVarSizedObjects. 168218885Sdim if (MFI->hasVarSizedObjects()) 169218885Sdim AFI->setShouldRestoreSPFromFP(true); 170218885Sdim} 171218885Sdim 172218885Sdimstatic bool isCalleeSavedRegister(unsigned Reg, const unsigned *CSRegs) { 173218885Sdim for (unsigned i = 0; CSRegs[i]; ++i) 174218885Sdim if (Reg == CSRegs[i]) 175218885Sdim return true; 176218885Sdim return false; 177218885Sdim} 178218885Sdim 179218885Sdimstatic bool isCSRestore(MachineInstr *MI, const unsigned *CSRegs) { 180218885Sdim if (MI->getOpcode() == ARM::tRestore && 181218885Sdim MI->getOperand(1).isFI() && 182218885Sdim isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs)) 183218885Sdim return true; 184218885Sdim else if (MI->getOpcode() == ARM::tPOP) { 185218885Sdim // The first two operands are predicates. The last two are 186218885Sdim // imp-def and imp-use of SP. Check everything in between. 187218885Sdim for (int i = 2, e = MI->getNumOperands() - 2; i != e; ++i) 188218885Sdim if (!isCalleeSavedRegister(MI->getOperand(i).getReg(), CSRegs)) 189218885Sdim return false; 190218885Sdim return true; 191218885Sdim } 192218885Sdim return false; 193218885Sdim} 194218885Sdim 195218885Sdimvoid Thumb1FrameLowering::emitEpilogue(MachineFunction &MF, 196218885Sdim MachineBasicBlock &MBB) const { 197218885Sdim MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 198218885Sdim assert((MBBI->getOpcode() == ARM::tBX_RET || 199218885Sdim MBBI->getOpcode() == ARM::tPOP_RET) && 200218885Sdim "Can only insert epilog into returning blocks"); 201218885Sdim DebugLoc dl = MBBI->getDebugLoc(); 202218885Sdim MachineFrameInfo *MFI = MF.getFrameInfo(); 203218885Sdim ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 204218885Sdim const Thumb1RegisterInfo *RegInfo = 205218885Sdim static_cast<const Thumb1RegisterInfo*>(MF.getTarget().getRegisterInfo()); 206218885Sdim const Thumb1InstrInfo &TII = 207218885Sdim *static_cast<const Thumb1InstrInfo*>(MF.getTarget().getInstrInfo()); 208218885Sdim 209218885Sdim unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize(); 210218885Sdim int NumBytes = (int)MFI->getStackSize(); 211218885Sdim const unsigned *CSRegs = RegInfo->getCalleeSavedRegs(); 212218885Sdim unsigned FramePtr = RegInfo->getFrameRegister(MF); 213218885Sdim 214218885Sdim if (!AFI->hasStackFrame()) { 215218885Sdim if (NumBytes != 0) 216218885Sdim emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, NumBytes); 217218885Sdim } else { 218218885Sdim // Unwind MBBI to point to first LDR / VLDRD. 219218885Sdim if (MBBI != MBB.begin()) { 220218885Sdim do 221218885Sdim --MBBI; 222218885Sdim while (MBBI != MBB.begin() && isCSRestore(MBBI, CSRegs)); 223218885Sdim if (!isCSRestore(MBBI, CSRegs)) 224218885Sdim ++MBBI; 225218885Sdim } 226218885Sdim 227218885Sdim // Move SP to start of FP callee save spill area. 228218885Sdim NumBytes -= (AFI->getGPRCalleeSavedArea1Size() + 229218885Sdim AFI->getGPRCalleeSavedArea2Size() + 230218885Sdim AFI->getDPRCalleeSavedAreaSize()); 231218885Sdim 232218885Sdim if (AFI->shouldRestoreSPFromFP()) { 233218885Sdim NumBytes = AFI->getFramePtrSpillOffset() - NumBytes; 234218885Sdim // Reset SP based on frame pointer only if the stack frame extends beyond 235218885Sdim // frame pointer stack slot, the target is ELF and the function has FP, or 236218885Sdim // the target uses var sized objects. 237218885Sdim if (NumBytes) { 238218885Sdim assert(MF.getRegInfo().isPhysRegUsed(ARM::R4) && 239218885Sdim "No scratch register to restore SP from FP!"); 240221345Sdim emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::R4, FramePtr, -NumBytes, 241221345Sdim TII, *RegInfo); 242218885Sdim BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), ARM::SP) 243218885Sdim .addReg(ARM::R4); 244218885Sdim } else 245218885Sdim BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), ARM::SP) 246218885Sdim .addReg(FramePtr); 247218885Sdim } else { 248218885Sdim if (MBBI->getOpcode() == ARM::tBX_RET && 249218885Sdim &MBB.front() != MBBI && 250218885Sdim prior(MBBI)->getOpcode() == ARM::tPOP) { 251218885Sdim MachineBasicBlock::iterator PMBBI = prior(MBBI); 252218885Sdim emitSPUpdate(MBB, PMBBI, TII, dl, *RegInfo, NumBytes); 253218885Sdim } else 254218885Sdim emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, NumBytes); 255218885Sdim } 256218885Sdim } 257218885Sdim 258218885Sdim if (VARegSaveSize) { 259218885Sdim // Unlike T2 and ARM mode, the T1 pop instruction cannot restore 260218885Sdim // to LR, and we can't pop the value directly to the PC since 261218885Sdim // we need to update the SP after popping the value. Therefore, we 262218885Sdim // pop the old LR into R3 as a temporary. 263218885Sdim 264218885Sdim // Move back past the callee-saved register restoration 265218885Sdim while (MBBI != MBB.end() && isCSRestore(MBBI, CSRegs)) 266218885Sdim ++MBBI; 267218885Sdim // Epilogue for vararg functions: pop LR to R3 and branch off it. 268218885Sdim AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tPOP))) 269218885Sdim .addReg(ARM::R3, RegState::Define); 270218885Sdim 271218885Sdim emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, VARegSaveSize); 272218885Sdim 273218885Sdim BuildMI(MBB, MBBI, dl, TII.get(ARM::tBX_RET_vararg)) 274218885Sdim .addReg(ARM::R3, RegState::Kill); 275218885Sdim // erase the old tBX_RET instruction 276218885Sdim MBB.erase(MBBI); 277218885Sdim } 278218885Sdim} 279218885Sdim 280218885Sdimbool Thumb1FrameLowering:: 281218885SdimspillCalleeSavedRegisters(MachineBasicBlock &MBB, 282218885Sdim MachineBasicBlock::iterator MI, 283218885Sdim const std::vector<CalleeSavedInfo> &CSI, 284218885Sdim const TargetRegisterInfo *TRI) const { 285218885Sdim if (CSI.empty()) 286218885Sdim return false; 287218885Sdim 288218885Sdim DebugLoc DL; 289218885Sdim MachineFunction &MF = *MBB.getParent(); 290218885Sdim const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); 291218885Sdim 292218885Sdim if (MI != MBB.end()) DL = MI->getDebugLoc(); 293218885Sdim 294218885Sdim MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(ARM::tPUSH)); 295218885Sdim AddDefaultPred(MIB); 296218885Sdim for (unsigned i = CSI.size(); i != 0; --i) { 297218885Sdim unsigned Reg = CSI[i-1].getReg(); 298218885Sdim bool isKill = true; 299218885Sdim 300218885Sdim // Add the callee-saved register as live-in unless it's LR and 301218885Sdim // @llvm.returnaddress is called. If LR is returned for @llvm.returnaddress 302218885Sdim // then it's already added to the function and entry block live-in sets. 303218885Sdim if (Reg == ARM::LR) { 304218885Sdim MachineFunction &MF = *MBB.getParent(); 305218885Sdim if (MF.getFrameInfo()->isReturnAddressTaken() && 306218885Sdim MF.getRegInfo().isLiveIn(Reg)) 307218885Sdim isKill = false; 308218885Sdim } 309218885Sdim 310218885Sdim if (isKill) 311218885Sdim MBB.addLiveIn(Reg); 312218885Sdim 313218885Sdim MIB.addReg(Reg, getKillRegState(isKill)); 314218885Sdim } 315221345Sdim MIB.setMIFlags(MachineInstr::FrameSetup); 316218885Sdim return true; 317218885Sdim} 318218885Sdim 319218885Sdimbool Thumb1FrameLowering:: 320218885SdimrestoreCalleeSavedRegisters(MachineBasicBlock &MBB, 321218885Sdim MachineBasicBlock::iterator MI, 322218885Sdim const std::vector<CalleeSavedInfo> &CSI, 323218885Sdim const TargetRegisterInfo *TRI) const { 324218885Sdim if (CSI.empty()) 325218885Sdim return false; 326218885Sdim 327218885Sdim MachineFunction &MF = *MBB.getParent(); 328218885Sdim ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 329218885Sdim const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); 330218885Sdim 331218885Sdim bool isVarArg = AFI->getVarArgsRegSaveSize() > 0; 332218885Sdim DebugLoc DL = MI->getDebugLoc(); 333218885Sdim MachineInstrBuilder MIB = BuildMI(MF, DL, TII.get(ARM::tPOP)); 334218885Sdim AddDefaultPred(MIB); 335218885Sdim 336218885Sdim bool NumRegs = false; 337218885Sdim for (unsigned i = CSI.size(); i != 0; --i) { 338218885Sdim unsigned Reg = CSI[i-1].getReg(); 339218885Sdim if (Reg == ARM::LR) { 340218885Sdim // Special epilogue for vararg functions. See emitEpilogue 341218885Sdim if (isVarArg) 342218885Sdim continue; 343218885Sdim Reg = ARM::PC; 344218885Sdim (*MIB).setDesc(TII.get(ARM::tPOP_RET)); 345218885Sdim MI = MBB.erase(MI); 346218885Sdim } 347218885Sdim MIB.addReg(Reg, getDefRegState(true)); 348218885Sdim NumRegs = true; 349218885Sdim } 350218885Sdim 351218885Sdim // It's illegal to emit pop instruction without operands. 352218885Sdim if (NumRegs) 353218885Sdim MBB.insert(MI, &*MIB); 354218885Sdim else 355218885Sdim MF.DeleteMachineInstr(MIB); 356218885Sdim 357218885Sdim return true; 358218885Sdim} 359