HexagonFrameLowering.cpp revision 234285
1238438Sdteske//===-- HexagonFrameLowering.cpp - Define frame lowering ------------------===// 2238438Sdteske// 3249746Sdteske// The LLVM Compiler Infrastructure 4238438Sdteske// 5238438Sdteske// This file is distributed under the University of Illinois Open Source 6238438Sdteske// License. See LICENSE.TXT for details. 7238438Sdteske// 8238438Sdteske// 9238438Sdteske//===----------------------------------------------------------------------===// 10238438Sdteske 11238438Sdteske#include "HexagonFrameLowering.h" 12238438Sdteske#include "Hexagon.h" 13238438Sdteske#include "HexagonInstrInfo.h" 14238438Sdteske#include "HexagonRegisterInfo.h" 15238438Sdteske#include "HexagonSubtarget.h" 16238438Sdteske#include "HexagonTargetMachine.h" 17238438Sdteske#include "HexagonMachineFunctionInfo.h" 18238438Sdteske#include "llvm/Function.h" 19238438Sdteske#include "llvm/Type.h" 20238438Sdteske#include "llvm/ADT/BitVector.h" 21238438Sdteske#include "llvm/ADT/STLExtras.h" 22238438Sdteske#include "llvm/CodeGen/AsmPrinter.h" 23238438Sdteske#include "llvm/CodeGen/MachineInstrBuilder.h" 24238438Sdteske#include "llvm/CodeGen/MachineFunction.h" 25238438Sdteske#include "llvm/CodeGen/MachineFunctionPass.h" 26238438Sdteske#include "llvm/CodeGen/MachineFrameInfo.h" 27238438Sdteske#include "llvm/CodeGen/MachineModuleInfo.h" 28238438Sdteske#include "llvm/CodeGen/MachineRegisterInfo.h" 29238438Sdteske#include "llvm/CodeGen/RegisterScavenging.h" 30238438Sdteske#include "llvm/MC/MachineLocation.h" 31240684Sdteske#include "llvm/MC/MCAsmInfo.h" 32240684Sdteske#include "llvm/Target/TargetInstrInfo.h" 33244675Sdteske#include "llvm/Target/TargetMachine.h" 34240684Sdteske#include "llvm/Target/TargetOptions.h" 35240684Sdteske#include "llvm/Support/CommandLine.h" 36240684Sdteske 37240684Sdteskeusing namespace llvm; 38238438Sdteske 39240684Sdteskestatic cl::opt<bool> DisableDeallocRet( 40238438Sdteske "disable-hexagon-dealloc-ret", 41238438Sdteske cl::Hidden, 42243112Sdteske cl::desc("Disable Dealloc Return for Hexagon target")); 43238438Sdteske 44238438Sdteske/// determineFrameLayout - Determine the size of the frame and maximum call 45238438Sdteske/// frame size. 46238438Sdteskevoid HexagonFrameLowering::determineFrameLayout(MachineFunction &MF) const { 47238438Sdteske MachineFrameInfo *MFI = MF.getFrameInfo(); 48238438Sdteske 49238438Sdteske // Get the number of bytes to allocate from the FrameInfo. 50238438Sdteske unsigned FrameSize = MFI->getStackSize(); 51238438Sdteske 52238438Sdteske // Get the alignments provided by the target. 53238438Sdteske unsigned TargetAlign = MF.getTarget().getFrameLowering()->getStackAlignment(); 54238438Sdteske // Get the maximum call frame size of all the calls. 55238438Sdteske unsigned maxCallFrameSize = MFI->getMaxCallFrameSize(); 56238438Sdteske 57240798Sdteske // If we have dynamic alloca then maxCallFrameSize needs to be aligned so 58238438Sdteske // that allocations will be aligned. 59238438Sdteske if (MFI->hasVarSizedObjects()) 60238438Sdteske maxCallFrameSize = RoundUpToAlignment(maxCallFrameSize, TargetAlign); 61238438Sdteske 62238438Sdteske // Update maximum call frame size. 63238438Sdteske MFI->setMaxCallFrameSize(maxCallFrameSize); 64238438Sdteske 65238438Sdteske // Include call frame size in total. 66238438Sdteske FrameSize += maxCallFrameSize; 67238438Sdteske 68238438Sdteske // Make sure the frame is aligned. 69238438Sdteske FrameSize = RoundUpToAlignment(FrameSize, TargetAlign); 70238438Sdteske 71238438Sdteske // Update frame info. 72238438Sdteske MFI->setStackSize(FrameSize); 73238438Sdteske} 74238438Sdteske 75249751Sdteske 76238438Sdteskevoid HexagonFrameLowering::emitPrologue(MachineFunction &MF) const { 77249751Sdteske MachineBasicBlock &MBB = MF.front(); 78249751Sdteske MachineFrameInfo *MFI = MF.getFrameInfo(); 79249751Sdteske MachineModuleInfo &MMI = MF.getMMI(); 80238438Sdteske MachineBasicBlock::iterator MBBI = MBB.begin(); 81249751Sdteske const HexagonRegisterInfo *QRI = 82238438Sdteske static_cast<const HexagonRegisterInfo *>(MF.getTarget().getRegisterInfo()); 83238438Sdteske DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 84238438Sdteske determineFrameLayout(MF); 85238438Sdteske 86238438Sdteske // Check if frame moves are needed for EH. 87249751Sdteske bool needsFrameMoves = MMI.hasDebugInfo() || 88240783Sdteske !MF.getFunction()->needsUnwindTableEntry(); 89240783Sdteske 90238438Sdteske // Get the number of bytes to allocate from the FrameInfo. 91238438Sdteske int NumBytes = (int) MFI->getStackSize(); 92238438Sdteske 93238438Sdteske // LLVM expects allocframe not to be the first instruction in the 94238438Sdteske // basic block. 95238438Sdteske MachineBasicBlock::iterator InsertPt = MBB.begin(); 96238438Sdteske 97238438Sdteske // 98238438Sdteske // ALLOCA adjust regs. Iterate over ADJDYNALLOC nodes and change the offset. 99238438Sdteske // 100238438Sdteske HexagonMachineFunctionInfo *FuncInfo = 101238438Sdteske MF.getInfo<HexagonMachineFunctionInfo>(); 102238438Sdteske const std::vector<MachineInstr*>& AdjustRegs = 103238438Sdteske FuncInfo->getAllocaAdjustInsts(); 104238438Sdteske for (std::vector<MachineInstr*>::const_iterator i = AdjustRegs.begin(), 105238438Sdteske e = AdjustRegs.end(); 106238438Sdteske i != e; ++i) { 107238438Sdteske MachineInstr* MI = *i; 108238438Sdteske assert((MI->getOpcode() == Hexagon::ADJDYNALLOC) && 109238438Sdteske "Expected adjust alloca node"); 110238438Sdteske 111238438Sdteske MachineOperand& MO = MI->getOperand(2); 112238438Sdteske assert(MO.isImm() && "Expected immediate"); 113238438Sdteske MO.setImm(MFI->getMaxCallFrameSize()); 114238438Sdteske } 115238438Sdteske 116238438Sdteske std::vector<MachineMove> &Moves = MMI.getFrameMoves(); 117238438Sdteske 118238438Sdteske if (needsFrameMoves) { 119238438Sdteske // Advance CFA. DW_CFA_def_cfa 120238438Sdteske unsigned FPReg = QRI->getFrameRegister(); 121238438Sdteske unsigned RAReg = QRI->getRARegister(); 122238438Sdteske 123238438Sdteske MachineLocation Dst(MachineLocation::VirtualFP); 124238438Sdteske MachineLocation Src(FPReg, -8); 125238438Sdteske Moves.push_back(MachineMove(0, Dst, Src)); 126238438Sdteske 127238438Sdteske // R31 = (R31 - #4) 128238438Sdteske MachineLocation LRDst(RAReg, -4); 129238438Sdteske MachineLocation LRSrc(RAReg); 130238438Sdteske Moves.push_back(MachineMove(0, LRDst, LRSrc)); 131238438Sdteske 132238438Sdteske // R30 = (R30 - #8) 133238438Sdteske MachineLocation SPDst(FPReg, -8); 134238438Sdteske MachineLocation SPSrc(FPReg); 135238438Sdteske Moves.push_back(MachineMove(0, SPDst, SPSrc)); 136238438Sdteske } 137238438Sdteske 138238438Sdteske // 139238438Sdteske // Only insert ALLOCFRAME if we need to. 140249751Sdteske // 141249751Sdteske if (hasFP(MF)) { 142238438Sdteske // Check for overflow. 143249751Sdteske // Hexagon_TODO: Ugh! hardcoding. Is there an API that can be used? 144249751Sdteske const int ALLOCFRAME_MAX = 16384; 145249751Sdteske const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); 146249751Sdteske 147249751Sdteske if (NumBytes >= ALLOCFRAME_MAX) { 148249751Sdteske // Emit allocframe(#0). 149249751Sdteske BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(0); 150249751Sdteske 151238438Sdteske // Subtract offset from frame pointer. 152249751Sdteske BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::CONST32_Int_Real), 153249751Sdteske HEXAGON_RESERVED_REG_1).addImm(NumBytes); 154249751Sdteske BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::SUB_rr), 155249751Sdteske QRI->getStackRegister()). 156249751Sdteske addReg(QRI->getStackRegister()). 157249751Sdteske addReg(HEXAGON_RESERVED_REG_1); 158249751Sdteske } else { 159249751Sdteske BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(NumBytes); 160249751Sdteske } 161249751Sdteske } 162249751Sdteske} 163249751Sdteske// Returns true if MBB has a machine instructions that indicates a tail call 164249751Sdteske// in the block. 165249751Sdteskebool HexagonFrameLowering::hasTailCall(MachineBasicBlock &MBB) const { 166249751Sdteske MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 167249751Sdteske unsigned RetOpcode = MBBI->getOpcode(); 168249751Sdteske 169249751Sdteske return RetOpcode == Hexagon::TCRETURNtg || RetOpcode == Hexagon::TCRETURNtext;} 170249751Sdteske 171249751Sdteskevoid HexagonFrameLowering::emitEpilogue(MachineFunction &MF, 172249751Sdteske MachineBasicBlock &MBB) const { 173249751Sdteske MachineBasicBlock::iterator MBBI = prior(MBB.end()); 174249751Sdteske DebugLoc dl = MBBI->getDebugLoc(); 175249751Sdteske // 176249751Sdteske // Only insert deallocframe if we need to. 177249751Sdteske // 178249751Sdteske if (hasFP(MF)) { 179249751Sdteske MachineBasicBlock::iterator MBBI = prior(MBB.end()); 180249751Sdteske MachineBasicBlock::iterator MBBI_end = MBB.end(); 181249751Sdteske // 182249751Sdteske // For Hexagon, we don't need the frame size. 183249751Sdteske // 184249751Sdteske MachineFrameInfo *MFI = MF.getFrameInfo(); 185249751Sdteske int NumBytes = (int) MFI->getStackSize(); 186249751Sdteske 187249751Sdteske const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); 188249751Sdteske 189249751Sdteske // Replace 'jumpr r31' instruction with dealloc_return for V4 and higher 190249751Sdteske // versions. 191249751Sdteske if (STI.hasV4TOps() && MBBI->getOpcode() == Hexagon::JMPR 192249751Sdteske && !DisableDeallocRet) { 193249751Sdteske // Remove jumpr node. 194249751Sdteske MBB.erase(MBBI); 195249751Sdteske // Add dealloc_return. 196249751Sdteske BuildMI(MBB, MBBI_end, dl, TII.get(Hexagon::DEALLOC_RET_V4)) 197249751Sdteske .addImm(NumBytes); 198249751Sdteske } else { // Add deallocframe for V2 and V3. 199251190Sdteske BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME)).addImm(NumBytes); 200251190Sdteske } 201251190Sdteske } 202251190Sdteske} 203251190Sdteske 204251190Sdteskebool HexagonFrameLowering::hasFP(const MachineFunction &MF) const { 205251190Sdteske const MachineFrameInfo *MFI = MF.getFrameInfo(); 206251190Sdteske const HexagonMachineFunctionInfo *FuncInfo = 207238438Sdteske MF.getInfo<HexagonMachineFunctionInfo>(); 208251236Sdteske return (MFI->hasCalls() || (MFI->getStackSize() > 0) || 209251236Sdteske FuncInfo->hasClobberLR() ); 210249751Sdteske} 211249751Sdteske 212249751Sdteskebool 213249751SdteskeHexagonFrameLowering::spillCalleeSavedRegisters( 214249751Sdteske MachineBasicBlock &MBB, 215249751Sdteske MachineBasicBlock::iterator MI, 216249751Sdteske const std::vector<CalleeSavedInfo> &CSI, 217249751Sdteske const TargetRegisterInfo *TRI) const { 218249751Sdteske MachineFunction *MF = MBB.getParent(); 219249751Sdteske const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); 220251190Sdteske 221251190Sdteske if (CSI.empty()) { 222249751Sdteske return false; 223240768Sdteske } 224240768Sdteske 225240768Sdteske // We can only schedule double loads if we spill contiguous callee-saved regs 226251236Sdteske // For instance, we cannot scheduled double-word loads if we spill r24, 227251236Sdteske // r26, and r27. 228249751Sdteske // Hexagon_TODO: We can try to double-word align odd registers for -O2 and 229249751Sdteske // above. 230251236Sdteske bool ContiguousRegs = true; 231249751Sdteske 232240768Sdteske for (unsigned i = 0; i < CSI.size(); ++i) { 233238438Sdteske unsigned Reg = CSI[i].getReg(); 234238438Sdteske 235249751Sdteske // 236238438Sdteske // Check if we can use a double-word store. 237249751Sdteske // 238249751Sdteske const uint16_t* SuperReg = TRI->getSuperRegisters(Reg); 239249751Sdteske 240238438Sdteske // Assume that there is exactly one superreg. 241249751Sdteske assert(SuperReg[0] && !SuperReg[1] && "Expected exactly one superreg"); 242238438Sdteske bool CanUseDblStore = false; 243238438Sdteske const TargetRegisterClass* SuperRegClass = 0; 244238438Sdteske 245238438Sdteske if (ContiguousRegs && (i < CSI.size()-1)) { 246238438Sdteske const uint16_t* SuperRegNext = TRI->getSuperRegisters(CSI[i+1].getReg()); 247238438Sdteske assert(SuperRegNext[0] && !SuperRegNext[1] && 248238438Sdteske "Expected exactly one superreg"); 249238438Sdteske SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg[0]); 250245402Sdteske CanUseDblStore = (SuperRegNext[0] == SuperReg[0]); 251238438Sdteske } 252238438Sdteske 253238438Sdteske 254238438Sdteske if (CanUseDblStore) { 255238438Sdteske TII.storeRegToStackSlot(MBB, MI, SuperReg[0], true, 256238438Sdteske CSI[i+1].getFrameIdx(), SuperRegClass, TRI); 257238438Sdteske MBB.addLiveIn(SuperReg[0]); 258238438Sdteske ++i; 259238438Sdteske } else { 260238438Sdteske // Cannot use a double-word store. 261238438Sdteske ContiguousRegs = false; 262238438Sdteske const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 263238438Sdteske TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(), RC, 264238438Sdteske TRI); 265238438Sdteske MBB.addLiveIn(Reg); 266238438Sdteske } 267238438Sdteske } 268238438Sdteske return true; 269238438Sdteske} 270238438Sdteske 271238438Sdteske 272238438Sdteskebool HexagonFrameLowering::restoreCalleeSavedRegisters( 273238438Sdteske MachineBasicBlock &MBB, 274251190Sdteske MachineBasicBlock::iterator MI, 275251190Sdteske const std::vector<CalleeSavedInfo> &CSI, 276251190Sdteske const TargetRegisterInfo *TRI) const { 277251190Sdteske 278251190Sdteske MachineFunction *MF = MBB.getParent(); 279251190Sdteske const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); 280251190Sdteske 281238438Sdteske if (CSI.empty()) { 282238438Sdteske return false; 283238438Sdteske } 284238438Sdteske 285249751Sdteske // We can only schedule double loads if we spill contiguous callee-saved regs 286249751Sdteske // For instance, we cannot scheduled double-word loads if we spill r24, 287238438Sdteske // r26, and r27. 288238438Sdteske // Hexagon_TODO: We can try to double-word align odd registers for -O2 and 289238438Sdteske // above. 290238438Sdteske bool ContiguousRegs = true; 291238438Sdteske 292251190Sdteske for (unsigned i = 0; i < CSI.size(); ++i) { 293251190Sdteske unsigned Reg = CSI[i].getReg(); 294238438Sdteske 295249751Sdteske // 296249954Sdteske // Check if we can use a double-word load. 297249954Sdteske // 298238438Sdteske const uint16_t* SuperReg = TRI->getSuperRegisters(Reg); 299238438Sdteske const TargetRegisterClass* SuperRegClass = 0; 300238438Sdteske 301238438Sdteske // Assume that there is exactly one superreg. 302238438Sdteske assert(SuperReg[0] && !SuperReg[1] && "Expected exactly one superreg"); 303238438Sdteske bool CanUseDblLoad = false; 304238438Sdteske if (ContiguousRegs && (i < CSI.size()-1)) { 305238438Sdteske const uint16_t* SuperRegNext = TRI->getSuperRegisters(CSI[i+1].getReg()); 306238438Sdteske assert(SuperRegNext[0] && !SuperRegNext[1] && 307238438Sdteske "Expected exactly one superreg"); 308250633Sdteske SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg[0]); 309238438Sdteske CanUseDblLoad = (SuperRegNext[0] == SuperReg[0]); 310238438Sdteske } 311238438Sdteske 312238438Sdteske 313238438Sdteske if (CanUseDblLoad) { 314238438Sdteske TII.loadRegFromStackSlot(MBB, MI, SuperReg[0], CSI[i+1].getFrameIdx(), 315238438Sdteske SuperRegClass, TRI); 316238438Sdteske MBB.addLiveIn(SuperReg[0]); 317238438Sdteske ++i; 318238438Sdteske } else { 319238438Sdteske // Cannot use a double-word load. 320238438Sdteske ContiguousRegs = false; 321238438Sdteske const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 322249751Sdteske TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), RC, TRI); 323249751Sdteske MBB.addLiveIn(Reg); 324249751Sdteske } 325249751Sdteske } 326249751Sdteske return true; 327249751Sdteske} 328249751Sdteske 329249751Sdteskeint HexagonFrameLowering::getFrameIndexOffset(const MachineFunction &MF, 330249751Sdteske int FI) const { 331249751Sdteske return MF.getFrameInfo()->getObjectOffset(FI); 332238438Sdteske} 333238438Sdteske