HexagonFrameLowering.cpp revision 239462
153247Sarchie//===-- HexagonFrameLowering.cpp - Define frame lowering ------------------===// 253247Sarchie// 379727Sschweikh// The LLVM Compiler Infrastructure 453247Sarchie// 553247Sarchie// This file is distributed under the University of Illinois Open Source 653247Sarchie// License. See LICENSE.TXT for details. 753247Sarchie// 853247Sarchie// 953247Sarchie//===----------------------------------------------------------------------===// 1053247Sarchie 1153247Sarchie#include "HexagonFrameLowering.h" 1253247Sarchie#include "Hexagon.h" 1353247Sarchie#include "HexagonInstrInfo.h" 1479727Sschweikh#include "HexagonRegisterInfo.h" 1553247Sarchie#include "HexagonSubtarget.h" 1653247Sarchie#include "HexagonTargetMachine.h" 1753247Sarchie#include "HexagonMachineFunctionInfo.h" 1853247Sarchie#include "llvm/Function.h" 1953247Sarchie#include "llvm/Type.h" 2053247Sarchie#include "llvm/ADT/BitVector.h" 2153247Sarchie#include "llvm/ADT/STLExtras.h" 2253247Sarchie#include "llvm/CodeGen/AsmPrinter.h" 2353247Sarchie#include "llvm/CodeGen/MachineInstrBuilder.h" 2453247Sarchie#include "llvm/CodeGen/MachineFunction.h" 2553247Sarchie#include "llvm/CodeGen/MachineFunctionPass.h" 2653247Sarchie#include "llvm/CodeGen/MachineFrameInfo.h" 2753247Sarchie#include "llvm/CodeGen/MachineModuleInfo.h" 2853247Sarchie#include "llvm/CodeGen/MachineRegisterInfo.h" 2953247Sarchie#include "llvm/CodeGen/RegisterScavenging.h" 3053247Sarchie#include "llvm/MC/MachineLocation.h" 3153247Sarchie#include "llvm/MC/MCAsmInfo.h" 3279727Sschweikh#include "llvm/Target/TargetInstrInfo.h" 3367627Sasmodai#include "llvm/Target/TargetMachine.h" 3453247Sarchie#include "llvm/Target/TargetOptions.h" 3553247Sarchie#include "llvm/Support/CommandLine.h" 3653247Sarchie 37236596Seadlerusing namespace llvm; 3859982Sarchie 3979538Srustatic cl::opt<bool> DisableDeallocRet( 4053247Sarchie "disable-hexagon-dealloc-ret", 4153247Sarchie cl::Hidden, 4253247Sarchie cl::desc("Disable Dealloc Return for Hexagon target")); 4353247Sarchie 44141350Sru/// determineFrameLayout - Determine the size of the frame and maximum call 4584306Sru/// frame size. 4653247Sarchievoid HexagonFrameLowering::determineFrameLayout(MachineFunction &MF) const { 4753247Sarchie MachineFrameInfo *MFI = MF.getFrameInfo(); 4853247Sarchie 4981622Sru // Get the number of bytes to allocate from the FrameInfo. 5081622Sru unsigned FrameSize = MFI->getStackSize(); 51117011Sru 52117011Sru // Get the alignments provided by the target. 5354927Sjulian unsigned TargetAlign = MF.getTarget().getFrameLowering()->getStackAlignment(); 5453247Sarchie // Get the maximum call frame size of all the calls. 55117011Sru unsigned maxCallFrameSize = MFI->getMaxCallFrameSize(); 56117011Sru 5754927Sjulian // If we have dynamic alloca then maxCallFrameSize needs to be aligned so 5853247Sarchie // that allocations will be aligned. 5959982Sarchie if (MFI->hasVarSizedObjects()) 6053247Sarchie maxCallFrameSize = RoundUpToAlignment(maxCallFrameSize, TargetAlign); 6153939Sarchie 6253939Sarchie // Update maximum call frame size. 6354927Sjulian MFI->setMaxCallFrameSize(maxCallFrameSize); 6453247Sarchie 6553939Sarchie // Include call frame size in total. 6653247Sarchie FrameSize += maxCallFrameSize; 6753247Sarchie 6854927Sjulian // Make sure the frame is aligned. 69117011Sru FrameSize = RoundUpToAlignment(FrameSize, TargetAlign); 70117011Sru 71117011Sru // Update frame info. 72117011Sru MFI->setStackSize(FrameSize); 7353939Sarchie} 7453247Sarchie 7553247Sarchie 7653247Sarchievoid HexagonFrameLowering::emitPrologue(MachineFunction &MF) const { 7753247Sarchie MachineBasicBlock &MBB = MF.front(); 7853247Sarchie MachineFrameInfo *MFI = MF.getFrameInfo(); 7973233Sru MachineModuleInfo &MMI = MF.getMMI(); 8053247Sarchie MachineBasicBlock::iterator MBBI = MBB.begin(); 8173233Sru const HexagonRegisterInfo *QRI = 8273233Sru static_cast<const HexagonRegisterInfo *>(MF.getTarget().getRegisterInfo()); 8353247Sarchie DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 8473233Sru determineFrameLayout(MF); 8553247Sarchie 8653247Sarchie // Check if frame moves are needed for EH. 8753247Sarchie bool needsFrameMoves = MMI.hasDebugInfo() || 88131530Sru !MF.getFunction()->needsUnwindTableEntry(); 89131530Sru 9053247Sarchie // Get the number of bytes to allocate from the FrameInfo. 9179727Sschweikh int NumBytes = (int) MFI->getStackSize(); 9253247Sarchie 93131108Sjulian // LLVM expects allocframe not to be the first instruction in the 94131108Sjulian // basic block. 95131108Sjulian MachineBasicBlock::iterator InsertPt = MBB.begin(); 96131108Sjulian 97131108Sjulian // 98131108Sjulian // ALLOCA adjust regs. Iterate over ADJDYNALLOC nodes and change the offset. 99131108Sjulian // 100131530Sru HexagonMachineFunctionInfo *FuncInfo = 101131108Sjulian MF.getInfo<HexagonMachineFunctionInfo>(); 102131108Sjulian const std::vector<MachineInstr*>& AdjustRegs = 103131108Sjulian FuncInfo->getAllocaAdjustInsts(); 104131108Sjulian for (std::vector<MachineInstr*>::const_iterator i = AdjustRegs.begin(), 105131108Sjulian e = AdjustRegs.end(); 106131108Sjulian i != e; ++i) { 107131108Sjulian MachineInstr* MI = *i; 108131108Sjulian assert((MI->getOpcode() == Hexagon::ADJDYNALLOC) && 109131530Sru "Expected adjust alloca node"); 110131108Sjulian 11153247Sarchie MachineOperand& MO = MI->getOperand(2); 11253247Sarchie assert(MO.isImm() && "Expected immediate"); 11353247Sarchie MO.setImm(MFI->getMaxCallFrameSize()); 114242997Sjoel } 11553247Sarchie 11653247Sarchie std::vector<MachineMove> &Moves = MMI.getFrameMoves(); 117117011Sru 118117011Sru if (needsFrameMoves) { 119131530Sru // Advance CFA. DW_CFA_def_cfa 12053247Sarchie unsigned FPReg = QRI->getFrameRegister(); 121242997Sjoel unsigned RAReg = QRI->getRARegister(); 12253247Sarchie 12353247Sarchie MachineLocation Dst(MachineLocation::VirtualFP); 124117011Sru MachineLocation Src(FPReg, -8); 125117011Sru Moves.push_back(MachineMove(0, Dst, Src)); 12653247Sarchie 12753247Sarchie // R31 = (R31 - #4) 128242997Sjoel MachineLocation LRDst(RAReg, -4); 12953247Sarchie MachineLocation LRSrc(RAReg); 13053247Sarchie Moves.push_back(MachineMove(0, LRDst, LRSrc)); 131117011Sru 132117011Sru // R30 = (R30 - #8) 133131530Sru MachineLocation SPDst(FPReg, -8); 13453939Sarchie MachineLocation SPSrc(FPReg); 135242997Sjoel Moves.push_back(MachineMove(0, SPDst, SPSrc)); 136151798Sru } 137151798Sru 138151798Sru // 139151798Sru // Only insert ALLOCFRAME if we need to. 140151798Sru // 141151798Sru if (hasFP(MF)) { 142151798Sru // Check for overflow. 143151798Sru // Hexagon_TODO: Ugh! hardcoding. Is there an API that can be used? 144151798Sru const int ALLOCFRAME_MAX = 16384; 145151798Sru const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); 146151798Sru 147151798Sru if (NumBytes >= ALLOCFRAME_MAX) { 148151798Sru // Emit allocframe(#0). 149151798Sru BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(0); 150151798Sru 151242997Sjoel // Subtract offset from frame pointer. 15253939Sarchie BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::CONST32_Int_Real), 15377973Ssobomax HEXAGON_RESERVED_REG_1).addImm(NumBytes); 154117011Sru BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::SUB_rr), 155117011Sru QRI->getStackRegister()). 156131530Sru addReg(QRI->getStackRegister()). 15753939Sarchie addReg(HEXAGON_RESERVED_REG_1); 158242997Sjoel } else { 15953939Sarchie BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(NumBytes); 16053939Sarchie } 161117011Sru } 162117011Sru} 163131530Sru// Returns true if MBB has a machine instructions that indicates a tail call 16453939Sarchie// in the block. 165242997Sjoelbool HexagonFrameLowering::hasTailCall(MachineBasicBlock &MBB) const { 16653939Sarchie MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 16753939Sarchie unsigned RetOpcode = MBBI->getOpcode(); 16853939Sarchie 169131530Sru return RetOpcode == Hexagon::TCRETURNtg || RetOpcode == Hexagon::TCRETURNtext;} 170242997Sjoel 17153939Sarchievoid HexagonFrameLowering::emitEpilogue(MachineFunction &MF, 17253939Sarchie MachineBasicBlock &MBB) const { 17353939Sarchie MachineBasicBlock::iterator MBBI = prior(MBB.end()); 174131530Sru DebugLoc dl = MBBI->getDebugLoc(); 17553939Sarchie // 17653939Sarchie // Only insert deallocframe if we need to. 17753939Sarchie // 17853939Sarchie if (hasFP(MF)) { 17953247Sarchie MachineBasicBlock::iterator MBBI = prior(MBB.end()); 18053939Sarchie MachineBasicBlock::iterator MBBI_end = MBB.end(); 18153939Sarchie // 182131530Sru // For Hexagon, we don't need the frame size. 18354927Sjulian // 18454927Sjulian MachineFrameInfo *MFI = MF.getFrameInfo(); 18554927Sjulian int NumBytes = (int) MFI->getStackSize(); 186117011Sru 187117011Sru const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); 18853939Sarchie 18953939Sarchie // Replace 'jumpr r31' instruction with dealloc_return for V4 and higher 19053939Sarchie // versions. 19153939Sarchie if (STI.hasV4TOps() && MBBI->getOpcode() == Hexagon::JMPR 19253939Sarchie && !DisableDeallocRet) { 193117011Sru // Remove jumpr node. 194117011Sru MBB.erase(MBBI); 19553939Sarchie // Add dealloc_return. 19653939Sarchie BuildMI(MBB, MBBI_end, dl, TII.get(Hexagon::DEALLOC_RET_V4)) 19753939Sarchie .addImm(NumBytes); 19853939Sarchie } else { // Add deallocframe for V2 and V3. 19953939Sarchie BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME)).addImm(NumBytes); 20053939Sarchie } 20153939Sarchie } 202229930Smelifaro} 20353939Sarchie 20458007Sarchiebool HexagonFrameLowering::hasFP(const MachineFunction &MF) const { 20558007Sarchie const MachineFrameInfo *MFI = MF.getFrameInfo(); 20653939Sarchie const HexagonMachineFunctionInfo *FuncInfo = 20753939Sarchie MF.getInfo<HexagonMachineFunctionInfo>(); 20858007Sarchie return (MFI->hasCalls() || (MFI->getStackSize() > 0) || 20953939Sarchie FuncInfo->hasClobberLR() ); 21053939Sarchie} 21153939Sarchie 212131530Srustatic inline 21354927Sjulianunsigned uniqueSuperReg(unsigned Reg, const TargetRegisterInfo *TRI) { 21454927Sjulian MCSuperRegIterator SRI(Reg, TRI); 215117011Sru assert(SRI.isValid() && "Expected a superreg"); 216117011Sru unsigned SuperReg = *SRI; 21753939Sarchie ++SRI; 218229930Smelifaro assert(!SRI.isValid() && "Expected exactly one superreg"); 219229930Smelifaro return SuperReg; 220229930Smelifaro} 221229930Smelifaro 222229930Smelifarobool 223229930SmelifaroHexagonFrameLowering::spillCalleeSavedRegisters( 22453247Sarchie MachineBasicBlock &MBB, 22553247Sarchie MachineBasicBlock::iterator MI, 22653247Sarchie const std::vector<CalleeSavedInfo> &CSI, 22753247Sarchie const TargetRegisterInfo *TRI) const { 22853247Sarchie MachineFunction *MF = MBB.getParent(); 22953247Sarchie const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); 23053247Sarchie 23153247Sarchie if (CSI.empty()) { 23259982Sarchie return false; 233131108Sjulian } 234165282Srwatson 235165282Srwatson // We can only schedule double loads if we spill contiguous callee-saved regs 23654927Sjulian // For instance, we cannot scheduled double-word loads if we spill r24, 23754927Sjulian // r26, and r27. 23854927Sjulian // Hexagon_TODO: We can try to double-word align odd registers for -O2 and 23954927Sjulian // above. 24054927Sjulian bool ContiguousRegs = true; 24154927Sjulian 24267627Sasmodai for (unsigned i = 0; i < CSI.size(); ++i) { 243 unsigned Reg = CSI[i].getReg(); 244 245 // 246 // Check if we can use a double-word store. 247 // 248 unsigned SuperReg = uniqueSuperReg(Reg, TRI); 249 bool CanUseDblStore = false; 250 const TargetRegisterClass* SuperRegClass = 0; 251 252 if (ContiguousRegs && (i < CSI.size()-1)) { 253 unsigned SuperRegNext = uniqueSuperReg(CSI[i+1].getReg(), TRI); 254 SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg); 255 CanUseDblStore = (SuperRegNext == SuperReg); 256 } 257 258 259 if (CanUseDblStore) { 260 TII.storeRegToStackSlot(MBB, MI, SuperReg, true, 261 CSI[i+1].getFrameIdx(), SuperRegClass, TRI); 262 MBB.addLiveIn(SuperReg); 263 ++i; 264 } else { 265 // Cannot use a double-word store. 266 ContiguousRegs = false; 267 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 268 TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(), RC, 269 TRI); 270 MBB.addLiveIn(Reg); 271 } 272 } 273 return true; 274} 275 276 277bool HexagonFrameLowering::restoreCalleeSavedRegisters( 278 MachineBasicBlock &MBB, 279 MachineBasicBlock::iterator MI, 280 const std::vector<CalleeSavedInfo> &CSI, 281 const TargetRegisterInfo *TRI) const { 282 283 MachineFunction *MF = MBB.getParent(); 284 const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); 285 286 if (CSI.empty()) { 287 return false; 288 } 289 290 // We can only schedule double loads if we spill contiguous callee-saved regs 291 // For instance, we cannot scheduled double-word loads if we spill r24, 292 // r26, and r27. 293 // Hexagon_TODO: We can try to double-word align odd registers for -O2 and 294 // above. 295 bool ContiguousRegs = true; 296 297 for (unsigned i = 0; i < CSI.size(); ++i) { 298 unsigned Reg = CSI[i].getReg(); 299 300 // 301 // Check if we can use a double-word load. 302 // 303 unsigned SuperReg = uniqueSuperReg(Reg, TRI); 304 const TargetRegisterClass* SuperRegClass = 0; 305 bool CanUseDblLoad = false; 306 if (ContiguousRegs && (i < CSI.size()-1)) { 307 unsigned SuperRegNext = uniqueSuperReg(CSI[i+1].getReg(), TRI); 308 SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg); 309 CanUseDblLoad = (SuperRegNext == SuperReg); 310 } 311 312 313 if (CanUseDblLoad) { 314 TII.loadRegFromStackSlot(MBB, MI, SuperReg, CSI[i+1].getFrameIdx(), 315 SuperRegClass, TRI); 316 MBB.addLiveIn(SuperReg); 317 ++i; 318 } else { 319 // Cannot use a double-word load. 320 ContiguousRegs = false; 321 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 322 TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), RC, TRI); 323 MBB.addLiveIn(Reg); 324 } 325 } 326 return true; 327} 328 329int HexagonFrameLowering::getFrameIndexOffset(const MachineFunction &MF, 330 int FI) const { 331 return MF.getFrameInfo()->getObjectOffset(FI); 332} 333