HexagonFrameLowering.cpp revision 249423
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" 14249423Sdim#include "HexagonMachineFunctionInfo.h" 15234285Sdim#include "HexagonRegisterInfo.h" 16234285Sdim#include "HexagonSubtarget.h" 17234285Sdim#include "HexagonTargetMachine.h" 18234285Sdim#include "llvm/ADT/BitVector.h" 19234285Sdim#include "llvm/ADT/STLExtras.h" 20234285Sdim#include "llvm/CodeGen/AsmPrinter.h" 21249423Sdim#include "llvm/CodeGen/MachineFrameInfo.h" 22234285Sdim#include "llvm/CodeGen/MachineFunction.h" 23234285Sdim#include "llvm/CodeGen/MachineFunctionPass.h" 24249423Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 25234285Sdim#include "llvm/CodeGen/MachineModuleInfo.h" 26234285Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 27234285Sdim#include "llvm/CodeGen/RegisterScavenging.h" 28249423Sdim#include "llvm/IR/Function.h" 29249423Sdim#include "llvm/IR/Type.h" 30249423Sdim#include "llvm/MC/MCAsmInfo.h" 31234285Sdim#include "llvm/MC/MachineLocation.h" 32249423Sdim#include "llvm/Support/CommandLine.h" 33234285Sdim#include "llvm/Target/TargetInstrInfo.h" 34234285Sdim#include "llvm/Target/TargetMachine.h" 35234285Sdim#include "llvm/Target/TargetOptions.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 169249423Sdim return RetOpcode == Hexagon::TCRETURNtg || RetOpcode == Hexagon::TCRETURNtext; 170249423Sdim} 171234285Sdim 172234285Sdimvoid HexagonFrameLowering::emitEpilogue(MachineFunction &MF, 173234285Sdim MachineBasicBlock &MBB) const { 174234285Sdim MachineBasicBlock::iterator MBBI = prior(MBB.end()); 175234285Sdim DebugLoc dl = MBBI->getDebugLoc(); 176234285Sdim // 177234285Sdim // Only insert deallocframe if we need to. 178234285Sdim // 179234285Sdim if (hasFP(MF)) { 180234285Sdim MachineBasicBlock::iterator MBBI = prior(MBB.end()); 181234285Sdim MachineBasicBlock::iterator MBBI_end = MBB.end(); 182234285Sdim // 183234285Sdim // For Hexagon, we don't need the frame size. 184234285Sdim // 185234285Sdim MachineFrameInfo *MFI = MF.getFrameInfo(); 186234285Sdim int NumBytes = (int) MFI->getStackSize(); 187234285Sdim 188234285Sdim const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); 189234285Sdim 190234285Sdim // Replace 'jumpr r31' instruction with dealloc_return for V4 and higher 191234285Sdim // versions. 192234285Sdim if (STI.hasV4TOps() && MBBI->getOpcode() == Hexagon::JMPR 193234285Sdim && !DisableDeallocRet) { 194234285Sdim // Remove jumpr node. 195234285Sdim MBB.erase(MBBI); 196234285Sdim // Add dealloc_return. 197234285Sdim BuildMI(MBB, MBBI_end, dl, TII.get(Hexagon::DEALLOC_RET_V4)) 198234285Sdim .addImm(NumBytes); 199234285Sdim } else { // Add deallocframe for V2 and V3. 200234285Sdim BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME)).addImm(NumBytes); 201234285Sdim } 202234285Sdim } 203234285Sdim} 204234285Sdim 205234285Sdimbool HexagonFrameLowering::hasFP(const MachineFunction &MF) const { 206234285Sdim const MachineFrameInfo *MFI = MF.getFrameInfo(); 207234285Sdim const HexagonMachineFunctionInfo *FuncInfo = 208234285Sdim MF.getInfo<HexagonMachineFunctionInfo>(); 209234285Sdim return (MFI->hasCalls() || (MFI->getStackSize() > 0) || 210234285Sdim FuncInfo->hasClobberLR() ); 211234285Sdim} 212234285Sdim 213239462Sdimstatic inline 214239462Sdimunsigned uniqueSuperReg(unsigned Reg, const TargetRegisterInfo *TRI) { 215239462Sdim MCSuperRegIterator SRI(Reg, TRI); 216239462Sdim assert(SRI.isValid() && "Expected a superreg"); 217239462Sdim unsigned SuperReg = *SRI; 218239462Sdim ++SRI; 219239462Sdim assert(!SRI.isValid() && "Expected exactly one superreg"); 220239462Sdim return SuperReg; 221239462Sdim} 222239462Sdim 223234285Sdimbool 224234285SdimHexagonFrameLowering::spillCalleeSavedRegisters( 225234285Sdim MachineBasicBlock &MBB, 226234285Sdim MachineBasicBlock::iterator MI, 227234285Sdim const std::vector<CalleeSavedInfo> &CSI, 228234285Sdim const TargetRegisterInfo *TRI) const { 229234285Sdim MachineFunction *MF = MBB.getParent(); 230234285Sdim const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); 231234285Sdim 232234285Sdim if (CSI.empty()) { 233234285Sdim return false; 234234285Sdim } 235234285Sdim 236234285Sdim // We can only schedule double loads if we spill contiguous callee-saved regs 237234285Sdim // For instance, we cannot scheduled double-word loads if we spill r24, 238234285Sdim // r26, and r27. 239234285Sdim // Hexagon_TODO: We can try to double-word align odd registers for -O2 and 240234285Sdim // above. 241234285Sdim bool ContiguousRegs = true; 242234285Sdim 243234285Sdim for (unsigned i = 0; i < CSI.size(); ++i) { 244234285Sdim unsigned Reg = CSI[i].getReg(); 245234285Sdim 246234285Sdim // 247234285Sdim // Check if we can use a double-word store. 248234285Sdim // 249239462Sdim unsigned SuperReg = uniqueSuperReg(Reg, TRI); 250234285Sdim bool CanUseDblStore = false; 251234285Sdim const TargetRegisterClass* SuperRegClass = 0; 252234285Sdim 253234285Sdim if (ContiguousRegs && (i < CSI.size()-1)) { 254239462Sdim unsigned SuperRegNext = uniqueSuperReg(CSI[i+1].getReg(), TRI); 255239462Sdim SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg); 256239462Sdim CanUseDblStore = (SuperRegNext == SuperReg); 257234285Sdim } 258234285Sdim 259234285Sdim 260234285Sdim if (CanUseDblStore) { 261239462Sdim TII.storeRegToStackSlot(MBB, MI, SuperReg, true, 262234285Sdim CSI[i+1].getFrameIdx(), SuperRegClass, TRI); 263239462Sdim MBB.addLiveIn(SuperReg); 264234285Sdim ++i; 265234285Sdim } else { 266234285Sdim // Cannot use a double-word store. 267234285Sdim ContiguousRegs = false; 268234285Sdim const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 269234285Sdim TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(), RC, 270234285Sdim TRI); 271234285Sdim MBB.addLiveIn(Reg); 272234285Sdim } 273234285Sdim } 274234285Sdim return true; 275234285Sdim} 276234285Sdim 277234285Sdim 278234285Sdimbool HexagonFrameLowering::restoreCalleeSavedRegisters( 279234285Sdim MachineBasicBlock &MBB, 280234285Sdim MachineBasicBlock::iterator MI, 281234285Sdim const std::vector<CalleeSavedInfo> &CSI, 282234285Sdim const TargetRegisterInfo *TRI) const { 283234285Sdim 284234285Sdim MachineFunction *MF = MBB.getParent(); 285234285Sdim const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); 286234285Sdim 287234285Sdim if (CSI.empty()) { 288234285Sdim return false; 289234285Sdim } 290234285Sdim 291234285Sdim // We can only schedule double loads if we spill contiguous callee-saved regs 292234285Sdim // For instance, we cannot scheduled double-word loads if we spill r24, 293234285Sdim // r26, and r27. 294234285Sdim // Hexagon_TODO: We can try to double-word align odd registers for -O2 and 295234285Sdim // above. 296234285Sdim bool ContiguousRegs = true; 297234285Sdim 298234285Sdim for (unsigned i = 0; i < CSI.size(); ++i) { 299234285Sdim unsigned Reg = CSI[i].getReg(); 300234285Sdim 301234285Sdim // 302234285Sdim // Check if we can use a double-word load. 303234285Sdim // 304239462Sdim unsigned SuperReg = uniqueSuperReg(Reg, TRI); 305234285Sdim const TargetRegisterClass* SuperRegClass = 0; 306234285Sdim bool CanUseDblLoad = false; 307234285Sdim if (ContiguousRegs && (i < CSI.size()-1)) { 308239462Sdim unsigned SuperRegNext = uniqueSuperReg(CSI[i+1].getReg(), TRI); 309239462Sdim SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg); 310239462Sdim CanUseDblLoad = (SuperRegNext == SuperReg); 311234285Sdim } 312234285Sdim 313234285Sdim 314234285Sdim if (CanUseDblLoad) { 315239462Sdim TII.loadRegFromStackSlot(MBB, MI, SuperReg, CSI[i+1].getFrameIdx(), 316234285Sdim SuperRegClass, TRI); 317239462Sdim MBB.addLiveIn(SuperReg); 318234285Sdim ++i; 319234285Sdim } else { 320234285Sdim // Cannot use a double-word load. 321234285Sdim ContiguousRegs = false; 322234285Sdim const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 323234285Sdim TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), RC, TRI); 324234285Sdim MBB.addLiveIn(Reg); 325234285Sdim } 326234285Sdim } 327234285Sdim return true; 328234285Sdim} 329234285Sdim 330249423Sdimvoid HexagonFrameLowering:: 331249423SdimeliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 332249423Sdim MachineBasicBlock::iterator I) const { 333249423Sdim MachineInstr &MI = *I; 334249423Sdim 335249423Sdim if (MI.getOpcode() == Hexagon::ADJCALLSTACKDOWN) { 336249423Sdim // Hexagon_TODO: add code 337249423Sdim } else if (MI.getOpcode() == Hexagon::ADJCALLSTACKUP) { 338249423Sdim // Hexagon_TODO: add code 339249423Sdim } else { 340249423Sdim llvm_unreachable("Cannot handle this call frame pseudo instruction"); 341249423Sdim } 342249423Sdim MBB.erase(I); 343249423Sdim} 344249423Sdim 345234285Sdimint HexagonFrameLowering::getFrameIndexOffset(const MachineFunction &MF, 346234285Sdim int FI) const { 347234285Sdim return MF.getFrameInfo()->getObjectOffset(FI); 348234285Sdim} 349