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 MachineBasicBlock::iterator MBBI = MBB.begin(); 80234285Sdim const HexagonRegisterInfo *QRI = 81234285Sdim static_cast<const HexagonRegisterInfo *>(MF.getTarget().getRegisterInfo()); 82234285Sdim DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 83234285Sdim determineFrameLayout(MF); 84234285Sdim 85234285Sdim // Get the number of bytes to allocate from the FrameInfo. 86234285Sdim int NumBytes = (int) MFI->getStackSize(); 87234285Sdim 88234285Sdim // LLVM expects allocframe not to be the first instruction in the 89234285Sdim // basic block. 90234285Sdim MachineBasicBlock::iterator InsertPt = MBB.begin(); 91234285Sdim 92234285Sdim // 93234285Sdim // ALLOCA adjust regs. Iterate over ADJDYNALLOC nodes and change the offset. 94234285Sdim // 95234285Sdim HexagonMachineFunctionInfo *FuncInfo = 96234285Sdim MF.getInfo<HexagonMachineFunctionInfo>(); 97234285Sdim const std::vector<MachineInstr*>& AdjustRegs = 98234285Sdim FuncInfo->getAllocaAdjustInsts(); 99234285Sdim for (std::vector<MachineInstr*>::const_iterator i = AdjustRegs.begin(), 100234285Sdim e = AdjustRegs.end(); 101234285Sdim i != e; ++i) { 102234285Sdim MachineInstr* MI = *i; 103234285Sdim assert((MI->getOpcode() == Hexagon::ADJDYNALLOC) && 104234285Sdim "Expected adjust alloca node"); 105234285Sdim 106234285Sdim MachineOperand& MO = MI->getOperand(2); 107234285Sdim assert(MO.isImm() && "Expected immediate"); 108234285Sdim MO.setImm(MFI->getMaxCallFrameSize()); 109234285Sdim } 110234285Sdim 111234285Sdim // 112234285Sdim // Only insert ALLOCFRAME if we need to. 113234285Sdim // 114234285Sdim if (hasFP(MF)) { 115234285Sdim // Check for overflow. 116234285Sdim // Hexagon_TODO: Ugh! hardcoding. Is there an API that can be used? 117234285Sdim const int ALLOCFRAME_MAX = 16384; 118234285Sdim const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); 119234285Sdim 120234285Sdim if (NumBytes >= ALLOCFRAME_MAX) { 121234285Sdim // Emit allocframe(#0). 122234285Sdim BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(0); 123234285Sdim 124234285Sdim // Subtract offset from frame pointer. 125234285Sdim BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::CONST32_Int_Real), 126234285Sdim HEXAGON_RESERVED_REG_1).addImm(NumBytes); 127234285Sdim BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::SUB_rr), 128234285Sdim QRI->getStackRegister()). 129234285Sdim addReg(QRI->getStackRegister()). 130234285Sdim addReg(HEXAGON_RESERVED_REG_1); 131234285Sdim } else { 132234285Sdim BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(NumBytes); 133234285Sdim } 134234285Sdim } 135234285Sdim} 136234285Sdim// Returns true if MBB has a machine instructions that indicates a tail call 137234285Sdim// in the block. 138234285Sdimbool HexagonFrameLowering::hasTailCall(MachineBasicBlock &MBB) const { 139234285Sdim MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 140234285Sdim unsigned RetOpcode = MBBI->getOpcode(); 141234285Sdim 142249423Sdim return RetOpcode == Hexagon::TCRETURNtg || RetOpcode == Hexagon::TCRETURNtext; 143249423Sdim} 144234285Sdim 145234285Sdimvoid HexagonFrameLowering::emitEpilogue(MachineFunction &MF, 146234285Sdim MachineBasicBlock &MBB) const { 147234285Sdim MachineBasicBlock::iterator MBBI = prior(MBB.end()); 148234285Sdim DebugLoc dl = MBBI->getDebugLoc(); 149234285Sdim // 150263508Sdim // Only insert deallocframe if we need to. Also at -O0. See comment 151263508Sdim // in emitPrologue above. 152234285Sdim // 153263508Sdim if (hasFP(MF) || MF.getTarget().getOptLevel() == CodeGenOpt::None) { 154234285Sdim MachineBasicBlock::iterator MBBI = prior(MBB.end()); 155234285Sdim MachineBasicBlock::iterator MBBI_end = MBB.end(); 156234285Sdim 157234285Sdim const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); 158263508Sdim // Handle EH_RETURN. 159263508Sdim if (MBBI->getOpcode() == Hexagon::EH_RETURN_JMPR) { 160263508Sdim assert(MBBI->getOperand(0).isReg() && "Offset should be in register!"); 161263508Sdim BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME)); 162263508Sdim BuildMI(MBB, MBBI, dl, TII.get(Hexagon::ADD_rr), 163263508Sdim Hexagon::R29).addReg(Hexagon::R29).addReg(Hexagon::R28); 164263508Sdim return; 165263508Sdim } 166234285Sdim // Replace 'jumpr r31' instruction with dealloc_return for V4 and higher 167234285Sdim // versions. 168251662Sdim if (STI.hasV4TOps() && MBBI->getOpcode() == Hexagon::JMPret 169234285Sdim && !DisableDeallocRet) { 170263508Sdim // Check for RESTORE_DEALLOC_RET_JMP_V4 call. Don't emit an extra DEALLOC 171263508Sdim // instruction if we encounter it. 172263508Sdim MachineBasicBlock::iterator BeforeJMPR = 173263508Sdim MBB.begin() == MBBI ? MBBI : prior(MBBI); 174263508Sdim if (BeforeJMPR != MBBI && 175263508Sdim BeforeJMPR->getOpcode() == Hexagon::RESTORE_DEALLOC_RET_JMP_V4) { 176263508Sdim // Remove the JMPR node. 177263508Sdim MBB.erase(MBBI); 178263508Sdim return; 179263508Sdim } 180263508Sdim 181263508Sdim // Add dealloc_return. 182263508Sdim MachineInstrBuilder MIB = 183263508Sdim BuildMI(MBB, MBBI_end, dl, TII.get(Hexagon::DEALLOC_RET_V4)); 184263508Sdim // Transfer the function live-out registers. 185263508Sdim MIB->copyImplicitOps(*MBB.getParent(), &*MBBI); 186263508Sdim // Remove the JUMPR node. 187234285Sdim MBB.erase(MBBI); 188263508Sdim } else { // Add deallocframe for V2 and V3, and V4 tail calls. 189263508Sdim // Check for RESTORE_DEALLOC_BEFORE_TAILCALL_V4. We don't need an extra 190263508Sdim // DEALLOCFRAME instruction after it. 191263508Sdim MachineBasicBlock::iterator Term = MBB.getFirstTerminator(); 192263508Sdim MachineBasicBlock::iterator I = 193263508Sdim Term == MBB.begin() ? MBB.end() : prior(Term); 194263508Sdim if (I != MBB.end() && 195263508Sdim I->getOpcode() == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4) 196263508Sdim return; 197263508Sdim 198263508Sdim BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME)); 199234285Sdim } 200234285Sdim } 201234285Sdim} 202234285Sdim 203234285Sdimbool HexagonFrameLowering::hasFP(const MachineFunction &MF) const { 204234285Sdim const MachineFrameInfo *MFI = MF.getFrameInfo(); 205234285Sdim const HexagonMachineFunctionInfo *FuncInfo = 206234285Sdim MF.getInfo<HexagonMachineFunctionInfo>(); 207234285Sdim return (MFI->hasCalls() || (MFI->getStackSize() > 0) || 208234285Sdim FuncInfo->hasClobberLR() ); 209234285Sdim} 210234285Sdim 211239462Sdimstatic inline 212239462Sdimunsigned uniqueSuperReg(unsigned Reg, const TargetRegisterInfo *TRI) { 213239462Sdim MCSuperRegIterator SRI(Reg, TRI); 214239462Sdim assert(SRI.isValid() && "Expected a superreg"); 215239462Sdim unsigned SuperReg = *SRI; 216239462Sdim ++SRI; 217239462Sdim assert(!SRI.isValid() && "Expected exactly one superreg"); 218239462Sdim return SuperReg; 219239462Sdim} 220239462Sdim 221234285Sdimbool 222234285SdimHexagonFrameLowering::spillCalleeSavedRegisters( 223234285Sdim MachineBasicBlock &MBB, 224234285Sdim MachineBasicBlock::iterator MI, 225234285Sdim const std::vector<CalleeSavedInfo> &CSI, 226234285Sdim const TargetRegisterInfo *TRI) const { 227234285Sdim MachineFunction *MF = MBB.getParent(); 228234285Sdim const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); 229234285Sdim 230234285Sdim if (CSI.empty()) { 231234285Sdim return false; 232234285Sdim } 233234285Sdim 234234285Sdim // We can only schedule double loads if we spill contiguous callee-saved regs 235234285Sdim // For instance, we cannot scheduled double-word loads if we spill r24, 236234285Sdim // r26, and r27. 237234285Sdim // Hexagon_TODO: We can try to double-word align odd registers for -O2 and 238234285Sdim // above. 239234285Sdim bool ContiguousRegs = true; 240234285Sdim 241234285Sdim for (unsigned i = 0; i < CSI.size(); ++i) { 242234285Sdim unsigned Reg = CSI[i].getReg(); 243234285Sdim 244234285Sdim // 245234285Sdim // Check if we can use a double-word store. 246234285Sdim // 247239462Sdim unsigned SuperReg = uniqueSuperReg(Reg, TRI); 248234285Sdim bool CanUseDblStore = false; 249234285Sdim const TargetRegisterClass* SuperRegClass = 0; 250234285Sdim 251234285Sdim if (ContiguousRegs && (i < CSI.size()-1)) { 252239462Sdim unsigned SuperRegNext = uniqueSuperReg(CSI[i+1].getReg(), TRI); 253239462Sdim SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg); 254239462Sdim CanUseDblStore = (SuperRegNext == SuperReg); 255234285Sdim } 256234285Sdim 257234285Sdim 258234285Sdim if (CanUseDblStore) { 259239462Sdim TII.storeRegToStackSlot(MBB, MI, SuperReg, true, 260234285Sdim CSI[i+1].getFrameIdx(), SuperRegClass, TRI); 261239462Sdim MBB.addLiveIn(SuperReg); 262234285Sdim ++i; 263234285Sdim } else { 264234285Sdim // Cannot use a double-word store. 265234285Sdim ContiguousRegs = false; 266234285Sdim const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 267234285Sdim TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(), RC, 268234285Sdim TRI); 269234285Sdim MBB.addLiveIn(Reg); 270234285Sdim } 271234285Sdim } 272234285Sdim return true; 273234285Sdim} 274234285Sdim 275234285Sdim 276234285Sdimbool HexagonFrameLowering::restoreCalleeSavedRegisters( 277234285Sdim MachineBasicBlock &MBB, 278234285Sdim MachineBasicBlock::iterator MI, 279234285Sdim const std::vector<CalleeSavedInfo> &CSI, 280234285Sdim const TargetRegisterInfo *TRI) const { 281234285Sdim 282234285Sdim MachineFunction *MF = MBB.getParent(); 283234285Sdim const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); 284234285Sdim 285234285Sdim if (CSI.empty()) { 286234285Sdim return false; 287234285Sdim } 288234285Sdim 289234285Sdim // We can only schedule double loads if we spill contiguous callee-saved regs 290234285Sdim // For instance, we cannot scheduled double-word loads if we spill r24, 291234285Sdim // r26, and r27. 292234285Sdim // Hexagon_TODO: We can try to double-word align odd registers for -O2 and 293234285Sdim // above. 294234285Sdim bool ContiguousRegs = true; 295234285Sdim 296234285Sdim for (unsigned i = 0; i < CSI.size(); ++i) { 297234285Sdim unsigned Reg = CSI[i].getReg(); 298234285Sdim 299234285Sdim // 300234285Sdim // Check if we can use a double-word load. 301234285Sdim // 302239462Sdim unsigned SuperReg = uniqueSuperReg(Reg, TRI); 303234285Sdim const TargetRegisterClass* SuperRegClass = 0; 304234285Sdim bool CanUseDblLoad = false; 305234285Sdim if (ContiguousRegs && (i < CSI.size()-1)) { 306239462Sdim unsigned SuperRegNext = uniqueSuperReg(CSI[i+1].getReg(), TRI); 307239462Sdim SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg); 308239462Sdim CanUseDblLoad = (SuperRegNext == SuperReg); 309234285Sdim } 310234285Sdim 311234285Sdim 312234285Sdim if (CanUseDblLoad) { 313239462Sdim TII.loadRegFromStackSlot(MBB, MI, SuperReg, CSI[i+1].getFrameIdx(), 314234285Sdim SuperRegClass, TRI); 315239462Sdim MBB.addLiveIn(SuperReg); 316234285Sdim ++i; 317234285Sdim } else { 318234285Sdim // Cannot use a double-word load. 319234285Sdim ContiguousRegs = false; 320234285Sdim const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 321234285Sdim TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), RC, TRI); 322234285Sdim MBB.addLiveIn(Reg); 323234285Sdim } 324234285Sdim } 325234285Sdim return true; 326234285Sdim} 327234285Sdim 328249423Sdimvoid HexagonFrameLowering:: 329249423SdimeliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 330249423Sdim MachineBasicBlock::iterator I) const { 331249423Sdim MachineInstr &MI = *I; 332249423Sdim 333249423Sdim if (MI.getOpcode() == Hexagon::ADJCALLSTACKDOWN) { 334249423Sdim // Hexagon_TODO: add code 335249423Sdim } else if (MI.getOpcode() == Hexagon::ADJCALLSTACKUP) { 336249423Sdim // Hexagon_TODO: add code 337249423Sdim } else { 338249423Sdim llvm_unreachable("Cannot handle this call frame pseudo instruction"); 339249423Sdim } 340249423Sdim MBB.erase(I); 341249423Sdim} 342249423Sdim 343234285Sdimint HexagonFrameLowering::getFrameIndexOffset(const MachineFunction &MF, 344234285Sdim int FI) const { 345234285Sdim return MF.getFrameInfo()->getObjectOffset(FI); 346234285Sdim} 347