HexagonFrameLowering.cpp revision 251662
1139825Simp//===-- HexagonFrameLowering.cpp - Define frame lowering ------------------===// 2109480Sgrehan// 3109480Sgrehan// The LLVM Compiler Infrastructure 4109480Sgrehan// 5109480Sgrehan// This file is distributed under the University of Illinois Open Source 6109480Sgrehan// License. See LICENSE.TXT for details. 7109480Sgrehan// 8109480Sgrehan// 9109480Sgrehan//===----------------------------------------------------------------------===// 10109480Sgrehan 11109480Sgrehan#include "HexagonFrameLowering.h" 12109480Sgrehan#include "Hexagon.h" 13109480Sgrehan#include "HexagonInstrInfo.h" 14109480Sgrehan#include "HexagonMachineFunctionInfo.h" 15109480Sgrehan#include "HexagonRegisterInfo.h" 16109480Sgrehan#include "HexagonSubtarget.h" 17109480Sgrehan#include "HexagonTargetMachine.h" 18109480Sgrehan#include "llvm/ADT/BitVector.h" 19109480Sgrehan#include "llvm/ADT/STLExtras.h" 20109480Sgrehan#include "llvm/CodeGen/AsmPrinter.h" 21109480Sgrehan#include "llvm/CodeGen/MachineFrameInfo.h" 22109480Sgrehan#include "llvm/CodeGen/MachineFunction.h" 23109480Sgrehan#include "llvm/CodeGen/MachineFunctionPass.h" 24109480Sgrehan#include "llvm/CodeGen/MachineInstrBuilder.h" 25109480Sgrehan#include "llvm/CodeGen/MachineModuleInfo.h" 26109480Sgrehan#include "llvm/CodeGen/MachineRegisterInfo.h" 27109480Sgrehan#include "llvm/CodeGen/RegisterScavenging.h" 28109480Sgrehan#include "llvm/IR/Function.h" 29109480Sgrehan#include "llvm/IR/Type.h" 30109480Sgrehan#include "llvm/MC/MCAsmInfo.h" 31109480Sgrehan#include "llvm/MC/MachineLocation.h" 32109480Sgrehan#include "llvm/Support/CommandLine.h" 33109480Sgrehan#include "llvm/Target/TargetInstrInfo.h" 34109480Sgrehan#include "llvm/Target/TargetMachine.h" 35109480Sgrehan#include "llvm/Target/TargetOptions.h" 36109480Sgrehan 37109480Sgrehanusing namespace llvm; 38109480Sgrehan 39109480Sgrehanstatic cl::opt<bool> DisableDeallocRet( 40109480Sgrehan "disable-hexagon-dealloc-ret", 41109480Sgrehan cl::Hidden, 42109480Sgrehan cl::desc("Disable Dealloc Return for Hexagon target")); 43109480Sgrehan 44109480Sgrehan/// determineFrameLayout - Determine the size of the frame and maximum call 45109480Sgrehan/// frame size. 46109480Sgrehanvoid HexagonFrameLowering::determineFrameLayout(MachineFunction &MF) const { 47109480Sgrehan MachineFrameInfo *MFI = MF.getFrameInfo(); 48109480Sgrehan 49109480Sgrehan // Get the number of bytes to allocate from the FrameInfo. 50109480Sgrehan unsigned FrameSize = MFI->getStackSize(); 51109480Sgrehan 52109480Sgrehan // Get the alignments provided by the target. 53109480Sgrehan unsigned TargetAlign = MF.getTarget().getFrameLowering()->getStackAlignment(); 54109480Sgrehan // Get the maximum call frame size of all the calls. 55109480Sgrehan unsigned maxCallFrameSize = MFI->getMaxCallFrameSize(); 56109480Sgrehan 57109480Sgrehan // If we have dynamic alloca then maxCallFrameSize needs to be aligned so 58109480Sgrehan // that allocations will be aligned. 59109480Sgrehan if (MFI->hasVarSizedObjects()) 60109480Sgrehan maxCallFrameSize = RoundUpToAlignment(maxCallFrameSize, TargetAlign); 61109480Sgrehan 62109480Sgrehan // Update maximum call frame size. 63109480Sgrehan MFI->setMaxCallFrameSize(maxCallFrameSize); 64109480Sgrehan 65109480Sgrehan // Include call frame size in total. 66109480Sgrehan FrameSize += maxCallFrameSize; 67109480Sgrehan 68109480Sgrehan // Make sure the frame is aligned. 69109480Sgrehan FrameSize = RoundUpToAlignment(FrameSize, TargetAlign); 70109480Sgrehan 71109480Sgrehan // Update frame info. 72109480Sgrehan MFI->setStackSize(FrameSize); 73109480Sgrehan} 74109480Sgrehan 75109480Sgrehan 76109480Sgrehanvoid HexagonFrameLowering::emitPrologue(MachineFunction &MF) const { 77109480Sgrehan MachineBasicBlock &MBB = MF.front(); 78109480Sgrehan MachineFrameInfo *MFI = MF.getFrameInfo(); 79109480Sgrehan MachineModuleInfo &MMI = MF.getMMI(); 80109480Sgrehan MachineBasicBlock::iterator MBBI = MBB.begin(); 81109480Sgrehan const HexagonRegisterInfo *QRI = 82109480Sgrehan static_cast<const HexagonRegisterInfo *>(MF.getTarget().getRegisterInfo()); 83109480Sgrehan DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 84109480Sgrehan determineFrameLayout(MF); 85109480Sgrehan 86109480Sgrehan // Check if frame moves are needed for EH. 87109480Sgrehan bool needsFrameMoves = MMI.hasDebugInfo() || 88109480Sgrehan !MF.getFunction()->needsUnwindTableEntry(); 89109480Sgrehan 90109480Sgrehan // Get the number of bytes to allocate from the FrameInfo. 91109480Sgrehan int NumBytes = (int) MFI->getStackSize(); 92109480Sgrehan 93109480Sgrehan // LLVM expects allocframe not to be the first instruction in the 94109480Sgrehan // basic block. 95109480Sgrehan MachineBasicBlock::iterator InsertPt = MBB.begin(); 96109480Sgrehan 97109480Sgrehan // 98109480Sgrehan // ALLOCA adjust regs. Iterate over ADJDYNALLOC nodes and change the offset. 99109480Sgrehan // 100109480Sgrehan HexagonMachineFunctionInfo *FuncInfo = 101109480Sgrehan MF.getInfo<HexagonMachineFunctionInfo>(); 102109480Sgrehan const std::vector<MachineInstr*>& AdjustRegs = 103109480Sgrehan FuncInfo->getAllocaAdjustInsts(); 104109480Sgrehan for (std::vector<MachineInstr*>::const_iterator i = AdjustRegs.begin(), 105109480Sgrehan e = AdjustRegs.end(); 106109480Sgrehan i != e; ++i) { 107109480Sgrehan MachineInstr* MI = *i; 108109480Sgrehan assert((MI->getOpcode() == Hexagon::ADJDYNALLOC) && 109109480Sgrehan "Expected adjust alloca node"); 110109480Sgrehan 111109480Sgrehan MachineOperand& MO = MI->getOperand(2); 112109480Sgrehan assert(MO.isImm() && "Expected immediate"); 113109480Sgrehan MO.setImm(MFI->getMaxCallFrameSize()); 114109480Sgrehan } 115109480Sgrehan 116109480Sgrehan std::vector<MachineMove> &Moves = MMI.getFrameMoves(); 117109480Sgrehan 118109480Sgrehan if (needsFrameMoves) { 119109480Sgrehan // Advance CFA. DW_CFA_def_cfa 120109480Sgrehan unsigned FPReg = QRI->getFrameRegister(); 121109480Sgrehan unsigned RAReg = QRI->getRARegister(); 122109480Sgrehan 123109480Sgrehan MachineLocation Dst(MachineLocation::VirtualFP); 124109480Sgrehan MachineLocation Src(FPReg, -8); 125109480Sgrehan Moves.push_back(MachineMove(0, Dst, Src)); 126109480Sgrehan 127109480Sgrehan // R31 = (R31 - #4) 128109480Sgrehan MachineLocation LRDst(RAReg, -4); 129109480Sgrehan MachineLocation LRSrc(RAReg); 130109480Sgrehan Moves.push_back(MachineMove(0, LRDst, LRSrc)); 131109480Sgrehan 132109480Sgrehan // R30 = (R30 - #8) 133109480Sgrehan MachineLocation SPDst(FPReg, -8); 134109480Sgrehan MachineLocation SPSrc(FPReg); 135109480Sgrehan Moves.push_back(MachineMove(0, SPDst, SPSrc)); 136109480Sgrehan } 137109480Sgrehan 138109480Sgrehan // 139109480Sgrehan // Only insert ALLOCFRAME if we need to. 140109480Sgrehan // 141109480Sgrehan if (hasFP(MF)) { 142109480Sgrehan // Check for overflow. 143 // Hexagon_TODO: Ugh! hardcoding. Is there an API that can be used? 144 const int ALLOCFRAME_MAX = 16384; 145 const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); 146 147 if (NumBytes >= ALLOCFRAME_MAX) { 148 // Emit allocframe(#0). 149 BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(0); 150 151 // Subtract offset from frame pointer. 152 BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::CONST32_Int_Real), 153 HEXAGON_RESERVED_REG_1).addImm(NumBytes); 154 BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::SUB_rr), 155 QRI->getStackRegister()). 156 addReg(QRI->getStackRegister()). 157 addReg(HEXAGON_RESERVED_REG_1); 158 } else { 159 BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(NumBytes); 160 } 161 } 162} 163// Returns true if MBB has a machine instructions that indicates a tail call 164// in the block. 165bool HexagonFrameLowering::hasTailCall(MachineBasicBlock &MBB) const { 166 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 167 unsigned RetOpcode = MBBI->getOpcode(); 168 169 return RetOpcode == Hexagon::TCRETURNtg || RetOpcode == Hexagon::TCRETURNtext; 170} 171 172void HexagonFrameLowering::emitEpilogue(MachineFunction &MF, 173 MachineBasicBlock &MBB) const { 174 MachineBasicBlock::iterator MBBI = prior(MBB.end()); 175 DebugLoc dl = MBBI->getDebugLoc(); 176 // 177 // Only insert deallocframe if we need to. 178 // 179 if (hasFP(MF)) { 180 MachineBasicBlock::iterator MBBI = prior(MBB.end()); 181 MachineBasicBlock::iterator MBBI_end = MBB.end(); 182 // 183 // For Hexagon, we don't need the frame size. 184 // 185 MachineFrameInfo *MFI = MF.getFrameInfo(); 186 int NumBytes = (int) MFI->getStackSize(); 187 188 const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); 189 190 // Replace 'jumpr r31' instruction with dealloc_return for V4 and higher 191 // versions. 192 if (STI.hasV4TOps() && MBBI->getOpcode() == Hexagon::JMPret 193 && !DisableDeallocRet) { 194 // Remove jumpr node. 195 MBB.erase(MBBI); 196 // Add dealloc_return. 197 BuildMI(MBB, MBBI_end, dl, TII.get(Hexagon::DEALLOC_RET_V4)) 198 .addImm(NumBytes); 199 } else { // Add deallocframe for V2 and V3. 200 BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME)).addImm(NumBytes); 201 } 202 } 203} 204 205bool HexagonFrameLowering::hasFP(const MachineFunction &MF) const { 206 const MachineFrameInfo *MFI = MF.getFrameInfo(); 207 const HexagonMachineFunctionInfo *FuncInfo = 208 MF.getInfo<HexagonMachineFunctionInfo>(); 209 return (MFI->hasCalls() || (MFI->getStackSize() > 0) || 210 FuncInfo->hasClobberLR() ); 211} 212 213static inline 214unsigned uniqueSuperReg(unsigned Reg, const TargetRegisterInfo *TRI) { 215 MCSuperRegIterator SRI(Reg, TRI); 216 assert(SRI.isValid() && "Expected a superreg"); 217 unsigned SuperReg = *SRI; 218 ++SRI; 219 assert(!SRI.isValid() && "Expected exactly one superreg"); 220 return SuperReg; 221} 222 223bool 224HexagonFrameLowering::spillCalleeSavedRegisters( 225 MachineBasicBlock &MBB, 226 MachineBasicBlock::iterator MI, 227 const std::vector<CalleeSavedInfo> &CSI, 228 const TargetRegisterInfo *TRI) const { 229 MachineFunction *MF = MBB.getParent(); 230 const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); 231 232 if (CSI.empty()) { 233 return false; 234 } 235 236 // We can only schedule double loads if we spill contiguous callee-saved regs 237 // For instance, we cannot scheduled double-word loads if we spill r24, 238 // r26, and r27. 239 // Hexagon_TODO: We can try to double-word align odd registers for -O2 and 240 // above. 241 bool ContiguousRegs = true; 242 243 for (unsigned i = 0; i < CSI.size(); ++i) { 244 unsigned Reg = CSI[i].getReg(); 245 246 // 247 // Check if we can use a double-word store. 248 // 249 unsigned SuperReg = uniqueSuperReg(Reg, TRI); 250 bool CanUseDblStore = false; 251 const TargetRegisterClass* SuperRegClass = 0; 252 253 if (ContiguousRegs && (i < CSI.size()-1)) { 254 unsigned SuperRegNext = uniqueSuperReg(CSI[i+1].getReg(), TRI); 255 SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg); 256 CanUseDblStore = (SuperRegNext == SuperReg); 257 } 258 259 260 if (CanUseDblStore) { 261 TII.storeRegToStackSlot(MBB, MI, SuperReg, true, 262 CSI[i+1].getFrameIdx(), SuperRegClass, TRI); 263 MBB.addLiveIn(SuperReg); 264 ++i; 265 } else { 266 // Cannot use a double-word store. 267 ContiguousRegs = false; 268 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 269 TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(), RC, 270 TRI); 271 MBB.addLiveIn(Reg); 272 } 273 } 274 return true; 275} 276 277 278bool HexagonFrameLowering::restoreCalleeSavedRegisters( 279 MachineBasicBlock &MBB, 280 MachineBasicBlock::iterator MI, 281 const std::vector<CalleeSavedInfo> &CSI, 282 const TargetRegisterInfo *TRI) const { 283 284 MachineFunction *MF = MBB.getParent(); 285 const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); 286 287 if (CSI.empty()) { 288 return false; 289 } 290 291 // We can only schedule double loads if we spill contiguous callee-saved regs 292 // For instance, we cannot scheduled double-word loads if we spill r24, 293 // r26, and r27. 294 // Hexagon_TODO: We can try to double-word align odd registers for -O2 and 295 // above. 296 bool ContiguousRegs = true; 297 298 for (unsigned i = 0; i < CSI.size(); ++i) { 299 unsigned Reg = CSI[i].getReg(); 300 301 // 302 // Check if we can use a double-word load. 303 // 304 unsigned SuperReg = uniqueSuperReg(Reg, TRI); 305 const TargetRegisterClass* SuperRegClass = 0; 306 bool CanUseDblLoad = false; 307 if (ContiguousRegs && (i < CSI.size()-1)) { 308 unsigned SuperRegNext = uniqueSuperReg(CSI[i+1].getReg(), TRI); 309 SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg); 310 CanUseDblLoad = (SuperRegNext == SuperReg); 311 } 312 313 314 if (CanUseDblLoad) { 315 TII.loadRegFromStackSlot(MBB, MI, SuperReg, CSI[i+1].getFrameIdx(), 316 SuperRegClass, TRI); 317 MBB.addLiveIn(SuperReg); 318 ++i; 319 } else { 320 // Cannot use a double-word load. 321 ContiguousRegs = false; 322 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 323 TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), RC, TRI); 324 MBB.addLiveIn(Reg); 325 } 326 } 327 return true; 328} 329 330void HexagonFrameLowering:: 331eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 332 MachineBasicBlock::iterator I) const { 333 MachineInstr &MI = *I; 334 335 if (MI.getOpcode() == Hexagon::ADJCALLSTACKDOWN) { 336 // Hexagon_TODO: add code 337 } else if (MI.getOpcode() == Hexagon::ADJCALLSTACKUP) { 338 // Hexagon_TODO: add code 339 } else { 340 llvm_unreachable("Cannot handle this call frame pseudo instruction"); 341 } 342 MBB.erase(I); 343} 344 345int HexagonFrameLowering::getFrameIndexOffset(const MachineFunction &MF, 346 int FI) const { 347 return MF.getFrameInfo()->getObjectOffset(FI); 348} 349