HexagonFrameLowering.cpp revision 234285
1238438Sdteske//===-- HexagonFrameLowering.cpp - Define frame lowering ------------------===//
2238438Sdteske//
3249746Sdteske//                     The LLVM Compiler Infrastructure
4238438Sdteske//
5238438Sdteske// This file is distributed under the University of Illinois Open Source
6238438Sdteske// License. See LICENSE.TXT for details.
7238438Sdteske//
8238438Sdteske//
9238438Sdteske//===----------------------------------------------------------------------===//
10238438Sdteske
11238438Sdteske#include "HexagonFrameLowering.h"
12238438Sdteske#include "Hexagon.h"
13238438Sdteske#include "HexagonInstrInfo.h"
14238438Sdteske#include "HexagonRegisterInfo.h"
15238438Sdteske#include "HexagonSubtarget.h"
16238438Sdteske#include "HexagonTargetMachine.h"
17238438Sdteske#include "HexagonMachineFunctionInfo.h"
18238438Sdteske#include "llvm/Function.h"
19238438Sdteske#include "llvm/Type.h"
20238438Sdteske#include "llvm/ADT/BitVector.h"
21238438Sdteske#include "llvm/ADT/STLExtras.h"
22238438Sdteske#include "llvm/CodeGen/AsmPrinter.h"
23238438Sdteske#include "llvm/CodeGen/MachineInstrBuilder.h"
24238438Sdteske#include "llvm/CodeGen/MachineFunction.h"
25238438Sdteske#include "llvm/CodeGen/MachineFunctionPass.h"
26238438Sdteske#include "llvm/CodeGen/MachineFrameInfo.h"
27238438Sdteske#include "llvm/CodeGen/MachineModuleInfo.h"
28238438Sdteske#include "llvm/CodeGen/MachineRegisterInfo.h"
29238438Sdteske#include "llvm/CodeGen/RegisterScavenging.h"
30238438Sdteske#include "llvm/MC/MachineLocation.h"
31240684Sdteske#include "llvm/MC/MCAsmInfo.h"
32240684Sdteske#include "llvm/Target/TargetInstrInfo.h"
33244675Sdteske#include "llvm/Target/TargetMachine.h"
34240684Sdteske#include "llvm/Target/TargetOptions.h"
35240684Sdteske#include "llvm/Support/CommandLine.h"
36240684Sdteske
37240684Sdteskeusing namespace llvm;
38238438Sdteske
39240684Sdteskestatic cl::opt<bool> DisableDeallocRet(
40238438Sdteske                       "disable-hexagon-dealloc-ret",
41238438Sdteske                       cl::Hidden,
42243112Sdteske                       cl::desc("Disable Dealloc Return for Hexagon target"));
43238438Sdteske
44238438Sdteske/// determineFrameLayout - Determine the size of the frame and maximum call
45238438Sdteske/// frame size.
46238438Sdteskevoid HexagonFrameLowering::determineFrameLayout(MachineFunction &MF) const {
47238438Sdteske  MachineFrameInfo *MFI = MF.getFrameInfo();
48238438Sdteske
49238438Sdteske  // Get the number of bytes to allocate from the FrameInfo.
50238438Sdteske  unsigned FrameSize = MFI->getStackSize();
51238438Sdteske
52238438Sdteske  // Get the alignments provided by the target.
53238438Sdteske  unsigned TargetAlign = MF.getTarget().getFrameLowering()->getStackAlignment();
54238438Sdteske  // Get the maximum call frame size of all the calls.
55238438Sdteske  unsigned maxCallFrameSize = MFI->getMaxCallFrameSize();
56238438Sdteske
57240798Sdteske  // If we have dynamic alloca then maxCallFrameSize needs to be aligned so
58238438Sdteske  // that allocations will be aligned.
59238438Sdteske  if (MFI->hasVarSizedObjects())
60238438Sdteske    maxCallFrameSize = RoundUpToAlignment(maxCallFrameSize, TargetAlign);
61238438Sdteske
62238438Sdteske  // Update maximum call frame size.
63238438Sdteske  MFI->setMaxCallFrameSize(maxCallFrameSize);
64238438Sdteske
65238438Sdteske  // Include call frame size in total.
66238438Sdteske  FrameSize += maxCallFrameSize;
67238438Sdteske
68238438Sdteske  // Make sure the frame is aligned.
69238438Sdteske  FrameSize = RoundUpToAlignment(FrameSize, TargetAlign);
70238438Sdteske
71238438Sdteske  // Update frame info.
72238438Sdteske  MFI->setStackSize(FrameSize);
73238438Sdteske}
74238438Sdteske
75249751Sdteske
76238438Sdteskevoid HexagonFrameLowering::emitPrologue(MachineFunction &MF) const {
77249751Sdteske  MachineBasicBlock &MBB = MF.front();
78249751Sdteske  MachineFrameInfo *MFI = MF.getFrameInfo();
79249751Sdteske  MachineModuleInfo &MMI = MF.getMMI();
80238438Sdteske  MachineBasicBlock::iterator MBBI = MBB.begin();
81249751Sdteske  const HexagonRegisterInfo *QRI =
82238438Sdteske    static_cast<const HexagonRegisterInfo *>(MF.getTarget().getRegisterInfo());
83238438Sdteske  DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
84238438Sdteske  determineFrameLayout(MF);
85238438Sdteske
86238438Sdteske  // Check if frame moves are needed for EH.
87249751Sdteske  bool needsFrameMoves = MMI.hasDebugInfo() ||
88240783Sdteske    !MF.getFunction()->needsUnwindTableEntry();
89240783Sdteske
90238438Sdteske  // Get the number of bytes to allocate from the FrameInfo.
91238438Sdteske  int NumBytes = (int) MFI->getStackSize();
92238438Sdteske
93238438Sdteske  // LLVM expects allocframe not to be the first instruction in the
94238438Sdteske  // basic block.
95238438Sdteske  MachineBasicBlock::iterator InsertPt = MBB.begin();
96238438Sdteske
97238438Sdteske  //
98238438Sdteske  // ALLOCA adjust regs.  Iterate over ADJDYNALLOC nodes and change the offset.
99238438Sdteske  //
100238438Sdteske  HexagonMachineFunctionInfo *FuncInfo =
101238438Sdteske    MF.getInfo<HexagonMachineFunctionInfo>();
102238438Sdteske  const std::vector<MachineInstr*>& AdjustRegs =
103238438Sdteske    FuncInfo->getAllocaAdjustInsts();
104238438Sdteske  for (std::vector<MachineInstr*>::const_iterator i = AdjustRegs.begin(),
105238438Sdteske         e = AdjustRegs.end();
106238438Sdteske       i != e; ++i) {
107238438Sdteske    MachineInstr* MI = *i;
108238438Sdteske    assert((MI->getOpcode() == Hexagon::ADJDYNALLOC) &&
109238438Sdteske           "Expected adjust alloca node");
110238438Sdteske
111238438Sdteske    MachineOperand& MO = MI->getOperand(2);
112238438Sdteske    assert(MO.isImm() && "Expected immediate");
113238438Sdteske    MO.setImm(MFI->getMaxCallFrameSize());
114238438Sdteske  }
115238438Sdteske
116238438Sdteske std::vector<MachineMove> &Moves = MMI.getFrameMoves();
117238438Sdteske
118238438Sdteske if (needsFrameMoves) {
119238438Sdteske   // Advance CFA. DW_CFA_def_cfa
120238438Sdteske   unsigned FPReg = QRI->getFrameRegister();
121238438Sdteske   unsigned RAReg = QRI->getRARegister();
122238438Sdteske
123238438Sdteske   MachineLocation Dst(MachineLocation::VirtualFP);
124238438Sdteske   MachineLocation Src(FPReg, -8);
125238438Sdteske   Moves.push_back(MachineMove(0, Dst, Src));
126238438Sdteske
127238438Sdteske   // R31 = (R31 - #4)
128238438Sdteske   MachineLocation LRDst(RAReg, -4);
129238438Sdteske   MachineLocation LRSrc(RAReg);
130238438Sdteske   Moves.push_back(MachineMove(0, LRDst, LRSrc));
131238438Sdteske
132238438Sdteske   // R30 = (R30 - #8)
133238438Sdteske   MachineLocation SPDst(FPReg, -8);
134238438Sdteske   MachineLocation SPSrc(FPReg);
135238438Sdteske   Moves.push_back(MachineMove(0, SPDst, SPSrc));
136238438Sdteske }
137238438Sdteske
138238438Sdteske  //
139238438Sdteske  // Only insert ALLOCFRAME if we need to.
140249751Sdteske  //
141249751Sdteske  if (hasFP(MF)) {
142238438Sdteske    // Check for overflow.
143249751Sdteske    // Hexagon_TODO: Ugh! hardcoding. Is there an API that can be used?
144249751Sdteske    const int ALLOCFRAME_MAX = 16384;
145249751Sdteske    const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
146249751Sdteske
147249751Sdteske    if (NumBytes >= ALLOCFRAME_MAX) {
148249751Sdteske      // Emit allocframe(#0).
149249751Sdteske      BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(0);
150249751Sdteske
151238438Sdteske      // Subtract offset from frame pointer.
152249751Sdteske      BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::CONST32_Int_Real),
153249751Sdteske                                      HEXAGON_RESERVED_REG_1).addImm(NumBytes);
154249751Sdteske      BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::SUB_rr),
155249751Sdteske                                      QRI->getStackRegister()).
156249751Sdteske                                      addReg(QRI->getStackRegister()).
157249751Sdteske                                      addReg(HEXAGON_RESERVED_REG_1);
158249751Sdteske    } else {
159249751Sdteske      BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(NumBytes);
160249751Sdteske    }
161249751Sdteske  }
162249751Sdteske}
163249751Sdteske// Returns true if MBB has a machine instructions that indicates a tail call
164249751Sdteske// in the block.
165249751Sdteskebool HexagonFrameLowering::hasTailCall(MachineBasicBlock &MBB) const {
166249751Sdteske  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
167249751Sdteske  unsigned RetOpcode = MBBI->getOpcode();
168249751Sdteske
169249751Sdteske  return RetOpcode == Hexagon::TCRETURNtg || RetOpcode == Hexagon::TCRETURNtext;}
170249751Sdteske
171249751Sdteskevoid HexagonFrameLowering::emitEpilogue(MachineFunction &MF,
172249751Sdteske                                     MachineBasicBlock &MBB) const {
173249751Sdteske  MachineBasicBlock::iterator MBBI = prior(MBB.end());
174249751Sdteske  DebugLoc dl = MBBI->getDebugLoc();
175249751Sdteske  //
176249751Sdteske  // Only insert deallocframe if we need to.
177249751Sdteske  //
178249751Sdteske  if (hasFP(MF)) {
179249751Sdteske    MachineBasicBlock::iterator MBBI = prior(MBB.end());
180249751Sdteske    MachineBasicBlock::iterator MBBI_end = MBB.end();
181249751Sdteske    //
182249751Sdteske    // For Hexagon, we don't need the frame size.
183249751Sdteske    //
184249751Sdteske    MachineFrameInfo *MFI = MF.getFrameInfo();
185249751Sdteske    int NumBytes = (int) MFI->getStackSize();
186249751Sdteske
187249751Sdteske    const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
188249751Sdteske
189249751Sdteske    // Replace 'jumpr r31' instruction with dealloc_return for V4 and higher
190249751Sdteske    // versions.
191249751Sdteske    if (STI.hasV4TOps() && MBBI->getOpcode() == Hexagon::JMPR
192249751Sdteske                        && !DisableDeallocRet) {
193249751Sdteske      // Remove jumpr node.
194249751Sdteske      MBB.erase(MBBI);
195249751Sdteske      // Add dealloc_return.
196249751Sdteske      BuildMI(MBB, MBBI_end, dl, TII.get(Hexagon::DEALLOC_RET_V4))
197249751Sdteske        .addImm(NumBytes);
198249751Sdteske    } else { // Add deallocframe for V2 and V3.
199251190Sdteske      BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME)).addImm(NumBytes);
200251190Sdteske    }
201251190Sdteske  }
202251190Sdteske}
203251190Sdteske
204251190Sdteskebool HexagonFrameLowering::hasFP(const MachineFunction &MF) const {
205251190Sdteske  const MachineFrameInfo *MFI = MF.getFrameInfo();
206251190Sdteske  const HexagonMachineFunctionInfo *FuncInfo =
207238438Sdteske    MF.getInfo<HexagonMachineFunctionInfo>();
208251236Sdteske  return (MFI->hasCalls() || (MFI->getStackSize() > 0) ||
209251236Sdteske          FuncInfo->hasClobberLR() );
210249751Sdteske}
211249751Sdteske
212249751Sdteskebool
213249751SdteskeHexagonFrameLowering::spillCalleeSavedRegisters(
214249751Sdteske                                        MachineBasicBlock &MBB,
215249751Sdteske                                        MachineBasicBlock::iterator MI,
216249751Sdteske                                        const std::vector<CalleeSavedInfo> &CSI,
217249751Sdteske                                        const TargetRegisterInfo *TRI) const {
218249751Sdteske  MachineFunction *MF = MBB.getParent();
219249751Sdteske  const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
220251190Sdteske
221251190Sdteske  if (CSI.empty()) {
222249751Sdteske    return false;
223240768Sdteske  }
224240768Sdteske
225240768Sdteske  // We can only schedule double loads if we spill contiguous callee-saved regs
226251236Sdteske  // For instance, we cannot scheduled double-word loads if we spill r24,
227251236Sdteske  // r26, and r27.
228249751Sdteske  // Hexagon_TODO: We can try to double-word align odd registers for -O2 and
229249751Sdteske  // above.
230251236Sdteske  bool ContiguousRegs = true;
231249751Sdteske
232240768Sdteske  for (unsigned i = 0; i < CSI.size(); ++i) {
233238438Sdteske    unsigned Reg = CSI[i].getReg();
234238438Sdteske
235249751Sdteske    //
236238438Sdteske    // Check if we can use a double-word store.
237249751Sdteske    //
238249751Sdteske    const uint16_t* SuperReg = TRI->getSuperRegisters(Reg);
239249751Sdteske
240238438Sdteske    // Assume that there is exactly one superreg.
241249751Sdteske    assert(SuperReg[0] && !SuperReg[1] && "Expected exactly one superreg");
242238438Sdteske    bool CanUseDblStore = false;
243238438Sdteske    const TargetRegisterClass* SuperRegClass = 0;
244238438Sdteske
245238438Sdteske    if (ContiguousRegs && (i < CSI.size()-1)) {
246238438Sdteske      const uint16_t* SuperRegNext = TRI->getSuperRegisters(CSI[i+1].getReg());
247238438Sdteske      assert(SuperRegNext[0] && !SuperRegNext[1] &&
248238438Sdteske             "Expected exactly one superreg");
249238438Sdteske      SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg[0]);
250245402Sdteske      CanUseDblStore = (SuperRegNext[0] == SuperReg[0]);
251238438Sdteske    }
252238438Sdteske
253238438Sdteske
254238438Sdteske    if (CanUseDblStore) {
255238438Sdteske      TII.storeRegToStackSlot(MBB, MI, SuperReg[0], true,
256238438Sdteske                              CSI[i+1].getFrameIdx(), SuperRegClass, TRI);
257238438Sdteske      MBB.addLiveIn(SuperReg[0]);
258238438Sdteske      ++i;
259238438Sdteske    } else {
260238438Sdteske      // Cannot use a double-word store.
261238438Sdteske      ContiguousRegs = false;
262238438Sdteske      const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
263238438Sdteske      TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(), RC,
264238438Sdteske                              TRI);
265238438Sdteske      MBB.addLiveIn(Reg);
266238438Sdteske    }
267238438Sdteske  }
268238438Sdteske  return true;
269238438Sdteske}
270238438Sdteske
271238438Sdteske
272238438Sdteskebool HexagonFrameLowering::restoreCalleeSavedRegisters(
273238438Sdteske                                        MachineBasicBlock &MBB,
274251190Sdteske                                        MachineBasicBlock::iterator MI,
275251190Sdteske                                        const std::vector<CalleeSavedInfo> &CSI,
276251190Sdteske                                        const TargetRegisterInfo *TRI) const {
277251190Sdteske
278251190Sdteske  MachineFunction *MF = MBB.getParent();
279251190Sdteske  const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
280251190Sdteske
281238438Sdteske  if (CSI.empty()) {
282238438Sdteske    return false;
283238438Sdteske  }
284238438Sdteske
285249751Sdteske  // We can only schedule double loads if we spill contiguous callee-saved regs
286249751Sdteske  // For instance, we cannot scheduled double-word loads if we spill r24,
287238438Sdteske  // r26, and r27.
288238438Sdteske  // Hexagon_TODO: We can try to double-word align odd registers for -O2 and
289238438Sdteske  // above.
290238438Sdteske  bool ContiguousRegs = true;
291238438Sdteske
292251190Sdteske  for (unsigned i = 0; i < CSI.size(); ++i) {
293251190Sdteske    unsigned Reg = CSI[i].getReg();
294238438Sdteske
295249751Sdteske    //
296249954Sdteske    // Check if we can use a double-word load.
297249954Sdteske    //
298238438Sdteske    const uint16_t* SuperReg = TRI->getSuperRegisters(Reg);
299238438Sdteske    const TargetRegisterClass* SuperRegClass = 0;
300238438Sdteske
301238438Sdteske    // Assume that there is exactly one superreg.
302238438Sdteske    assert(SuperReg[0] && !SuperReg[1] && "Expected exactly one superreg");
303238438Sdteske    bool CanUseDblLoad = false;
304238438Sdteske    if (ContiguousRegs && (i < CSI.size()-1)) {
305238438Sdteske      const uint16_t* SuperRegNext = TRI->getSuperRegisters(CSI[i+1].getReg());
306238438Sdteske      assert(SuperRegNext[0] && !SuperRegNext[1] &&
307238438Sdteske             "Expected exactly one superreg");
308250633Sdteske      SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg[0]);
309238438Sdteske      CanUseDblLoad = (SuperRegNext[0] == SuperReg[0]);
310238438Sdteske    }
311238438Sdteske
312238438Sdteske
313238438Sdteske    if (CanUseDblLoad) {
314238438Sdteske      TII.loadRegFromStackSlot(MBB, MI, SuperReg[0], CSI[i+1].getFrameIdx(),
315238438Sdteske                               SuperRegClass, TRI);
316238438Sdteske      MBB.addLiveIn(SuperReg[0]);
317238438Sdteske      ++i;
318238438Sdteske    } else {
319238438Sdteske      // Cannot use a double-word load.
320238438Sdteske      ContiguousRegs = false;
321238438Sdteske      const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
322249751Sdteske      TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), RC, TRI);
323249751Sdteske      MBB.addLiveIn(Reg);
324249751Sdteske    }
325249751Sdteske  }
326249751Sdteske  return true;
327249751Sdteske}
328249751Sdteske
329249751Sdteskeint HexagonFrameLowering::getFrameIndexOffset(const MachineFunction &MF,
330249751Sdteske                                              int FI) const {
331249751Sdteske  return MF.getFrameInfo()->getObjectOffset(FI);
332238438Sdteske}
333238438Sdteske