HexagonFrameLowering.cpp revision 234285
1234285Sdim//===-- HexagonFrameLowering.cpp - Define frame lowering ------------------===// 2234285Sdim// 3234285Sdim// The LLVM Compiler Infrastructure 4234285Sdim// 5234285Sdim// This file is distributed under the University of Illinois Open Source 6234285Sdim// License. See LICENSE.TXT for details. 7234285Sdim// 8234285Sdim// 9234285Sdim//===----------------------------------------------------------------------===// 10234285Sdim 11234285Sdim#include "HexagonFrameLowering.h" 12234285Sdim#include "Hexagon.h" 13234285Sdim#include "HexagonInstrInfo.h" 14234285Sdim#include "HexagonRegisterInfo.h" 15234285Sdim#include "HexagonSubtarget.h" 16234285Sdim#include "HexagonTargetMachine.h" 17234285Sdim#include "HexagonMachineFunctionInfo.h" 18234285Sdim#include "llvm/Function.h" 19234285Sdim#include "llvm/Type.h" 20234285Sdim#include "llvm/ADT/BitVector.h" 21234285Sdim#include "llvm/ADT/STLExtras.h" 22234285Sdim#include "llvm/CodeGen/AsmPrinter.h" 23234285Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 24234285Sdim#include "llvm/CodeGen/MachineFunction.h" 25234285Sdim#include "llvm/CodeGen/MachineFunctionPass.h" 26234285Sdim#include "llvm/CodeGen/MachineFrameInfo.h" 27234285Sdim#include "llvm/CodeGen/MachineModuleInfo.h" 28234285Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 29234285Sdim#include "llvm/CodeGen/RegisterScavenging.h" 30234285Sdim#include "llvm/MC/MachineLocation.h" 31234285Sdim#include "llvm/MC/MCAsmInfo.h" 32234285Sdim#include "llvm/Target/TargetInstrInfo.h" 33234285Sdim#include "llvm/Target/TargetMachine.h" 34234285Sdim#include "llvm/Target/TargetOptions.h" 35234285Sdim#include "llvm/Support/CommandLine.h" 36234285Sdim 37234285Sdimusing namespace llvm; 38234285Sdim 39234285Sdimstatic cl::opt<bool> DisableDeallocRet( 40234285Sdim "disable-hexagon-dealloc-ret", 41234285Sdim cl::Hidden, 42234285Sdim cl::desc("Disable Dealloc Return for Hexagon target")); 43234285Sdim 44234285Sdim/// determineFrameLayout - Determine the size of the frame and maximum call 45234285Sdim/// frame size. 46234285Sdimvoid HexagonFrameLowering::determineFrameLayout(MachineFunction &MF) const { 47234285Sdim MachineFrameInfo *MFI = MF.getFrameInfo(); 48234285Sdim 49234285Sdim // Get the number of bytes to allocate from the FrameInfo. 50234285Sdim unsigned FrameSize = MFI->getStackSize(); 51234285Sdim 52234285Sdim // Get the alignments provided by the target. 53234285Sdim unsigned TargetAlign = MF.getTarget().getFrameLowering()->getStackAlignment(); 54234285Sdim // Get the maximum call frame size of all the calls. 55234285Sdim unsigned maxCallFrameSize = MFI->getMaxCallFrameSize(); 56234285Sdim 57234285Sdim // If we have dynamic alloca then maxCallFrameSize needs to be aligned so 58234285Sdim // that allocations will be aligned. 59234285Sdim if (MFI->hasVarSizedObjects()) 60234285Sdim maxCallFrameSize = RoundUpToAlignment(maxCallFrameSize, TargetAlign); 61234285Sdim 62234285Sdim // Update maximum call frame size. 63234285Sdim MFI->setMaxCallFrameSize(maxCallFrameSize); 64234285Sdim 65234285Sdim // Include call frame size in total. 66234285Sdim FrameSize += maxCallFrameSize; 67234285Sdim 68234285Sdim // Make sure the frame is aligned. 69234285Sdim FrameSize = RoundUpToAlignment(FrameSize, TargetAlign); 70234285Sdim 71234285Sdim // Update frame info. 72234285Sdim MFI->setStackSize(FrameSize); 73234285Sdim} 74234285Sdim 75234285Sdim 76234285Sdimvoid HexagonFrameLowering::emitPrologue(MachineFunction &MF) const { 77234285Sdim MachineBasicBlock &MBB = MF.front(); 78234285Sdim MachineFrameInfo *MFI = MF.getFrameInfo(); 79234285Sdim MachineModuleInfo &MMI = MF.getMMI(); 80234285Sdim MachineBasicBlock::iterator MBBI = MBB.begin(); 81234285Sdim const HexagonRegisterInfo *QRI = 82234285Sdim static_cast<const HexagonRegisterInfo *>(MF.getTarget().getRegisterInfo()); 83234285Sdim DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 84234285Sdim determineFrameLayout(MF); 85234285Sdim 86234285Sdim // Check if frame moves are needed for EH. 87234285Sdim bool needsFrameMoves = MMI.hasDebugInfo() || 88234285Sdim !MF.getFunction()->needsUnwindTableEntry(); 89234285Sdim 90234285Sdim // Get the number of bytes to allocate from the FrameInfo. 91234285Sdim int NumBytes = (int) MFI->getStackSize(); 92234285Sdim 93234285Sdim // LLVM expects allocframe not to be the first instruction in the 94234285Sdim // basic block. 95234285Sdim MachineBasicBlock::iterator InsertPt = MBB.begin(); 96234285Sdim 97234285Sdim // 98234285Sdim // ALLOCA adjust regs. Iterate over ADJDYNALLOC nodes and change the offset. 99234285Sdim // 100234285Sdim HexagonMachineFunctionInfo *FuncInfo = 101234285Sdim MF.getInfo<HexagonMachineFunctionInfo>(); 102234285Sdim const std::vector<MachineInstr*>& AdjustRegs = 103234285Sdim FuncInfo->getAllocaAdjustInsts(); 104234285Sdim for (std::vector<MachineInstr*>::const_iterator i = AdjustRegs.begin(), 105234285Sdim e = AdjustRegs.end(); 106234285Sdim i != e; ++i) { 107234285Sdim MachineInstr* MI = *i; 108234285Sdim assert((MI->getOpcode() == Hexagon::ADJDYNALLOC) && 109234285Sdim "Expected adjust alloca node"); 110234285Sdim 111234285Sdim MachineOperand& MO = MI->getOperand(2); 112234285Sdim assert(MO.isImm() && "Expected immediate"); 113234285Sdim MO.setImm(MFI->getMaxCallFrameSize()); 114234285Sdim } 115234285Sdim 116234285Sdim std::vector<MachineMove> &Moves = MMI.getFrameMoves(); 117234285Sdim 118234285Sdim if (needsFrameMoves) { 119234285Sdim // Advance CFA. DW_CFA_def_cfa 120234285Sdim unsigned FPReg = QRI->getFrameRegister(); 121234285Sdim unsigned RAReg = QRI->getRARegister(); 122234285Sdim 123234285Sdim MachineLocation Dst(MachineLocation::VirtualFP); 124234285Sdim MachineLocation Src(FPReg, -8); 125234285Sdim Moves.push_back(MachineMove(0, Dst, Src)); 126234285Sdim 127234285Sdim // R31 = (R31 - #4) 128234285Sdim MachineLocation LRDst(RAReg, -4); 129234285Sdim MachineLocation LRSrc(RAReg); 130234285Sdim Moves.push_back(MachineMove(0, LRDst, LRSrc)); 131234285Sdim 132234285Sdim // R30 = (R30 - #8) 133234285Sdim MachineLocation SPDst(FPReg, -8); 134234285Sdim MachineLocation SPSrc(FPReg); 135234285Sdim Moves.push_back(MachineMove(0, SPDst, SPSrc)); 136234285Sdim } 137234285Sdim 138234285Sdim // 139234285Sdim // Only insert ALLOCFRAME if we need to. 140234285Sdim // 141234285Sdim if (hasFP(MF)) { 142234285Sdim // Check for overflow. 143234285Sdim // Hexagon_TODO: Ugh! hardcoding. Is there an API that can be used? 144234285Sdim const int ALLOCFRAME_MAX = 16384; 145234285Sdim const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); 146234285Sdim 147234285Sdim if (NumBytes >= ALLOCFRAME_MAX) { 148234285Sdim // Emit allocframe(#0). 149234285Sdim BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(0); 150234285Sdim 151234285Sdim // Subtract offset from frame pointer. 152234285Sdim BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::CONST32_Int_Real), 153234285Sdim HEXAGON_RESERVED_REG_1).addImm(NumBytes); 154234285Sdim BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::SUB_rr), 155234285Sdim QRI->getStackRegister()). 156234285Sdim addReg(QRI->getStackRegister()). 157234285Sdim addReg(HEXAGON_RESERVED_REG_1); 158234285Sdim } else { 159234285Sdim BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(NumBytes); 160234285Sdim } 161234285Sdim } 162234285Sdim} 163234285Sdim// Returns true if MBB has a machine instructions that indicates a tail call 164234285Sdim// in the block. 165234285Sdimbool HexagonFrameLowering::hasTailCall(MachineBasicBlock &MBB) const { 166234285Sdim MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 167234285Sdim unsigned RetOpcode = MBBI->getOpcode(); 168234285Sdim 169234285Sdim return RetOpcode == Hexagon::TCRETURNtg || RetOpcode == Hexagon::TCRETURNtext;} 170234285Sdim 171234285Sdimvoid HexagonFrameLowering::emitEpilogue(MachineFunction &MF, 172234285Sdim MachineBasicBlock &MBB) const { 173234285Sdim MachineBasicBlock::iterator MBBI = prior(MBB.end()); 174234285Sdim DebugLoc dl = MBBI->getDebugLoc(); 175234285Sdim // 176234285Sdim // Only insert deallocframe if we need to. 177234285Sdim // 178234285Sdim if (hasFP(MF)) { 179234285Sdim MachineBasicBlock::iterator MBBI = prior(MBB.end()); 180234285Sdim MachineBasicBlock::iterator MBBI_end = MBB.end(); 181234285Sdim // 182234285Sdim // For Hexagon, we don't need the frame size. 183234285Sdim // 184234285Sdim MachineFrameInfo *MFI = MF.getFrameInfo(); 185234285Sdim int NumBytes = (int) MFI->getStackSize(); 186234285Sdim 187234285Sdim const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); 188234285Sdim 189234285Sdim // Replace 'jumpr r31' instruction with dealloc_return for V4 and higher 190234285Sdim // versions. 191234285Sdim if (STI.hasV4TOps() && MBBI->getOpcode() == Hexagon::JMPR 192234285Sdim && !DisableDeallocRet) { 193234285Sdim // Remove jumpr node. 194234285Sdim MBB.erase(MBBI); 195234285Sdim // Add dealloc_return. 196234285Sdim BuildMI(MBB, MBBI_end, dl, TII.get(Hexagon::DEALLOC_RET_V4)) 197234285Sdim .addImm(NumBytes); 198234285Sdim } else { // Add deallocframe for V2 and V3. 199234285Sdim BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME)).addImm(NumBytes); 200234285Sdim } 201234285Sdim } 202234285Sdim} 203234285Sdim 204234285Sdimbool HexagonFrameLowering::hasFP(const MachineFunction &MF) const { 205234285Sdim const MachineFrameInfo *MFI = MF.getFrameInfo(); 206234285Sdim const HexagonMachineFunctionInfo *FuncInfo = 207234285Sdim MF.getInfo<HexagonMachineFunctionInfo>(); 208234285Sdim return (MFI->hasCalls() || (MFI->getStackSize() > 0) || 209234285Sdim FuncInfo->hasClobberLR() ); 210234285Sdim} 211234285Sdim 212234285Sdimbool 213234285SdimHexagonFrameLowering::spillCalleeSavedRegisters( 214234285Sdim MachineBasicBlock &MBB, 215234285Sdim MachineBasicBlock::iterator MI, 216234285Sdim const std::vector<CalleeSavedInfo> &CSI, 217234285Sdim const TargetRegisterInfo *TRI) const { 218234285Sdim MachineFunction *MF = MBB.getParent(); 219234285Sdim const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); 220234285Sdim 221234285Sdim if (CSI.empty()) { 222234285Sdim return false; 223234285Sdim } 224234285Sdim 225234285Sdim // We can only schedule double loads if we spill contiguous callee-saved regs 226234285Sdim // For instance, we cannot scheduled double-word loads if we spill r24, 227234285Sdim // r26, and r27. 228234285Sdim // Hexagon_TODO: We can try to double-word align odd registers for -O2 and 229234285Sdim // above. 230234285Sdim bool ContiguousRegs = true; 231234285Sdim 232234285Sdim for (unsigned i = 0; i < CSI.size(); ++i) { 233234285Sdim unsigned Reg = CSI[i].getReg(); 234234285Sdim 235234285Sdim // 236234285Sdim // Check if we can use a double-word store. 237234285Sdim // 238234285Sdim const uint16_t* SuperReg = TRI->getSuperRegisters(Reg); 239234285Sdim 240234285Sdim // Assume that there is exactly one superreg. 241234285Sdim assert(SuperReg[0] && !SuperReg[1] && "Expected exactly one superreg"); 242234285Sdim bool CanUseDblStore = false; 243234285Sdim const TargetRegisterClass* SuperRegClass = 0; 244234285Sdim 245234285Sdim if (ContiguousRegs && (i < CSI.size()-1)) { 246234285Sdim const uint16_t* SuperRegNext = TRI->getSuperRegisters(CSI[i+1].getReg()); 247234285Sdim assert(SuperRegNext[0] && !SuperRegNext[1] && 248234285Sdim "Expected exactly one superreg"); 249234285Sdim SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg[0]); 250234285Sdim CanUseDblStore = (SuperRegNext[0] == SuperReg[0]); 251234285Sdim } 252234285Sdim 253234285Sdim 254234285Sdim if (CanUseDblStore) { 255234285Sdim TII.storeRegToStackSlot(MBB, MI, SuperReg[0], true, 256234285Sdim CSI[i+1].getFrameIdx(), SuperRegClass, TRI); 257234285Sdim MBB.addLiveIn(SuperReg[0]); 258234285Sdim ++i; 259234285Sdim } else { 260234285Sdim // Cannot use a double-word store. 261234285Sdim ContiguousRegs = false; 262234285Sdim const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 263234285Sdim TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(), RC, 264234285Sdim TRI); 265234285Sdim MBB.addLiveIn(Reg); 266234285Sdim } 267234285Sdim } 268234285Sdim return true; 269234285Sdim} 270234285Sdim 271234285Sdim 272234285Sdimbool HexagonFrameLowering::restoreCalleeSavedRegisters( 273234285Sdim MachineBasicBlock &MBB, 274234285Sdim MachineBasicBlock::iterator MI, 275234285Sdim const std::vector<CalleeSavedInfo> &CSI, 276234285Sdim const TargetRegisterInfo *TRI) const { 277234285Sdim 278234285Sdim MachineFunction *MF = MBB.getParent(); 279234285Sdim const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); 280234285Sdim 281234285Sdim if (CSI.empty()) { 282234285Sdim return false; 283234285Sdim } 284234285Sdim 285234285Sdim // We can only schedule double loads if we spill contiguous callee-saved regs 286234285Sdim // For instance, we cannot scheduled double-word loads if we spill r24, 287234285Sdim // r26, and r27. 288234285Sdim // Hexagon_TODO: We can try to double-word align odd registers for -O2 and 289234285Sdim // above. 290234285Sdim bool ContiguousRegs = true; 291234285Sdim 292234285Sdim for (unsigned i = 0; i < CSI.size(); ++i) { 293234285Sdim unsigned Reg = CSI[i].getReg(); 294234285Sdim 295234285Sdim // 296234285Sdim // Check if we can use a double-word load. 297234285Sdim // 298234285Sdim const uint16_t* SuperReg = TRI->getSuperRegisters(Reg); 299234285Sdim const TargetRegisterClass* SuperRegClass = 0; 300234285Sdim 301234285Sdim // Assume that there is exactly one superreg. 302234285Sdim assert(SuperReg[0] && !SuperReg[1] && "Expected exactly one superreg"); 303234285Sdim bool CanUseDblLoad = false; 304234285Sdim if (ContiguousRegs && (i < CSI.size()-1)) { 305234285Sdim const uint16_t* SuperRegNext = TRI->getSuperRegisters(CSI[i+1].getReg()); 306234285Sdim assert(SuperRegNext[0] && !SuperRegNext[1] && 307234285Sdim "Expected exactly one superreg"); 308234285Sdim SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg[0]); 309234285Sdim CanUseDblLoad = (SuperRegNext[0] == SuperReg[0]); 310234285Sdim } 311234285Sdim 312234285Sdim 313234285Sdim if (CanUseDblLoad) { 314234285Sdim TII.loadRegFromStackSlot(MBB, MI, SuperReg[0], CSI[i+1].getFrameIdx(), 315234285Sdim SuperRegClass, TRI); 316234285Sdim MBB.addLiveIn(SuperReg[0]); 317234285Sdim ++i; 318234285Sdim } else { 319234285Sdim // Cannot use a double-word load. 320234285Sdim ContiguousRegs = false; 321234285Sdim const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 322234285Sdim TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), RC, TRI); 323234285Sdim MBB.addLiveIn(Reg); 324234285Sdim } 325234285Sdim } 326234285Sdim return true; 327234285Sdim} 328234285Sdim 329234285Sdimint HexagonFrameLowering::getFrameIndexOffset(const MachineFunction &MF, 330234285Sdim int FI) const { 331234285Sdim return MF.getFrameInfo()->getObjectOffset(FI); 332234285Sdim} 333