• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/IR/Function.h"
29 #include "llvm/IR/Type.h"
30 #include "llvm/MC/MCAsmInfo.h"
31 #include "llvm/MC/MachineLocation.h"
32 #include "llvm/Support/CommandLine.h"
33 #include "llvm/Target/TargetInstrInfo.h"
34 #include "llvm/Target/TargetMachine.h"
35 #include "llvm/Target/TargetOptions.h"
36 
37 using namespace llvm;
38 
39 static 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.
determineFrameLayout(MachineFunction & MF) const46 void 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 
emitPrologue(MachineFunction & MF) const76 void HexagonFrameLowering::emitPrologue(MachineFunction &MF) const {
77   MachineBasicBlock &MBB = MF.front();
78   MachineFrameInfo *MFI = MF.getFrameInfo();
79   MachineBasicBlock::iterator MBBI = MBB.begin();
80   const HexagonRegisterInfo *QRI =
81     static_cast<const HexagonRegisterInfo *>(MF.getTarget().getRegisterInfo());
82   DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
83   determineFrameLayout(MF);
84 
85   // Get the number of bytes to allocate from the FrameInfo.
86   int NumBytes = (int) MFI->getStackSize();
87 
88   // LLVM expects allocframe not to be the first instruction in the
89   // basic block.
90   MachineBasicBlock::iterator InsertPt = MBB.begin();
91 
92   //
93   // ALLOCA adjust regs.  Iterate over ADJDYNALLOC nodes and change the offset.
94   //
95   HexagonMachineFunctionInfo *FuncInfo =
96     MF.getInfo<HexagonMachineFunctionInfo>();
97   const std::vector<MachineInstr*>& AdjustRegs =
98     FuncInfo->getAllocaAdjustInsts();
99   for (std::vector<MachineInstr*>::const_iterator i = AdjustRegs.begin(),
100          e = AdjustRegs.end();
101        i != e; ++i) {
102     MachineInstr* MI = *i;
103     assert((MI->getOpcode() == Hexagon::ADJDYNALLOC) &&
104            "Expected adjust alloca node");
105 
106     MachineOperand& MO = MI->getOperand(2);
107     assert(MO.isImm() && "Expected immediate");
108     MO.setImm(MFI->getMaxCallFrameSize());
109   }
110 
111   //
112   // Only insert ALLOCFRAME if we need to.
113   //
114   if (hasFP(MF)) {
115     // Check for overflow.
116     // Hexagon_TODO: Ugh! hardcoding. Is there an API that can be used?
117     const int ALLOCFRAME_MAX = 16384;
118     const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
119 
120     if (NumBytes >= ALLOCFRAME_MAX) {
121       // Emit allocframe(#0).
122       BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(0);
123 
124       // Subtract offset from frame pointer.
125       BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::CONST32_Int_Real),
126                                       HEXAGON_RESERVED_REG_1).addImm(NumBytes);
127       BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::SUB_rr),
128                                       QRI->getStackRegister()).
129                                       addReg(QRI->getStackRegister()).
130                                       addReg(HEXAGON_RESERVED_REG_1);
131     } else {
132       BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(NumBytes);
133     }
134   }
135 }
136 // Returns true if MBB has a machine instructions that indicates a tail call
137 // in the block.
hasTailCall(MachineBasicBlock & MBB) const138 bool HexagonFrameLowering::hasTailCall(MachineBasicBlock &MBB) const {
139   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
140   unsigned RetOpcode = MBBI->getOpcode();
141 
142   return RetOpcode == Hexagon::TCRETURNtg || RetOpcode == Hexagon::TCRETURNtext;
143 }
144 
emitEpilogue(MachineFunction & MF,MachineBasicBlock & MBB) const145 void HexagonFrameLowering::emitEpilogue(MachineFunction &MF,
146                                      MachineBasicBlock &MBB) const {
147   MachineBasicBlock::iterator MBBI = prior(MBB.end());
148   DebugLoc dl = MBBI->getDebugLoc();
149   //
150   // Only insert deallocframe if we need to.  Also at -O0.  See comment
151   // in emitPrologue above.
152   //
153   if (hasFP(MF) || MF.getTarget().getOptLevel() == CodeGenOpt::None) {
154     MachineBasicBlock::iterator MBBI = prior(MBB.end());
155     MachineBasicBlock::iterator MBBI_end = MBB.end();
156 
157     const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
158     // Handle EH_RETURN.
159     if (MBBI->getOpcode() == Hexagon::EH_RETURN_JMPR) {
160       assert(MBBI->getOperand(0).isReg() && "Offset should be in register!");
161       BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME));
162       BuildMI(MBB, MBBI, dl, TII.get(Hexagon::ADD_rr),
163               Hexagon::R29).addReg(Hexagon::R29).addReg(Hexagon::R28);
164       return;
165     }
166     // Replace 'jumpr r31' instruction with dealloc_return for V4 and higher
167     // versions.
168     if (STI.hasV4TOps() && MBBI->getOpcode() == Hexagon::JMPret
169                         && !DisableDeallocRet) {
170       // Check for RESTORE_DEALLOC_RET_JMP_V4 call. Don't emit an extra DEALLOC
171       // instruction if we encounter it.
172       MachineBasicBlock::iterator BeforeJMPR =
173         MBB.begin() == MBBI ? MBBI : prior(MBBI);
174       if (BeforeJMPR != MBBI &&
175           BeforeJMPR->getOpcode() == Hexagon::RESTORE_DEALLOC_RET_JMP_V4) {
176         // Remove the JMPR node.
177         MBB.erase(MBBI);
178         return;
179       }
180 
181       // Add dealloc_return.
182       MachineInstrBuilder MIB =
183         BuildMI(MBB, MBBI_end, dl, TII.get(Hexagon::DEALLOC_RET_V4));
184       // Transfer the function live-out registers.
185       MIB->copyImplicitOps(*MBB.getParent(), &*MBBI);
186       // Remove the JUMPR node.
187       MBB.erase(MBBI);
188     } else { // Add deallocframe for V2 and V3, and V4 tail calls.
189       // Check for RESTORE_DEALLOC_BEFORE_TAILCALL_V4. We don't need an extra
190       // DEALLOCFRAME instruction after it.
191       MachineBasicBlock::iterator Term = MBB.getFirstTerminator();
192       MachineBasicBlock::iterator I =
193         Term == MBB.begin() ?  MBB.end() : prior(Term);
194       if (I != MBB.end() &&
195           I->getOpcode() == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4)
196         return;
197 
198       BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME));
199     }
200   }
201 }
202 
hasFP(const MachineFunction & MF) const203 bool HexagonFrameLowering::hasFP(const MachineFunction &MF) const {
204   const MachineFrameInfo *MFI = MF.getFrameInfo();
205   const HexagonMachineFunctionInfo *FuncInfo =
206     MF.getInfo<HexagonMachineFunctionInfo>();
207   return (MFI->hasCalls() || (MFI->getStackSize() > 0) ||
208           FuncInfo->hasClobberLR() );
209 }
210 
211 static inline
uniqueSuperReg(unsigned Reg,const TargetRegisterInfo * TRI)212 unsigned uniqueSuperReg(unsigned Reg, const TargetRegisterInfo *TRI) {
213   MCSuperRegIterator SRI(Reg, TRI);
214   assert(SRI.isValid() && "Expected a superreg");
215   unsigned SuperReg = *SRI;
216   ++SRI;
217   assert(!SRI.isValid() && "Expected exactly one superreg");
218   return SuperReg;
219 }
220 
221 bool
spillCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,const std::vector<CalleeSavedInfo> & CSI,const TargetRegisterInfo * TRI) const222 HexagonFrameLowering::spillCalleeSavedRegisters(
223                                         MachineBasicBlock &MBB,
224                                         MachineBasicBlock::iterator MI,
225                                         const std::vector<CalleeSavedInfo> &CSI,
226                                         const TargetRegisterInfo *TRI) const {
227   MachineFunction *MF = MBB.getParent();
228   const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
229 
230   if (CSI.empty()) {
231     return false;
232   }
233 
234   // We can only schedule double loads if we spill contiguous callee-saved regs
235   // For instance, we cannot scheduled double-word loads if we spill r24,
236   // r26, and r27.
237   // Hexagon_TODO: We can try to double-word align odd registers for -O2 and
238   // above.
239   bool ContiguousRegs = true;
240 
241   for (unsigned i = 0; i < CSI.size(); ++i) {
242     unsigned Reg = CSI[i].getReg();
243 
244     //
245     // Check if we can use a double-word store.
246     //
247     unsigned SuperReg = uniqueSuperReg(Reg, TRI);
248     bool CanUseDblStore = false;
249     const TargetRegisterClass* SuperRegClass = 0;
250 
251     if (ContiguousRegs && (i < CSI.size()-1)) {
252       unsigned SuperRegNext = uniqueSuperReg(CSI[i+1].getReg(), TRI);
253       SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg);
254       CanUseDblStore = (SuperRegNext == SuperReg);
255     }
256 
257 
258     if (CanUseDblStore) {
259       TII.storeRegToStackSlot(MBB, MI, SuperReg, true,
260                               CSI[i+1].getFrameIdx(), SuperRegClass, TRI);
261       MBB.addLiveIn(SuperReg);
262       ++i;
263     } else {
264       // Cannot use a double-word store.
265       ContiguousRegs = false;
266       const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
267       TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(), RC,
268                               TRI);
269       MBB.addLiveIn(Reg);
270     }
271   }
272   return true;
273 }
274 
275 
restoreCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,const std::vector<CalleeSavedInfo> & CSI,const TargetRegisterInfo * TRI) const276 bool HexagonFrameLowering::restoreCalleeSavedRegisters(
277                                         MachineBasicBlock &MBB,
278                                         MachineBasicBlock::iterator MI,
279                                         const std::vector<CalleeSavedInfo> &CSI,
280                                         const TargetRegisterInfo *TRI) const {
281 
282   MachineFunction *MF = MBB.getParent();
283   const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
284 
285   if (CSI.empty()) {
286     return false;
287   }
288 
289   // We can only schedule double loads if we spill contiguous callee-saved regs
290   // For instance, we cannot scheduled double-word loads if we spill r24,
291   // r26, and r27.
292   // Hexagon_TODO: We can try to double-word align odd registers for -O2 and
293   // above.
294   bool ContiguousRegs = true;
295 
296   for (unsigned i = 0; i < CSI.size(); ++i) {
297     unsigned Reg = CSI[i].getReg();
298 
299     //
300     // Check if we can use a double-word load.
301     //
302     unsigned SuperReg = uniqueSuperReg(Reg, TRI);
303     const TargetRegisterClass* SuperRegClass = 0;
304     bool CanUseDblLoad = false;
305     if (ContiguousRegs && (i < CSI.size()-1)) {
306       unsigned SuperRegNext = uniqueSuperReg(CSI[i+1].getReg(), TRI);
307       SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg);
308       CanUseDblLoad = (SuperRegNext == SuperReg);
309     }
310 
311 
312     if (CanUseDblLoad) {
313       TII.loadRegFromStackSlot(MBB, MI, SuperReg, CSI[i+1].getFrameIdx(),
314                                SuperRegClass, TRI);
315       MBB.addLiveIn(SuperReg);
316       ++i;
317     } else {
318       // Cannot use a double-word load.
319       ContiguousRegs = false;
320       const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
321       TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), RC, TRI);
322       MBB.addLiveIn(Reg);
323     }
324   }
325   return true;
326 }
327 
328 void HexagonFrameLowering::
eliminateCallFramePseudoInstr(MachineFunction & MF,MachineBasicBlock & MBB,MachineBasicBlock::iterator I) const329 eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
330                               MachineBasicBlock::iterator I) const {
331   MachineInstr &MI = *I;
332 
333   if (MI.getOpcode() == Hexagon::ADJCALLSTACKDOWN) {
334     // Hexagon_TODO: add code
335   } else if (MI.getOpcode() == Hexagon::ADJCALLSTACKUP) {
336     // Hexagon_TODO: add code
337   } else {
338     llvm_unreachable("Cannot handle this call frame pseudo instruction");
339   }
340   MBB.erase(I);
341 }
342 
getFrameIndexOffset(const MachineFunction & MF,int FI) const343 int HexagonFrameLowering::getFrameIndexOffset(const MachineFunction &MF,
344                                               int FI) const {
345   return MF.getFrameInfo()->getObjectOffset(FI);
346 }
347