HexagonFrameLowering.cpp revision 239462
153247Sarchie//===-- HexagonFrameLowering.cpp - Define frame lowering ------------------===//
253247Sarchie//
379727Sschweikh//                     The LLVM Compiler Infrastructure
453247Sarchie//
553247Sarchie// This file is distributed under the University of Illinois Open Source
653247Sarchie// License. See LICENSE.TXT for details.
753247Sarchie//
853247Sarchie//
953247Sarchie//===----------------------------------------------------------------------===//
1053247Sarchie
1153247Sarchie#include "HexagonFrameLowering.h"
1253247Sarchie#include "Hexagon.h"
1353247Sarchie#include "HexagonInstrInfo.h"
1479727Sschweikh#include "HexagonRegisterInfo.h"
1553247Sarchie#include "HexagonSubtarget.h"
1653247Sarchie#include "HexagonTargetMachine.h"
1753247Sarchie#include "HexagonMachineFunctionInfo.h"
1853247Sarchie#include "llvm/Function.h"
1953247Sarchie#include "llvm/Type.h"
2053247Sarchie#include "llvm/ADT/BitVector.h"
2153247Sarchie#include "llvm/ADT/STLExtras.h"
2253247Sarchie#include "llvm/CodeGen/AsmPrinter.h"
2353247Sarchie#include "llvm/CodeGen/MachineInstrBuilder.h"
2453247Sarchie#include "llvm/CodeGen/MachineFunction.h"
2553247Sarchie#include "llvm/CodeGen/MachineFunctionPass.h"
2653247Sarchie#include "llvm/CodeGen/MachineFrameInfo.h"
2753247Sarchie#include "llvm/CodeGen/MachineModuleInfo.h"
2853247Sarchie#include "llvm/CodeGen/MachineRegisterInfo.h"
2953247Sarchie#include "llvm/CodeGen/RegisterScavenging.h"
3053247Sarchie#include "llvm/MC/MachineLocation.h"
3153247Sarchie#include "llvm/MC/MCAsmInfo.h"
3279727Sschweikh#include "llvm/Target/TargetInstrInfo.h"
3367627Sasmodai#include "llvm/Target/TargetMachine.h"
3453247Sarchie#include "llvm/Target/TargetOptions.h"
3553247Sarchie#include "llvm/Support/CommandLine.h"
3653247Sarchie
37236596Seadlerusing namespace llvm;
3859982Sarchie
3979538Srustatic cl::opt<bool> DisableDeallocRet(
4053247Sarchie                       "disable-hexagon-dealloc-ret",
4153247Sarchie                       cl::Hidden,
4253247Sarchie                       cl::desc("Disable Dealloc Return for Hexagon target"));
4353247Sarchie
44141350Sru/// determineFrameLayout - Determine the size of the frame and maximum call
4584306Sru/// frame size.
4653247Sarchievoid HexagonFrameLowering::determineFrameLayout(MachineFunction &MF) const {
4753247Sarchie  MachineFrameInfo *MFI = MF.getFrameInfo();
4853247Sarchie
4981622Sru  // Get the number of bytes to allocate from the FrameInfo.
5081622Sru  unsigned FrameSize = MFI->getStackSize();
51117011Sru
52117011Sru  // Get the alignments provided by the target.
5354927Sjulian  unsigned TargetAlign = MF.getTarget().getFrameLowering()->getStackAlignment();
5453247Sarchie  // Get the maximum call frame size of all the calls.
55117011Sru  unsigned maxCallFrameSize = MFI->getMaxCallFrameSize();
56117011Sru
5754927Sjulian  // If we have dynamic alloca then maxCallFrameSize needs to be aligned so
5853247Sarchie  // that allocations will be aligned.
5959982Sarchie  if (MFI->hasVarSizedObjects())
6053247Sarchie    maxCallFrameSize = RoundUpToAlignment(maxCallFrameSize, TargetAlign);
6153939Sarchie
6253939Sarchie  // Update maximum call frame size.
6354927Sjulian  MFI->setMaxCallFrameSize(maxCallFrameSize);
6453247Sarchie
6553939Sarchie  // Include call frame size in total.
6653247Sarchie  FrameSize += maxCallFrameSize;
6753247Sarchie
6854927Sjulian  // Make sure the frame is aligned.
69117011Sru  FrameSize = RoundUpToAlignment(FrameSize, TargetAlign);
70117011Sru
71117011Sru  // Update frame info.
72117011Sru  MFI->setStackSize(FrameSize);
7353939Sarchie}
7453247Sarchie
7553247Sarchie
7653247Sarchievoid HexagonFrameLowering::emitPrologue(MachineFunction &MF) const {
7753247Sarchie  MachineBasicBlock &MBB = MF.front();
7853247Sarchie  MachineFrameInfo *MFI = MF.getFrameInfo();
7973233Sru  MachineModuleInfo &MMI = MF.getMMI();
8053247Sarchie  MachineBasicBlock::iterator MBBI = MBB.begin();
8173233Sru  const HexagonRegisterInfo *QRI =
8273233Sru    static_cast<const HexagonRegisterInfo *>(MF.getTarget().getRegisterInfo());
8353247Sarchie  DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
8473233Sru  determineFrameLayout(MF);
8553247Sarchie
8653247Sarchie  // Check if frame moves are needed for EH.
8753247Sarchie  bool needsFrameMoves = MMI.hasDebugInfo() ||
88131530Sru    !MF.getFunction()->needsUnwindTableEntry();
89131530Sru
9053247Sarchie  // Get the number of bytes to allocate from the FrameInfo.
9179727Sschweikh  int NumBytes = (int) MFI->getStackSize();
9253247Sarchie
93131108Sjulian  // LLVM expects allocframe not to be the first instruction in the
94131108Sjulian  // basic block.
95131108Sjulian  MachineBasicBlock::iterator InsertPt = MBB.begin();
96131108Sjulian
97131108Sjulian  //
98131108Sjulian  // ALLOCA adjust regs.  Iterate over ADJDYNALLOC nodes and change the offset.
99131108Sjulian  //
100131530Sru  HexagonMachineFunctionInfo *FuncInfo =
101131108Sjulian    MF.getInfo<HexagonMachineFunctionInfo>();
102131108Sjulian  const std::vector<MachineInstr*>& AdjustRegs =
103131108Sjulian    FuncInfo->getAllocaAdjustInsts();
104131108Sjulian  for (std::vector<MachineInstr*>::const_iterator i = AdjustRegs.begin(),
105131108Sjulian         e = AdjustRegs.end();
106131108Sjulian       i != e; ++i) {
107131108Sjulian    MachineInstr* MI = *i;
108131108Sjulian    assert((MI->getOpcode() == Hexagon::ADJDYNALLOC) &&
109131530Sru           "Expected adjust alloca node");
110131108Sjulian
11153247Sarchie    MachineOperand& MO = MI->getOperand(2);
11253247Sarchie    assert(MO.isImm() && "Expected immediate");
11353247Sarchie    MO.setImm(MFI->getMaxCallFrameSize());
114242997Sjoel  }
11553247Sarchie
11653247Sarchie std::vector<MachineMove> &Moves = MMI.getFrameMoves();
117117011Sru
118117011Sru if (needsFrameMoves) {
119131530Sru   // Advance CFA. DW_CFA_def_cfa
12053247Sarchie   unsigned FPReg = QRI->getFrameRegister();
121242997Sjoel   unsigned RAReg = QRI->getRARegister();
12253247Sarchie
12353247Sarchie   MachineLocation Dst(MachineLocation::VirtualFP);
124117011Sru   MachineLocation Src(FPReg, -8);
125117011Sru   Moves.push_back(MachineMove(0, Dst, Src));
12653247Sarchie
12753247Sarchie   // R31 = (R31 - #4)
128242997Sjoel   MachineLocation LRDst(RAReg, -4);
12953247Sarchie   MachineLocation LRSrc(RAReg);
13053247Sarchie   Moves.push_back(MachineMove(0, LRDst, LRSrc));
131117011Sru
132117011Sru   // R30 = (R30 - #8)
133131530Sru   MachineLocation SPDst(FPReg, -8);
13453939Sarchie   MachineLocation SPSrc(FPReg);
135242997Sjoel   Moves.push_back(MachineMove(0, SPDst, SPSrc));
136151798Sru }
137151798Sru
138151798Sru  //
139151798Sru  // Only insert ALLOCFRAME if we need to.
140151798Sru  //
141151798Sru  if (hasFP(MF)) {
142151798Sru    // Check for overflow.
143151798Sru    // Hexagon_TODO: Ugh! hardcoding. Is there an API that can be used?
144151798Sru    const int ALLOCFRAME_MAX = 16384;
145151798Sru    const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
146151798Sru
147151798Sru    if (NumBytes >= ALLOCFRAME_MAX) {
148151798Sru      // Emit allocframe(#0).
149151798Sru      BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(0);
150151798Sru
151242997Sjoel      // Subtract offset from frame pointer.
15253939Sarchie      BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::CONST32_Int_Real),
15377973Ssobomax                                      HEXAGON_RESERVED_REG_1).addImm(NumBytes);
154117011Sru      BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::SUB_rr),
155117011Sru                                      QRI->getStackRegister()).
156131530Sru                                      addReg(QRI->getStackRegister()).
15753939Sarchie                                      addReg(HEXAGON_RESERVED_REG_1);
158242997Sjoel    } else {
15953939Sarchie      BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(NumBytes);
16053939Sarchie    }
161117011Sru  }
162117011Sru}
163131530Sru// Returns true if MBB has a machine instructions that indicates a tail call
16453939Sarchie// in the block.
165242997Sjoelbool HexagonFrameLowering::hasTailCall(MachineBasicBlock &MBB) const {
16653939Sarchie  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
16753939Sarchie  unsigned RetOpcode = MBBI->getOpcode();
16853939Sarchie
169131530Sru  return RetOpcode == Hexagon::TCRETURNtg || RetOpcode == Hexagon::TCRETURNtext;}
170242997Sjoel
17153939Sarchievoid HexagonFrameLowering::emitEpilogue(MachineFunction &MF,
17253939Sarchie                                     MachineBasicBlock &MBB) const {
17353939Sarchie  MachineBasicBlock::iterator MBBI = prior(MBB.end());
174131530Sru  DebugLoc dl = MBBI->getDebugLoc();
17553939Sarchie  //
17653939Sarchie  // Only insert deallocframe if we need to.
17753939Sarchie  //
17853939Sarchie  if (hasFP(MF)) {
17953247Sarchie    MachineBasicBlock::iterator MBBI = prior(MBB.end());
18053939Sarchie    MachineBasicBlock::iterator MBBI_end = MBB.end();
18153939Sarchie    //
182131530Sru    // For Hexagon, we don't need the frame size.
18354927Sjulian    //
18454927Sjulian    MachineFrameInfo *MFI = MF.getFrameInfo();
18554927Sjulian    int NumBytes = (int) MFI->getStackSize();
186117011Sru
187117011Sru    const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
18853939Sarchie
18953939Sarchie    // Replace 'jumpr r31' instruction with dealloc_return for V4 and higher
19053939Sarchie    // versions.
19153939Sarchie    if (STI.hasV4TOps() && MBBI->getOpcode() == Hexagon::JMPR
19253939Sarchie                        && !DisableDeallocRet) {
193117011Sru      // Remove jumpr node.
194117011Sru      MBB.erase(MBBI);
19553939Sarchie      // Add dealloc_return.
19653939Sarchie      BuildMI(MBB, MBBI_end, dl, TII.get(Hexagon::DEALLOC_RET_V4))
19753939Sarchie        .addImm(NumBytes);
19853939Sarchie    } else { // Add deallocframe for V2 and V3.
19953939Sarchie      BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME)).addImm(NumBytes);
20053939Sarchie    }
20153939Sarchie  }
202229930Smelifaro}
20353939Sarchie
20458007Sarchiebool HexagonFrameLowering::hasFP(const MachineFunction &MF) const {
20558007Sarchie  const MachineFrameInfo *MFI = MF.getFrameInfo();
20653939Sarchie  const HexagonMachineFunctionInfo *FuncInfo =
20753939Sarchie    MF.getInfo<HexagonMachineFunctionInfo>();
20858007Sarchie  return (MFI->hasCalls() || (MFI->getStackSize() > 0) ||
20953939Sarchie          FuncInfo->hasClobberLR() );
21053939Sarchie}
21153939Sarchie
212131530Srustatic inline
21354927Sjulianunsigned uniqueSuperReg(unsigned Reg, const TargetRegisterInfo *TRI) {
21454927Sjulian  MCSuperRegIterator SRI(Reg, TRI);
215117011Sru  assert(SRI.isValid() && "Expected a superreg");
216117011Sru  unsigned SuperReg = *SRI;
21753939Sarchie  ++SRI;
218229930Smelifaro  assert(!SRI.isValid() && "Expected exactly one superreg");
219229930Smelifaro  return SuperReg;
220229930Smelifaro}
221229930Smelifaro
222229930Smelifarobool
223229930SmelifaroHexagonFrameLowering::spillCalleeSavedRegisters(
22453247Sarchie                                        MachineBasicBlock &MBB,
22553247Sarchie                                        MachineBasicBlock::iterator MI,
22653247Sarchie                                        const std::vector<CalleeSavedInfo> &CSI,
22753247Sarchie                                        const TargetRegisterInfo *TRI) const {
22853247Sarchie  MachineFunction *MF = MBB.getParent();
22953247Sarchie  const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
23053247Sarchie
23153247Sarchie  if (CSI.empty()) {
23259982Sarchie    return false;
233131108Sjulian  }
234165282Srwatson
235165282Srwatson  // We can only schedule double loads if we spill contiguous callee-saved regs
23654927Sjulian  // For instance, we cannot scheduled double-word loads if we spill r24,
23754927Sjulian  // r26, and r27.
23854927Sjulian  // Hexagon_TODO: We can try to double-word align odd registers for -O2 and
23954927Sjulian  // above.
24054927Sjulian  bool ContiguousRegs = true;
24154927Sjulian
24267627Sasmodai  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