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
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}
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::JMPR
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