LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HexagonFrameLowering.cpp
Go to the documentation of this file.
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"
15 #include "HexagonRegisterInfo.h"
16 #include "HexagonSubtarget.h"
17 #include "HexagonTargetMachine.h"
18 #include "llvm/ADT/BitVector.h"
19 #include "llvm/ADT/STLExtras.h"
28 #include "llvm/IR/Function.h"
29 #include "llvm/IR/Type.h"
30 #include "llvm/MC/MCAsmInfo.h"
36 
37 using namespace llvm;
38 
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.
46 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 
77  MachineBasicBlock &MBB = MF.front();
78  MachineFrameInfo *MFI = MF.getFrameInfo();
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 =
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.
140  unsigned RetOpcode = MBBI->getOpcode();
141 
142  return RetOpcode == Hexagon::TCRETURNtg || RetOpcode == Hexagon::TCRETURNtext;
143 }
144 
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.
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 
204  const MachineFrameInfo *MFI = MF.getFrameInfo();
205  const HexagonMachineFunctionInfo *FuncInfo =
207  return (MFI->hasCalls() || (MFI->getStackSize() > 0) ||
208  FuncInfo->hasClobberLR() );
209 }
210 
211 static inline
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
223  MachineBasicBlock &MBB,
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 
277  MachineBasicBlock &MBB,
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 
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 
344  int FI) const {
345  return MF.getFrameInfo()->getObjectOffset(FI);
346 }
unsigned getStackAlignment() const
const MachineFunction * getParent() const
instr_iterator erase(instr_iterator I)
#define HEXAGON_RESERVED_REG_1
const TargetRegisterClass * getMinimalPhysRegClass(unsigned Reg, EVT VT=MVT::Other) const
bool isValid() const
isValid - returns true if this iterator is not yet at the end.
void addLiveIn(unsigned Reg)
Hexagon target-specific information for each MachineFunction.
bool hasTailCall(MachineBasicBlock &MBB) const
bool hasFP(const MachineFunction &MF) const
virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector< CalleeSavedInfo > &CSI, const TargetRegisterInfo *TRI) const
uint64_t getStackSize() const
static unsigned uniqueSuperReg(unsigned Reg, const TargetRegisterInfo *TRI)
const HexagonInstrInfo * TII
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
#define llvm_unreachable(msg)
Abstract Stack Frame Information.
const MachineBasicBlock & front() const
int getOpcode() const
Definition: MachineInstr.h:261
CodeGenOpt::Level getOptLevel() const
bundle_iterator< MachineInstr, instr_iterator > iterator
static cl::opt< bool > DisableDeallocRet("disable-hexagon-dealloc-ret", cl::Hidden, cl::desc("Disable Dealloc Return for Hexagon target"))
void setStackSize(uint64_t Size)
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:267
virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const
void setImm(int64_t immVal)
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
virtual void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const
virtual const TargetFrameLowering * getFrameLowering() const
const MCInstrDesc & get(unsigned Opcode) const
Definition: MCInstrInfo.h:48
int64_t getObjectOffset(int ObjectIdx) const
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const
bool hasCalls() const
hasCalls - Return true if the current function has any function calls.
virtual const TargetInstrInfo * getInstrInfo() const
const std::vector< MachineInstr * > & getAllocaAdjustInsts()
unsigned getMaxCallFrameSize() const
MachineFrameInfo * getFrameInfo()
int getFrameIndexOffset(const MachineFunction &MF, int FI) const
void eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const
uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align)
Definition: MathExtras.h:565
void copyImplicitOps(MachineFunction &MF, const MachineInstr *MI)
virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector< CalleeSavedInfo > &CSI, const TargetRegisterInfo *TRI) const
#define I(x, y, z)
Definition: MD5.cpp:54
void setMaxCallFrameSize(unsigned S)
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
const TargetMachine & getTarget() const
virtual const TargetRegisterInfo * getRegisterInfo() const
bool hasVarSizedObjects() const
ItTy prior(ItTy it, Dist n)
Definition: STLExtras.h:167
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
void emitPrologue(MachineFunction &MF) const