HexagonFrameLowering.cpp revision d04a8d4b33ff316ca4cf961e06c9e312eff8e64f
1//===-- HexagonFrameLowering.cpp - Define frame lowering ------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8// 9//===----------------------------------------------------------------------===// 10 11#include "HexagonFrameLowering.h" 12#include "Hexagon.h" 13#include "HexagonInstrInfo.h" 14#include "HexagonMachineFunctionInfo.h" 15#include "HexagonRegisterInfo.h" 16#include "HexagonSubtarget.h" 17#include "HexagonTargetMachine.h" 18#include "llvm/ADT/BitVector.h" 19#include "llvm/ADT/STLExtras.h" 20#include "llvm/CodeGen/AsmPrinter.h" 21#include "llvm/CodeGen/MachineFrameInfo.h" 22#include "llvm/CodeGen/MachineFunction.h" 23#include "llvm/CodeGen/MachineFunctionPass.h" 24#include "llvm/CodeGen/MachineInstrBuilder.h" 25#include "llvm/CodeGen/MachineModuleInfo.h" 26#include "llvm/CodeGen/MachineRegisterInfo.h" 27#include "llvm/CodeGen/RegisterScavenging.h" 28#include "llvm/Function.h" 29#include "llvm/MC/MCAsmInfo.h" 30#include "llvm/MC/MachineLocation.h" 31#include "llvm/Support/CommandLine.h" 32#include "llvm/Target/TargetInstrInfo.h" 33#include "llvm/Target/TargetMachine.h" 34#include "llvm/Target/TargetOptions.h" 35#include "llvm/Type.h" 36 37using namespace llvm; 38 39static cl::opt<bool> DisableDeallocRet( 40 "disable-hexagon-dealloc-ret", 41 cl::Hidden, 42 cl::desc("Disable Dealloc Return for Hexagon target")); 43 44/// determineFrameLayout - Determine the size of the frame and maximum call 45/// frame size. 46void HexagonFrameLowering::determineFrameLayout(MachineFunction &MF) const { 47 MachineFrameInfo *MFI = MF.getFrameInfo(); 48 49 // Get the number of bytes to allocate from the FrameInfo. 50 unsigned FrameSize = MFI->getStackSize(); 51 52 // Get the alignments provided by the target. 53 unsigned TargetAlign = MF.getTarget().getFrameLowering()->getStackAlignment(); 54 // Get the maximum call frame size of all the calls. 55 unsigned maxCallFrameSize = MFI->getMaxCallFrameSize(); 56 57 // If we have dynamic alloca then maxCallFrameSize needs to be aligned so 58 // that allocations will be aligned. 59 if (MFI->hasVarSizedObjects()) 60 maxCallFrameSize = RoundUpToAlignment(maxCallFrameSize, TargetAlign); 61 62 // Update maximum call frame size. 63 MFI->setMaxCallFrameSize(maxCallFrameSize); 64 65 // Include call frame size in total. 66 FrameSize += maxCallFrameSize; 67 68 // Make sure the frame is aligned. 69 FrameSize = RoundUpToAlignment(FrameSize, TargetAlign); 70 71 // Update frame info. 72 MFI->setStackSize(FrameSize); 73} 74 75 76void HexagonFrameLowering::emitPrologue(MachineFunction &MF) const { 77 MachineBasicBlock &MBB = MF.front(); 78 MachineFrameInfo *MFI = MF.getFrameInfo(); 79 MachineModuleInfo &MMI = MF.getMMI(); 80 MachineBasicBlock::iterator MBBI = MBB.begin(); 81 const HexagonRegisterInfo *QRI = 82 static_cast<const HexagonRegisterInfo *>(MF.getTarget().getRegisterInfo()); 83 DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 84 determineFrameLayout(MF); 85 86 // Check if frame moves are needed for EH. 87 bool needsFrameMoves = MMI.hasDebugInfo() || 88 !MF.getFunction()->needsUnwindTableEntry(); 89 90 // Get the number of bytes to allocate from the FrameInfo. 91 int NumBytes = (int) MFI->getStackSize(); 92 93 // LLVM expects allocframe not to be the first instruction in the 94 // basic block. 95 MachineBasicBlock::iterator InsertPt = MBB.begin(); 96 97 // 98 // ALLOCA adjust regs. Iterate over ADJDYNALLOC nodes and change the offset. 99 // 100 HexagonMachineFunctionInfo *FuncInfo = 101 MF.getInfo<HexagonMachineFunctionInfo>(); 102 const std::vector<MachineInstr*>& AdjustRegs = 103 FuncInfo->getAllocaAdjustInsts(); 104 for (std::vector<MachineInstr*>::const_iterator i = AdjustRegs.begin(), 105 e = AdjustRegs.end(); 106 i != e; ++i) { 107 MachineInstr* MI = *i; 108 assert((MI->getOpcode() == Hexagon::ADJDYNALLOC) && 109 "Expected adjust alloca node"); 110 111 MachineOperand& MO = MI->getOperand(2); 112 assert(MO.isImm() && "Expected immediate"); 113 MO.setImm(MFI->getMaxCallFrameSize()); 114 } 115 116 std::vector<MachineMove> &Moves = MMI.getFrameMoves(); 117 118 if (needsFrameMoves) { 119 // Advance CFA. DW_CFA_def_cfa 120 unsigned FPReg = QRI->getFrameRegister(); 121 unsigned RAReg = QRI->getRARegister(); 122 123 MachineLocation Dst(MachineLocation::VirtualFP); 124 MachineLocation Src(FPReg, -8); 125 Moves.push_back(MachineMove(0, Dst, Src)); 126 127 // R31 = (R31 - #4) 128 MachineLocation LRDst(RAReg, -4); 129 MachineLocation LRSrc(RAReg); 130 Moves.push_back(MachineMove(0, LRDst, LRSrc)); 131 132 // R30 = (R30 - #8) 133 MachineLocation SPDst(FPReg, -8); 134 MachineLocation SPSrc(FPReg); 135 Moves.push_back(MachineMove(0, SPDst, SPSrc)); 136 } 137 138 // 139 // Only insert ALLOCFRAME if we need to. 140 // 141 if (hasFP(MF)) { 142 // 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 171void HexagonFrameLowering::emitEpilogue(MachineFunction &MF, 172 MachineBasicBlock &MBB) const { 173 MachineBasicBlock::iterator MBBI = prior(MBB.end()); 174 DebugLoc dl = MBBI->getDebugLoc(); 175 // 176 // Only insert deallocframe if we need to. 177 // 178 if (hasFP(MF)) { 179 MachineBasicBlock::iterator MBBI = prior(MBB.end()); 180 MachineBasicBlock::iterator MBBI_end = MBB.end(); 181 // 182 // For Hexagon, we don't need the frame size. 183 // 184 MachineFrameInfo *MFI = MF.getFrameInfo(); 185 int NumBytes = (int) MFI->getStackSize(); 186 187 const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); 188 189 // Replace 'jumpr r31' instruction with dealloc_return for V4 and higher 190 // versions. 191 if (STI.hasV4TOps() && MBBI->getOpcode() == Hexagon::JMPR 192 && !DisableDeallocRet) { 193 // Remove jumpr node. 194 MBB.erase(MBBI); 195 // Add dealloc_return. 196 BuildMI(MBB, MBBI_end, dl, TII.get(Hexagon::DEALLOC_RET_V4)) 197 .addImm(NumBytes); 198 } else { // Add deallocframe for V2 and V3. 199 BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME)).addImm(NumBytes); 200 } 201 } 202} 203 204bool HexagonFrameLowering::hasFP(const MachineFunction &MF) const { 205 const MachineFrameInfo *MFI = MF.getFrameInfo(); 206 const HexagonMachineFunctionInfo *FuncInfo = 207 MF.getInfo<HexagonMachineFunctionInfo>(); 208 return (MFI->hasCalls() || (MFI->getStackSize() > 0) || 209 FuncInfo->hasClobberLR() ); 210} 211 212static inline 213unsigned uniqueSuperReg(unsigned Reg, const TargetRegisterInfo *TRI) { 214 MCSuperRegIterator SRI(Reg, TRI); 215 assert(SRI.isValid() && "Expected a superreg"); 216 unsigned SuperReg = *SRI; 217 ++SRI; 218 assert(!SRI.isValid() && "Expected exactly one superreg"); 219 return SuperReg; 220} 221 222bool 223HexagonFrameLowering::spillCalleeSavedRegisters( 224 MachineBasicBlock &MBB, 225 MachineBasicBlock::iterator MI, 226 const std::vector<CalleeSavedInfo> &CSI, 227 const TargetRegisterInfo *TRI) const { 228 MachineFunction *MF = MBB.getParent(); 229 const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); 230 231 if (CSI.empty()) { 232 return false; 233 } 234 235 // We can only schedule double loads if we spill contiguous callee-saved regs 236 // For instance, we cannot scheduled double-word loads if we spill r24, 237 // r26, and r27. 238 // Hexagon_TODO: We can try to double-word align odd registers for -O2 and 239 // above. 240 bool ContiguousRegs = true; 241 242 for (unsigned i = 0; i < CSI.size(); ++i) { 243 unsigned Reg = CSI[i].getReg(); 244 245 // 246 // Check if we can use a double-word store. 247 // 248 unsigned SuperReg = uniqueSuperReg(Reg, TRI); 249 bool CanUseDblStore = false; 250 const TargetRegisterClass* SuperRegClass = 0; 251 252 if (ContiguousRegs && (i < CSI.size()-1)) { 253 unsigned SuperRegNext = uniqueSuperReg(CSI[i+1].getReg(), TRI); 254 SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg); 255 CanUseDblStore = (SuperRegNext == SuperReg); 256 } 257 258 259 if (CanUseDblStore) { 260 TII.storeRegToStackSlot(MBB, MI, SuperReg, true, 261 CSI[i+1].getFrameIdx(), SuperRegClass, TRI); 262 MBB.addLiveIn(SuperReg); 263 ++i; 264 } else { 265 // Cannot use a double-word store. 266 ContiguousRegs = false; 267 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 268 TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(), RC, 269 TRI); 270 MBB.addLiveIn(Reg); 271 } 272 } 273 return true; 274} 275 276 277bool HexagonFrameLowering::restoreCalleeSavedRegisters( 278 MachineBasicBlock &MBB, 279 MachineBasicBlock::iterator MI, 280 const std::vector<CalleeSavedInfo> &CSI, 281 const TargetRegisterInfo *TRI) const { 282 283 MachineFunction *MF = MBB.getParent(); 284 const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); 285 286 if (CSI.empty()) { 287 return false; 288 } 289 290 // We can only schedule double loads if we spill contiguous callee-saved regs 291 // For instance, we cannot scheduled double-word loads if we spill r24, 292 // r26, and r27. 293 // Hexagon_TODO: We can try to double-word align odd registers for -O2 and 294 // above. 295 bool ContiguousRegs = true; 296 297 for (unsigned i = 0; i < CSI.size(); ++i) { 298 unsigned Reg = CSI[i].getReg(); 299 300 // 301 // Check if we can use a double-word load. 302 // 303 unsigned SuperReg = uniqueSuperReg(Reg, TRI); 304 const TargetRegisterClass* SuperRegClass = 0; 305 bool CanUseDblLoad = false; 306 if (ContiguousRegs && (i < CSI.size()-1)) { 307 unsigned SuperRegNext = uniqueSuperReg(CSI[i+1].getReg(), TRI); 308 SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg); 309 CanUseDblLoad = (SuperRegNext == SuperReg); 310 } 311 312 313 if (CanUseDblLoad) { 314 TII.loadRegFromStackSlot(MBB, MI, SuperReg, CSI[i+1].getFrameIdx(), 315 SuperRegClass, TRI); 316 MBB.addLiveIn(SuperReg); 317 ++i; 318 } else { 319 // Cannot use a double-word load. 320 ContiguousRegs = false; 321 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 322 TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), RC, TRI); 323 MBB.addLiveIn(Reg); 324 } 325 } 326 return true; 327} 328 329int HexagonFrameLowering::getFrameIndexOffset(const MachineFunction &MF, 330 int FI) const { 331 return MF.getFrameInfo()->getObjectOffset(FI); 332} 333