131d157ae1ac2cd9c787dc3c1d28e64c682803844Jia Liu//===-- HexagonFrameLowering.cpp - Define frame lowering ------------------===//
2b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum//
3b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum//                     The LLVM Compiler Infrastructure
4b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum//
5b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum// This file is distributed under the University of Illinois Open Source
6b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum// License. See LICENSE.TXT for details.
7b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum//
8b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum//
9b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum//===----------------------------------------------------------------------===//
10f3fd7ee415ec8a6475a060e29959d04d6158f45fBenjamin Kramer
1179aa3417eb6f58d668aadfedf075240a41d35a26Craig Topper#include "HexagonFrameLowering.h"
12b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum#include "Hexagon.h"
13b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum#include "HexagonInstrInfo.h"
14d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "HexagonMachineFunctionInfo.h"
15b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum#include "HexagonRegisterInfo.h"
16b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum#include "HexagonSubtarget.h"
17b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum#include "HexagonTargetMachine.h"
18f3fd7ee415ec8a6475a060e29959d04d6158f45fBenjamin Kramer#include "llvm/ADT/BitVector.h"
19f3fd7ee415ec8a6475a060e29959d04d6158f45fBenjamin Kramer#include "llvm/ADT/STLExtras.h"
20b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum#include "llvm/CodeGen/AsmPrinter.h"
21d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/CodeGen/MachineFrameInfo.h"
22b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum#include "llvm/CodeGen/MachineFunction.h"
23f3fd7ee415ec8a6475a060e29959d04d6158f45fBenjamin Kramer#include "llvm/CodeGen/MachineFunctionPass.h"
24d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/CodeGen/MachineInstrBuilder.h"
25f3fd7ee415ec8a6475a060e29959d04d6158f45fBenjamin Kramer#include "llvm/CodeGen/MachineModuleInfo.h"
26b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum#include "llvm/CodeGen/MachineRegisterInfo.h"
27f3fd7ee415ec8a6475a060e29959d04d6158f45fBenjamin Kramer#include "llvm/CodeGen/RegisterScavenging.h"
280b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Function.h"
290b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Type.h"
30b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum#include "llvm/MC/MCAsmInfo.h"
31d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/MC/MachineLocation.h"
32d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Support/CommandLine.h"
33b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum#include "llvm/Target/TargetInstrInfo.h"
34b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum#include "llvm/Target/TargetMachine.h"
35b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum#include "llvm/Target/TargetOptions.h"
36b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
37b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicumusing namespace llvm;
38b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
39b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicumstatic cl::opt<bool> DisableDeallocRet(
40b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum                       "disable-hexagon-dealloc-ret",
41b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum                       cl::Hidden,
42b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum                       cl::desc("Disable Dealloc Return for Hexagon target"));
43b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
44b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum/// determineFrameLayout - Determine the size of the frame and maximum call
45b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum/// frame size.
46b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicumvoid HexagonFrameLowering::determineFrameLayout(MachineFunction &MF) const {
47b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  MachineFrameInfo *MFI = MF.getFrameInfo();
48b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
49b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // Get the number of bytes to allocate from the FrameInfo.
50b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  unsigned FrameSize = MFI->getStackSize();
51b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
52b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // Get the alignments provided by the target.
53b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  unsigned TargetAlign = MF.getTarget().getFrameLowering()->getStackAlignment();
54b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // Get the maximum call frame size of all the calls.
55b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  unsigned maxCallFrameSize = MFI->getMaxCallFrameSize();
56b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
57b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // If we have dynamic alloca then maxCallFrameSize needs to be aligned so
58b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // that allocations will be aligned.
59b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  if (MFI->hasVarSizedObjects())
60b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    maxCallFrameSize = RoundUpToAlignment(maxCallFrameSize, TargetAlign);
61b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
62b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // Update maximum call frame size.
63b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  MFI->setMaxCallFrameSize(maxCallFrameSize);
64b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
65b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // Include call frame size in total.
66b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  FrameSize += maxCallFrameSize;
67b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
68b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // Make sure the frame is aligned.
69b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  FrameSize = RoundUpToAlignment(FrameSize, TargetAlign);
70b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
71b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // Update frame info.
72b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  MFI->setStackSize(FrameSize);
73b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum}
74b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
75b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
76b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicumvoid HexagonFrameLowering::emitPrologue(MachineFunction &MF) const {
77b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  MachineBasicBlock &MBB = MF.front();
78b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  MachineFrameInfo *MFI = MF.getFrameInfo();
79b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  MachineBasicBlock::iterator MBBI = MBB.begin();
80b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  const HexagonRegisterInfo *QRI =
81b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    static_cast<const HexagonRegisterInfo *>(MF.getTarget().getRegisterInfo());
82b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
83b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  determineFrameLayout(MF);
84b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
85b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // Get the number of bytes to allocate from the FrameInfo.
86b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  int NumBytes = (int) MFI->getStackSize();
87b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
88b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // LLVM expects allocframe not to be the first instruction in the
89b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // basic block.
90b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  MachineBasicBlock::iterator InsertPt = MBB.begin();
91b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
92b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  //
93b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // ALLOCA adjust regs.  Iterate over ADJDYNALLOC nodes and change the offset.
94b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  //
95b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  HexagonMachineFunctionInfo *FuncInfo =
96b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    MF.getInfo<HexagonMachineFunctionInfo>();
97b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  const std::vector<MachineInstr*>& AdjustRegs =
98b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    FuncInfo->getAllocaAdjustInsts();
99b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  for (std::vector<MachineInstr*>::const_iterator i = AdjustRegs.begin(),
100b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum         e = AdjustRegs.end();
101b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum       i != e; ++i) {
102b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    MachineInstr* MI = *i;
103b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    assert((MI->getOpcode() == Hexagon::ADJDYNALLOC) &&
104b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum           "Expected adjust alloca node");
105b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
106b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    MachineOperand& MO = MI->getOperand(2);
107b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    assert(MO.isImm() && "Expected immediate");
108b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    MO.setImm(MFI->getMaxCallFrameSize());
109b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  }
110b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
111b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  //
112b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // Only insert ALLOCFRAME if we need to.
113b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  //
114b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  if (hasFP(MF)) {
115b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    // Check for overflow.
116b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    // Hexagon_TODO: Ugh! hardcoding. Is there an API that can be used?
11722614a02eb8855548a892139e54e478c70050f9fTony Linthicum    const int ALLOCFRAME_MAX = 16384;
118b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
119b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
120b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    if (NumBytes >= ALLOCFRAME_MAX) {
121b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum      // Emit allocframe(#0).
122b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum      BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(0);
123b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
124b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum      // Subtract offset from frame pointer.
125b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum      BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::CONST32_Int_Real),
126b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum                                      HEXAGON_RESERVED_REG_1).addImm(NumBytes);
127b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum      BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::SUB_rr),
128b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum                                      QRI->getStackRegister()).
129b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum                                      addReg(QRI->getStackRegister()).
130b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum                                      addReg(HEXAGON_RESERVED_REG_1);
131b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    } else {
132b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum      BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(NumBytes);
133b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    }
134b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  }
135b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum}
136b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum// Returns true if MBB has a machine instructions that indicates a tail call
137b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum// in the block.
138b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicumbool HexagonFrameLowering::hasTailCall(MachineBasicBlock &MBB) const {
139b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
140b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  unsigned RetOpcode = MBBI->getOpcode();
141b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
14273714eac00958b072e7356360ebc6e818b51367bMatthew Curtis  return RetOpcode == Hexagon::TCRETURNtg || RetOpcode == Hexagon::TCRETURNtext;
14373714eac00958b072e7356360ebc6e818b51367bMatthew Curtis}
144b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
145b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicumvoid HexagonFrameLowering::emitEpilogue(MachineFunction &MF,
146b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum                                     MachineBasicBlock &MBB) const {
14736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  MachineBasicBlock::iterator MBBI = std::prev(MBB.end());
148b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  DebugLoc dl = MBBI->getDebugLoc();
149b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  //
1501a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma  // Only insert deallocframe if we need to.  Also at -O0.  See comment
1511a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma  // in emitPrologue above.
152b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  //
1531a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma  if (hasFP(MF) || MF.getTarget().getOptLevel() == CodeGenOpt::None) {
15436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MachineBasicBlock::iterator MBBI = std::prev(MBB.end());
155b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    MachineBasicBlock::iterator MBBI_end = MBB.end();
156b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
157b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
1581a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma    // Handle EH_RETURN.
1591a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma    if (MBBI->getOpcode() == Hexagon::EH_RETURN_JMPR) {
160fd4ccda4a56d1664b43ca7ed9909254f6de592bbJyotsna Verma      assert(MBBI->getOperand(0).isReg() && "Offset should be in register!");
1611a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma      BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME));
1621a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma      BuildMI(MBB, MBBI, dl, TII.get(Hexagon::ADD_rr),
1631a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma              Hexagon::R29).addReg(Hexagon::R29).addReg(Hexagon::R28);
1641a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma      return;
1651a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma    }
166b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    // Replace 'jumpr r31' instruction with dealloc_return for V4 and higher
167b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    // versions.
168cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (MF.getTarget().getSubtarget<HexagonSubtarget>().hasV4TOps() &&
169cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        MBBI->getOpcode() == Hexagon::JMPret && !DisableDeallocRet) {
1701a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma      // Check for RESTORE_DEALLOC_RET_JMP_V4 call. Don't emit an extra DEALLOC
1711a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma      // instruction if we encounter it.
1721a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma      MachineBasicBlock::iterator BeforeJMPR =
17336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        MBB.begin() == MBBI ? MBBI : std::prev(MBBI);
1741a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma      if (BeforeJMPR != MBBI &&
1751a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma          BeforeJMPR->getOpcode() == Hexagon::RESTORE_DEALLOC_RET_JMP_V4) {
1761a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma        // Remove the JMPR node.
1771a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma        MBB.erase(MBBI);
1781a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma        return;
1791a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma      }
1801a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma
181b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum      // Add dealloc_return.
1821a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma      MachineInstrBuilder MIB =
1831a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma        BuildMI(MBB, MBBI_end, dl, TII.get(Hexagon::DEALLOC_RET_V4));
1841a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma      // Transfer the function live-out registers.
1851a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma      MIB->copyImplicitOps(*MBB.getParent(), &*MBBI);
1861a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma      // Remove the JUMPR node.
1871a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma      MBB.erase(MBBI);
1881a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma    } else { // Add deallocframe for V2 and V3, and V4 tail calls.
1891a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma      // Check for RESTORE_DEALLOC_BEFORE_TAILCALL_V4. We don't need an extra
1901a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma      // DEALLOCFRAME instruction after it.
1911a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma      MachineBasicBlock::iterator Term = MBB.getFirstTerminator();
1921a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma      MachineBasicBlock::iterator I =
19336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        Term == MBB.begin() ?  MBB.end() : std::prev(Term);
1941a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma      if (I != MBB.end() &&
1951a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma          I->getOpcode() == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4)
1961a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma        return;
1971a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma
1981a35b8e2eb165624013d5a2eaf8b673f026999fcJyotsna Verma      BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME));
199b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    }
200b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  }
201b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum}
202b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
203b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicumbool HexagonFrameLowering::hasFP(const MachineFunction &MF) const {
204b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  const MachineFrameInfo *MFI = MF.getFrameInfo();
205b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  const HexagonMachineFunctionInfo *FuncInfo =
206b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    MF.getInfo<HexagonMachineFunctionInfo>();
207b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  return (MFI->hasCalls() || (MFI->getStackSize() > 0) ||
208b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum          FuncInfo->hasClobberLR() );
209b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum}
210b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
2114aecc761c7c9069424630ed8dfb8cd382866dd45Jakob Stoklund Olesenstatic inline
2124aecc761c7c9069424630ed8dfb8cd382866dd45Jakob Stoklund Olesenunsigned uniqueSuperReg(unsigned Reg, const TargetRegisterInfo *TRI) {
2134aecc761c7c9069424630ed8dfb8cd382866dd45Jakob Stoklund Olesen  MCSuperRegIterator SRI(Reg, TRI);
2144aecc761c7c9069424630ed8dfb8cd382866dd45Jakob Stoklund Olesen  assert(SRI.isValid() && "Expected a superreg");
2154aecc761c7c9069424630ed8dfb8cd382866dd45Jakob Stoklund Olesen  unsigned SuperReg = *SRI;
2164aecc761c7c9069424630ed8dfb8cd382866dd45Jakob Stoklund Olesen  ++SRI;
2174aecc761c7c9069424630ed8dfb8cd382866dd45Jakob Stoklund Olesen  assert(!SRI.isValid() && "Expected exactly one superreg");
2184aecc761c7c9069424630ed8dfb8cd382866dd45Jakob Stoklund Olesen  return SuperReg;
2194aecc761c7c9069424630ed8dfb8cd382866dd45Jakob Stoklund Olesen}
2204aecc761c7c9069424630ed8dfb8cd382866dd45Jakob Stoklund Olesen
221b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicumbool
222b4b54153ad760c69a00a08531abef4ed434a5092Tony LinthicumHexagonFrameLowering::spillCalleeSavedRegisters(
223b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum                                        MachineBasicBlock &MBB,
224b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum                                        MachineBasicBlock::iterator MI,
225b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum                                        const std::vector<CalleeSavedInfo> &CSI,
226b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum                                        const TargetRegisterInfo *TRI) const {
227b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  MachineFunction *MF = MBB.getParent();
228b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
229b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
230b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  if (CSI.empty()) {
231b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    return false;
232b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  }
233b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
234b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // We can only schedule double loads if we spill contiguous callee-saved regs
235b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // For instance, we cannot scheduled double-word loads if we spill r24,
236b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // r26, and r27.
237b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // Hexagon_TODO: We can try to double-word align odd registers for -O2 and
238b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // above.
239b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  bool ContiguousRegs = true;
240b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
241b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  for (unsigned i = 0; i < CSI.size(); ++i) {
242b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    unsigned Reg = CSI[i].getReg();
243b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
244b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    //
245b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    // Check if we can use a double-word store.
246b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    //
2474aecc761c7c9069424630ed8dfb8cd382866dd45Jakob Stoklund Olesen    unsigned SuperReg = uniqueSuperReg(Reg, TRI);
248b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    bool CanUseDblStore = false;
249dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    const TargetRegisterClass* SuperRegClass = nullptr;
250b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
251b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    if (ContiguousRegs && (i < CSI.size()-1)) {
2524aecc761c7c9069424630ed8dfb8cd382866dd45Jakob Stoklund Olesen      unsigned SuperRegNext = uniqueSuperReg(CSI[i+1].getReg(), TRI);
2534aecc761c7c9069424630ed8dfb8cd382866dd45Jakob Stoklund Olesen      SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg);
2544aecc761c7c9069424630ed8dfb8cd382866dd45Jakob Stoklund Olesen      CanUseDblStore = (SuperRegNext == SuperReg);
255b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    }
256b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
257b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
258b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    if (CanUseDblStore) {
2594aecc761c7c9069424630ed8dfb8cd382866dd45Jakob Stoklund Olesen      TII.storeRegToStackSlot(MBB, MI, SuperReg, true,
260b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum                              CSI[i+1].getFrameIdx(), SuperRegClass, TRI);
2614aecc761c7c9069424630ed8dfb8cd382866dd45Jakob Stoklund Olesen      MBB.addLiveIn(SuperReg);
262b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum      ++i;
263b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    } else {
264b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum      // Cannot use a double-word store.
265b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum      ContiguousRegs = false;
266b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum      const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
267b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum      TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(), RC,
268b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum                              TRI);
269b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum      MBB.addLiveIn(Reg);
270b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    }
271b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  }
272b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  return true;
273b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum}
274b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
275b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
276b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicumbool HexagonFrameLowering::restoreCalleeSavedRegisters(
277b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum                                        MachineBasicBlock &MBB,
278b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum                                        MachineBasicBlock::iterator MI,
279b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum                                        const std::vector<CalleeSavedInfo> &CSI,
280b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum                                        const TargetRegisterInfo *TRI) const {
281b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
282b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  MachineFunction *MF = MBB.getParent();
283b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
284b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
285b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  if (CSI.empty()) {
286b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    return false;
287b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  }
288b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
289b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // We can only schedule double loads if we spill contiguous callee-saved regs
290b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // For instance, we cannot scheduled double-word loads if we spill r24,
291b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // r26, and r27.
292b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // Hexagon_TODO: We can try to double-word align odd registers for -O2 and
293b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  // above.
294b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  bool ContiguousRegs = true;
295b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
296b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  for (unsigned i = 0; i < CSI.size(); ++i) {
297b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    unsigned Reg = CSI[i].getReg();
298b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
299b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    //
300b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    // Check if we can use a double-word load.
301b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    //
3024aecc761c7c9069424630ed8dfb8cd382866dd45Jakob Stoklund Olesen    unsigned SuperReg = uniqueSuperReg(Reg, TRI);
303dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    const TargetRegisterClass* SuperRegClass = nullptr;
304b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    bool CanUseDblLoad = false;
305b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    if (ContiguousRegs && (i < CSI.size()-1)) {
3064aecc761c7c9069424630ed8dfb8cd382866dd45Jakob Stoklund Olesen      unsigned SuperRegNext = uniqueSuperReg(CSI[i+1].getReg(), TRI);
3074aecc761c7c9069424630ed8dfb8cd382866dd45Jakob Stoklund Olesen      SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg);
3084aecc761c7c9069424630ed8dfb8cd382866dd45Jakob Stoklund Olesen      CanUseDblLoad = (SuperRegNext == SuperReg);
309b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    }
310b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
311b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
312b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    if (CanUseDblLoad) {
3134aecc761c7c9069424630ed8dfb8cd382866dd45Jakob Stoklund Olesen      TII.loadRegFromStackSlot(MBB, MI, SuperReg, CSI[i+1].getFrameIdx(),
314b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum                               SuperRegClass, TRI);
3154aecc761c7c9069424630ed8dfb8cd382866dd45Jakob Stoklund Olesen      MBB.addLiveIn(SuperReg);
316b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum      ++i;
317b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    } else {
318b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum      // Cannot use a double-word load.
319b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum      ContiguousRegs = false;
320b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum      const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
321b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum      TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), RC, TRI);
322b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum      MBB.addLiveIn(Reg);
323b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum    }
324b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  }
325b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  return true;
326b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum}
327b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum
328700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Benderskyvoid HexagonFrameLowering::
329700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli BenderskyeliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
330700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky                              MachineBasicBlock::iterator I) const {
331700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky  MachineInstr &MI = *I;
332700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky
333700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky  if (MI.getOpcode() == Hexagon::ADJCALLSTACKDOWN) {
334700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky    // Hexagon_TODO: add code
335700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky  } else if (MI.getOpcode() == Hexagon::ADJCALLSTACKUP) {
336700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky    // Hexagon_TODO: add code
337700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky  } else {
338700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky    llvm_unreachable("Cannot handle this call frame pseudo instruction");
339700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky  }
340700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky  MBB.erase(I);
341700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky}
342700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky
343b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicumint HexagonFrameLowering::getFrameIndexOffset(const MachineFunction &MF,
344b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum                                              int FI) const {
345b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum  return MF.getFrameInfo()->getObjectOffset(FI);
346b4b54153ad760c69a00a08531abef4ed434a5092Tony Linthicum}
347