1239310Sdim//===-- MipsSEFrameLowering.cpp - Mips32/64 Frame Information -------------===//
2239310Sdim//
3239310Sdim//                     The LLVM Compiler Infrastructure
4239310Sdim//
5239310Sdim// This file is distributed under the University of Illinois Open Source
6239310Sdim// License. See LICENSE.TXT for details.
7239310Sdim//
8239310Sdim//===----------------------------------------------------------------------===//
9239310Sdim//
10239310Sdim// This file contains the Mips32/64 implementation of TargetFrameLowering class.
11239310Sdim//
12239310Sdim//===----------------------------------------------------------------------===//
13239310Sdim
14239310Sdim#include "MipsSEFrameLowering.h"
15249423Sdim#include "MCTargetDesc/MipsBaseInfo.h"
16239310Sdim#include "MipsAnalyzeImmediate.h"
17249423Sdim#include "MipsMachineFunction.h"
18239310Sdim#include "MipsSEInstrInfo.h"
19239310Sdim#include "llvm/CodeGen/MachineFrameInfo.h"
20239310Sdim#include "llvm/CodeGen/MachineFunction.h"
21239310Sdim#include "llvm/CodeGen/MachineInstrBuilder.h"
22239310Sdim#include "llvm/CodeGen/MachineModuleInfo.h"
23239310Sdim#include "llvm/CodeGen/MachineRegisterInfo.h"
24243830Sdim#include "llvm/CodeGen/RegisterScavenging.h"
25249423Sdim#include "llvm/IR/DataLayout.h"
26249423Sdim#include "llvm/IR/Function.h"
27249423Sdim#include "llvm/Support/CommandLine.h"
28239310Sdim#include "llvm/Target/TargetOptions.h"
29239310Sdim
30239310Sdimusing namespace llvm;
31239310Sdim
32249423Sdimnamespace {
33249423Sdimtypedef MachineBasicBlock::iterator Iter;
34249423Sdim
35251662Sdim/// Helper class to expand pseudos.
36251662Sdimclass ExpandPseudo {
37249423Sdimpublic:
38251662Sdim  ExpandPseudo(MachineFunction &MF);
39249423Sdim  bool expand();
40249423Sdim
41249423Sdimprivate:
42249423Sdim  bool expandInstr(MachineBasicBlock &MBB, Iter I);
43251662Sdim  void expandLoadCCond(MachineBasicBlock &MBB, Iter I);
44251662Sdim  void expandStoreCCond(MachineBasicBlock &MBB, Iter I);
45251662Sdim  void expandLoadACC(MachineBasicBlock &MBB, Iter I, unsigned RegSize);
46251662Sdim  void expandStoreACC(MachineBasicBlock &MBB, Iter I, unsigned RegSize);
47251662Sdim  bool expandCopy(MachineBasicBlock &MBB, Iter I);
48251662Sdim  bool expandCopyACC(MachineBasicBlock &MBB, Iter I, unsigned Dst,
49251662Sdim                     unsigned Src, unsigned RegSize);
50249423Sdim
51249423Sdim  MachineFunction &MF;
52249423Sdim  const MipsSEInstrInfo &TII;
53249423Sdim  const MipsRegisterInfo &RegInfo;
54249423Sdim  MachineRegisterInfo &MRI;
55249423Sdim};
56249423Sdim}
57249423Sdim
58251662SdimExpandPseudo::ExpandPseudo(MachineFunction &MF_)
59249423Sdim  : MF(MF_),
60249423Sdim    TII(*static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo())),
61249423Sdim    RegInfo(TII.getRegisterInfo()), MRI(MF.getRegInfo()) {}
62249423Sdim
63251662Sdimbool ExpandPseudo::expand() {
64249423Sdim  bool Expanded = false;
65249423Sdim
66249423Sdim  for (MachineFunction::iterator BB = MF.begin(), BBEnd = MF.end();
67249423Sdim       BB != BBEnd; ++BB)
68249423Sdim    for (Iter I = BB->begin(), End = BB->end(); I != End;)
69249423Sdim      Expanded |= expandInstr(*BB, I++);
70249423Sdim
71249423Sdim  return Expanded;
72249423Sdim}
73249423Sdim
74251662Sdimbool ExpandPseudo::expandInstr(MachineBasicBlock &MBB, Iter I) {
75249423Sdim  switch(I->getOpcode()) {
76251662Sdim  case Mips::LOAD_CCOND_DSP:
77251662Sdim  case Mips::LOAD_CCOND_DSP_P8:
78251662Sdim    expandLoadCCond(MBB, I);
79251662Sdim    break;
80251662Sdim  case Mips::STORE_CCOND_DSP:
81251662Sdim  case Mips::STORE_CCOND_DSP_P8:
82251662Sdim    expandStoreCCond(MBB, I);
83251662Sdim    break;
84249423Sdim  case Mips::LOAD_AC64:
85249423Sdim  case Mips::LOAD_AC64_P8:
86249423Sdim  case Mips::LOAD_AC_DSP:
87249423Sdim  case Mips::LOAD_AC_DSP_P8:
88251662Sdim    expandLoadACC(MBB, I, 4);
89249423Sdim    break;
90249423Sdim  case Mips::LOAD_AC128:
91249423Sdim  case Mips::LOAD_AC128_P8:
92251662Sdim    expandLoadACC(MBB, I, 8);
93249423Sdim    break;
94249423Sdim  case Mips::STORE_AC64:
95249423Sdim  case Mips::STORE_AC64_P8:
96249423Sdim  case Mips::STORE_AC_DSP:
97249423Sdim  case Mips::STORE_AC_DSP_P8:
98251662Sdim    expandStoreACC(MBB, I, 4);
99249423Sdim    break;
100249423Sdim  case Mips::STORE_AC128:
101249423Sdim  case Mips::STORE_AC128_P8:
102251662Sdim    expandStoreACC(MBB, I, 8);
103249423Sdim    break;
104251662Sdim  case TargetOpcode::COPY:
105251662Sdim    if (!expandCopy(MBB, I))
106251662Sdim      return false;
107249423Sdim    break;
108249423Sdim  default:
109249423Sdim    return false;
110249423Sdim  }
111249423Sdim
112249423Sdim  MBB.erase(I);
113249423Sdim  return true;
114249423Sdim}
115249423Sdim
116251662Sdimvoid ExpandPseudo::expandLoadCCond(MachineBasicBlock &MBB, Iter I) {
117251662Sdim  //  load $vr, FI
118251662Sdim  //  copy ccond, $vr
119251662Sdim
120251662Sdim  assert(I->getOperand(0).isReg() && I->getOperand(1).isFI());
121251662Sdim
122251662Sdim  const TargetRegisterClass *RC = RegInfo.intRegClass(4);
123251662Sdim  unsigned VR = MRI.createVirtualRegister(RC);
124251662Sdim  unsigned Dst = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex();
125251662Sdim
126251662Sdim  TII.loadRegFromStack(MBB, I, VR, FI, RC, &RegInfo, 0);
127251662Sdim  BuildMI(MBB, I, I->getDebugLoc(), TII.get(TargetOpcode::COPY), Dst)
128251662Sdim    .addReg(VR, RegState::Kill);
129251662Sdim}
130251662Sdim
131251662Sdimvoid ExpandPseudo::expandStoreCCond(MachineBasicBlock &MBB, Iter I) {
132251662Sdim  //  copy $vr, ccond
133251662Sdim  //  store $vr, FI
134251662Sdim
135251662Sdim  assert(I->getOperand(0).isReg() && I->getOperand(1).isFI());
136251662Sdim
137251662Sdim  const TargetRegisterClass *RC = RegInfo.intRegClass(4);
138251662Sdim  unsigned VR = MRI.createVirtualRegister(RC);
139251662Sdim  unsigned Src = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex();
140251662Sdim
141251662Sdim  BuildMI(MBB, I, I->getDebugLoc(), TII.get(TargetOpcode::COPY), VR)
142251662Sdim    .addReg(Src, getKillRegState(I->getOperand(0).isKill()));
143251662Sdim  TII.storeRegToStack(MBB, I, VR, true, FI, RC, &RegInfo, 0);
144251662Sdim}
145251662Sdim
146251662Sdimvoid ExpandPseudo::expandLoadACC(MachineBasicBlock &MBB, Iter I,
147249423Sdim                                 unsigned RegSize) {
148249423Sdim  //  load $vr0, FI
149249423Sdim  //  copy lo, $vr0
150249423Sdim  //  load $vr1, FI + 4
151249423Sdim  //  copy hi, $vr1
152249423Sdim
153249423Sdim  assert(I->getOperand(0).isReg() && I->getOperand(1).isFI());
154249423Sdim
155249423Sdim  const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize);
156249423Sdim  unsigned VR0 = MRI.createVirtualRegister(RC);
157249423Sdim  unsigned VR1 = MRI.createVirtualRegister(RC);
158249423Sdim  unsigned Dst = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex();
159249423Sdim  unsigned Lo = RegInfo.getSubReg(Dst, Mips::sub_lo);
160249423Sdim  unsigned Hi = RegInfo.getSubReg(Dst, Mips::sub_hi);
161249423Sdim  DebugLoc DL = I->getDebugLoc();
162249423Sdim  const MCInstrDesc &Desc = TII.get(TargetOpcode::COPY);
163249423Sdim
164249423Sdim  TII.loadRegFromStack(MBB, I, VR0, FI, RC, &RegInfo, 0);
165249423Sdim  BuildMI(MBB, I, DL, Desc, Lo).addReg(VR0, RegState::Kill);
166249423Sdim  TII.loadRegFromStack(MBB, I, VR1, FI, RC, &RegInfo, RegSize);
167249423Sdim  BuildMI(MBB, I, DL, Desc, Hi).addReg(VR1, RegState::Kill);
168249423Sdim}
169249423Sdim
170251662Sdimvoid ExpandPseudo::expandStoreACC(MachineBasicBlock &MBB, Iter I,
171249423Sdim                                  unsigned RegSize) {
172249423Sdim  //  copy $vr0, lo
173249423Sdim  //  store $vr0, FI
174249423Sdim  //  copy $vr1, hi
175249423Sdim  //  store $vr1, FI + 4
176249423Sdim
177249423Sdim  assert(I->getOperand(0).isReg() && I->getOperand(1).isFI());
178249423Sdim
179249423Sdim  const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize);
180249423Sdim  unsigned VR0 = MRI.createVirtualRegister(RC);
181249423Sdim  unsigned VR1 = MRI.createVirtualRegister(RC);
182249423Sdim  unsigned Src = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex();
183249423Sdim  unsigned SrcKill = getKillRegState(I->getOperand(0).isKill());
184249423Sdim  unsigned Lo = RegInfo.getSubReg(Src, Mips::sub_lo);
185249423Sdim  unsigned Hi = RegInfo.getSubReg(Src, Mips::sub_hi);
186249423Sdim  DebugLoc DL = I->getDebugLoc();
187249423Sdim
188249423Sdim  BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), VR0).addReg(Lo, SrcKill);
189249423Sdim  TII.storeRegToStack(MBB, I, VR0, true, FI, RC, &RegInfo, 0);
190249423Sdim  BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), VR1).addReg(Hi, SrcKill);
191249423Sdim  TII.storeRegToStack(MBB, I, VR1, true, FI, RC, &RegInfo, RegSize);
192249423Sdim}
193249423Sdim
194251662Sdimbool ExpandPseudo::expandCopy(MachineBasicBlock &MBB, Iter I) {
195251662Sdim  unsigned Dst = I->getOperand(0).getReg(), Src = I->getOperand(1).getReg();
196251662Sdim
197251662Sdim  if (Mips::ACRegsDSPRegClass.contains(Dst, Src))
198251662Sdim    return expandCopyACC(MBB, I, Dst, Src, 4);
199251662Sdim
200251662Sdim  if (Mips::ACRegs128RegClass.contains(Dst, Src))
201251662Sdim    return expandCopyACC(MBB, I, Dst, Src, 8);
202251662Sdim
203251662Sdim  return false;
204251662Sdim}
205251662Sdim
206251662Sdimbool ExpandPseudo::expandCopyACC(MachineBasicBlock &MBB, Iter I, unsigned Dst,
207251662Sdim                                 unsigned Src, unsigned RegSize) {
208249423Sdim  //  copy $vr0, src_lo
209249423Sdim  //  copy dst_lo, $vr0
210249423Sdim  //  copy $vr1, src_hi
211249423Sdim  //  copy dst_hi, $vr1
212249423Sdim
213249423Sdim  const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize);
214249423Sdim  unsigned VR0 = MRI.createVirtualRegister(RC);
215249423Sdim  unsigned VR1 = MRI.createVirtualRegister(RC);
216249423Sdim  unsigned SrcKill = getKillRegState(I->getOperand(1).isKill());
217249423Sdim  unsigned DstLo = RegInfo.getSubReg(Dst, Mips::sub_lo);
218249423Sdim  unsigned DstHi = RegInfo.getSubReg(Dst, Mips::sub_hi);
219249423Sdim  unsigned SrcLo = RegInfo.getSubReg(Src, Mips::sub_lo);
220249423Sdim  unsigned SrcHi = RegInfo.getSubReg(Src, Mips::sub_hi);
221249423Sdim  DebugLoc DL = I->getDebugLoc();
222249423Sdim
223249423Sdim  BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), VR0).addReg(SrcLo, SrcKill);
224249423Sdim  BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), DstLo)
225249423Sdim    .addReg(VR0, RegState::Kill);
226249423Sdim  BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), VR1).addReg(SrcHi, SrcKill);
227249423Sdim  BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), DstHi)
228249423Sdim    .addReg(VR1, RegState::Kill);
229251662Sdim  return true;
230249423Sdim}
231249423Sdim
232249423Sdimunsigned MipsSEFrameLowering::ehDataReg(unsigned I) const {
233249423Sdim  static const unsigned EhDataReg[] = {
234249423Sdim    Mips::A0, Mips::A1, Mips::A2, Mips::A3
235249423Sdim  };
236249423Sdim  static const unsigned EhDataReg64[] = {
237249423Sdim    Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64
238249423Sdim  };
239249423Sdim
240249423Sdim  return STI.isABI_N64() ? EhDataReg64[I] : EhDataReg[I];
241249423Sdim}
242249423Sdim
243239310Sdimvoid MipsSEFrameLowering::emitPrologue(MachineFunction &MF) const {
244239310Sdim  MachineBasicBlock &MBB   = MF.front();
245239310Sdim  MachineFrameInfo *MFI    = MF.getFrameInfo();
246249423Sdim  MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
247239310Sdim  const MipsRegisterInfo *RegInfo =
248239310Sdim    static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo());
249239310Sdim  const MipsSEInstrInfo &TII =
250239310Sdim    *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo());
251239310Sdim  MachineBasicBlock::iterator MBBI = MBB.begin();
252239310Sdim  DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
253239310Sdim  unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP;
254239310Sdim  unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
255239310Sdim  unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO;
256239310Sdim  unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu;
257239310Sdim
258239310Sdim  // First, compute final stack size.
259239310Sdim  uint64_t StackSize = MFI->getStackSize();
260239310Sdim
261239310Sdim  // No need to allocate space on the stack.
262239310Sdim  if (StackSize == 0 && !MFI->adjustsStack()) return;
263239310Sdim
264239310Sdim  MachineModuleInfo &MMI = MF.getMMI();
265239310Sdim  std::vector<MachineMove> &Moves = MMI.getFrameMoves();
266239310Sdim  MachineLocation DstML, SrcML;
267239310Sdim
268239310Sdim  // Adjust stack.
269239310Sdim  TII.adjustStackPtr(SP, -StackSize, MBB, MBBI);
270239310Sdim
271239310Sdim  // emit ".cfi_def_cfa_offset StackSize"
272239310Sdim  MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol();
273239310Sdim  BuildMI(MBB, MBBI, dl,
274239310Sdim          TII.get(TargetOpcode::PROLOG_LABEL)).addSym(AdjustSPLabel);
275239310Sdim  DstML = MachineLocation(MachineLocation::VirtualFP);
276239310Sdim  SrcML = MachineLocation(MachineLocation::VirtualFP, -StackSize);
277239310Sdim  Moves.push_back(MachineMove(AdjustSPLabel, DstML, SrcML));
278239310Sdim
279239310Sdim  const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
280239310Sdim
281239310Sdim  if (CSI.size()) {
282239310Sdim    // Find the instruction past the last instruction that saves a callee-saved
283239310Sdim    // register to the stack.
284239310Sdim    for (unsigned i = 0; i < CSI.size(); ++i)
285239310Sdim      ++MBBI;
286239310Sdim
287239310Sdim    // Iterate over list of callee-saved registers and emit .cfi_offset
288239310Sdim    // directives.
289239310Sdim    MCSymbol *CSLabel = MMI.getContext().CreateTempSymbol();
290239310Sdim    BuildMI(MBB, MBBI, dl,
291239310Sdim            TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel);
292239310Sdim
293239310Sdim    for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(),
294239310Sdim           E = CSI.end(); I != E; ++I) {
295239310Sdim      int64_t Offset = MFI->getObjectOffset(I->getFrameIdx());
296239310Sdim      unsigned Reg = I->getReg();
297239310Sdim
298239310Sdim      // If Reg is a double precision register, emit two cfa_offsets,
299239310Sdim      // one for each of the paired single precision registers.
300239310Sdim      if (Mips::AFGR64RegClass.contains(Reg)) {
301239310Sdim        MachineLocation DstML0(MachineLocation::VirtualFP, Offset);
302239310Sdim        MachineLocation DstML1(MachineLocation::VirtualFP, Offset + 4);
303239310Sdim        MachineLocation SrcML0(RegInfo->getSubReg(Reg, Mips::sub_fpeven));
304239310Sdim        MachineLocation SrcML1(RegInfo->getSubReg(Reg, Mips::sub_fpodd));
305239310Sdim
306239310Sdim        if (!STI.isLittle())
307239310Sdim          std::swap(SrcML0, SrcML1);
308239310Sdim
309239310Sdim        Moves.push_back(MachineMove(CSLabel, DstML0, SrcML0));
310239310Sdim        Moves.push_back(MachineMove(CSLabel, DstML1, SrcML1));
311239310Sdim      } else {
312239310Sdim        // Reg is either in CPURegs or FGR32.
313239310Sdim        DstML = MachineLocation(MachineLocation::VirtualFP, Offset);
314239310Sdim        SrcML = MachineLocation(Reg);
315239310Sdim        Moves.push_back(MachineMove(CSLabel, DstML, SrcML));
316239310Sdim      }
317239310Sdim    }
318239310Sdim  }
319239310Sdim
320249423Sdim  if (MipsFI->callsEhReturn()) {
321249423Sdim    const TargetRegisterClass *RC = STI.isABI_N64() ?
322249423Sdim        &Mips::CPU64RegsRegClass : &Mips::CPURegsRegClass;
323249423Sdim
324249423Sdim    // Insert instructions that spill eh data registers.
325249423Sdim    for (int I = 0; I < 4; ++I) {
326249423Sdim      if (!MBB.isLiveIn(ehDataReg(I)))
327249423Sdim        MBB.addLiveIn(ehDataReg(I));
328249423Sdim      TII.storeRegToStackSlot(MBB, MBBI, ehDataReg(I), false,
329249423Sdim                              MipsFI->getEhDataRegFI(I), RC, RegInfo);
330249423Sdim    }
331249423Sdim
332249423Sdim    // Emit .cfi_offset directives for eh data registers.
333249423Sdim    MCSymbol *CSLabel2 = MMI.getContext().CreateTempSymbol();
334249423Sdim    BuildMI(MBB, MBBI, dl,
335249423Sdim            TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel2);
336249423Sdim    for (int I = 0; I < 4; ++I) {
337249423Sdim      int64_t Offset = MFI->getObjectOffset(MipsFI->getEhDataRegFI(I));
338249423Sdim      DstML = MachineLocation(MachineLocation::VirtualFP, Offset);
339249423Sdim      SrcML = MachineLocation(ehDataReg(I));
340249423Sdim      Moves.push_back(MachineMove(CSLabel2, DstML, SrcML));
341249423Sdim    }
342249423Sdim  }
343249423Sdim
344239310Sdim  // if framepointer enabled, set it to point to the stack pointer.
345239310Sdim  if (hasFP(MF)) {
346239310Sdim    // Insert instruction "move $fp, $sp" at this location.
347239310Sdim    BuildMI(MBB, MBBI, dl, TII.get(ADDu), FP).addReg(SP).addReg(ZERO);
348239310Sdim
349239310Sdim    // emit ".cfi_def_cfa_register $fp"
350239310Sdim    MCSymbol *SetFPLabel = MMI.getContext().CreateTempSymbol();
351239310Sdim    BuildMI(MBB, MBBI, dl,
352239310Sdim            TII.get(TargetOpcode::PROLOG_LABEL)).addSym(SetFPLabel);
353239310Sdim    DstML = MachineLocation(FP);
354239310Sdim    SrcML = MachineLocation(MachineLocation::VirtualFP);
355239310Sdim    Moves.push_back(MachineMove(SetFPLabel, DstML, SrcML));
356239310Sdim  }
357239310Sdim}
358239310Sdim
359239310Sdimvoid MipsSEFrameLowering::emitEpilogue(MachineFunction &MF,
360239310Sdim                                       MachineBasicBlock &MBB) const {
361239310Sdim  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
362239310Sdim  MachineFrameInfo *MFI            = MF.getFrameInfo();
363249423Sdim  MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
364249423Sdim  const MipsRegisterInfo *RegInfo =
365249423Sdim    static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo());
366239310Sdim  const MipsSEInstrInfo &TII =
367239310Sdim    *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo());
368239310Sdim  DebugLoc dl = MBBI->getDebugLoc();
369239310Sdim  unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP;
370239310Sdim  unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
371239310Sdim  unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO;
372239310Sdim  unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu;
373239310Sdim
374239310Sdim  // if framepointer enabled, restore the stack pointer.
375239310Sdim  if (hasFP(MF)) {
376239310Sdim    // Find the first instruction that restores a callee-saved register.
377239310Sdim    MachineBasicBlock::iterator I = MBBI;
378239310Sdim
379239310Sdim    for (unsigned i = 0; i < MFI->getCalleeSavedInfo().size(); ++i)
380239310Sdim      --I;
381239310Sdim
382239310Sdim    // Insert instruction "move $sp, $fp" at this location.
383239310Sdim    BuildMI(MBB, I, dl, TII.get(ADDu), SP).addReg(FP).addReg(ZERO);
384239310Sdim  }
385239310Sdim
386249423Sdim  if (MipsFI->callsEhReturn()) {
387249423Sdim    const TargetRegisterClass *RC = STI.isABI_N64() ?
388249423Sdim        &Mips::CPU64RegsRegClass : &Mips::CPURegsRegClass;
389249423Sdim
390249423Sdim    // Find first instruction that restores a callee-saved register.
391249423Sdim    MachineBasicBlock::iterator I = MBBI;
392249423Sdim    for (unsigned i = 0; i < MFI->getCalleeSavedInfo().size(); ++i)
393249423Sdim      --I;
394249423Sdim
395249423Sdim    // Insert instructions that restore eh data registers.
396249423Sdim    for (int J = 0; J < 4; ++J) {
397249423Sdim      TII.loadRegFromStackSlot(MBB, I, ehDataReg(J), MipsFI->getEhDataRegFI(J),
398249423Sdim                               RC, RegInfo);
399249423Sdim    }
400249423Sdim  }
401249423Sdim
402239310Sdim  // Get the number of bytes from FrameInfo
403239310Sdim  uint64_t StackSize = MFI->getStackSize();
404239310Sdim
405239310Sdim  if (!StackSize)
406239310Sdim    return;
407239310Sdim
408239310Sdim  // Adjust stack.
409239310Sdim  TII.adjustStackPtr(SP, StackSize, MBB, MBBI);
410239310Sdim}
411239310Sdim
412239310Sdimbool MipsSEFrameLowering::
413239310SdimspillCalleeSavedRegisters(MachineBasicBlock &MBB,
414239310Sdim                          MachineBasicBlock::iterator MI,
415239310Sdim                          const std::vector<CalleeSavedInfo> &CSI,
416239310Sdim                          const TargetRegisterInfo *TRI) const {
417239310Sdim  MachineFunction *MF = MBB.getParent();
418239310Sdim  MachineBasicBlock *EntryBlock = MF->begin();
419239310Sdim  const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
420239310Sdim
421239310Sdim  for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
422239310Sdim    // Add the callee-saved register as live-in. Do not add if the register is
423239310Sdim    // RA and return address is taken, because it has already been added in
424239310Sdim    // method MipsTargetLowering::LowerRETURNADDR.
425239310Sdim    // It's killed at the spill, unless the register is RA and return address
426239310Sdim    // is taken.
427239310Sdim    unsigned Reg = CSI[i].getReg();
428239310Sdim    bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA || Reg == Mips::RA_64)
429239310Sdim        && MF->getFrameInfo()->isReturnAddressTaken();
430239310Sdim    if (!IsRAAndRetAddrIsTaken)
431239310Sdim      EntryBlock->addLiveIn(Reg);
432239310Sdim
433239310Sdim    // Insert the spill to the stack frame.
434239310Sdim    bool IsKill = !IsRAAndRetAddrIsTaken;
435239310Sdim    const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
436239310Sdim    TII.storeRegToStackSlot(*EntryBlock, MI, Reg, IsKill,
437239310Sdim                            CSI[i].getFrameIdx(), RC, TRI);
438239310Sdim  }
439239310Sdim
440239310Sdim  return true;
441239310Sdim}
442239310Sdim
443239310Sdimbool
444239310SdimMipsSEFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
445239310Sdim  const MachineFrameInfo *MFI = MF.getFrameInfo();
446239310Sdim
447239310Sdim  // Reserve call frame if the size of the maximum call frame fits into 16-bit
448239310Sdim  // immediate field and there are no variable sized objects on the stack.
449249423Sdim  // Make sure the second register scavenger spill slot can be accessed with one
450249423Sdim  // instruction.
451249423Sdim  return isInt<16>(MFI->getMaxCallFrameSize() + getStackAlignment()) &&
452249423Sdim    !MFI->hasVarSizedObjects();
453239310Sdim}
454239310Sdim
455249423Sdim// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions
456239310Sdimvoid MipsSEFrameLowering::
457249423SdimeliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
458249423Sdim                              MachineBasicBlock::iterator I) const {
459249423Sdim  const MipsSEInstrInfo &TII =
460249423Sdim    *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo());
461249423Sdim
462249423Sdim  if (!hasReservedCallFrame(MF)) {
463249423Sdim    int64_t Amount = I->getOperand(0).getImm();
464249423Sdim
465249423Sdim    if (I->getOpcode() == Mips::ADJCALLSTACKDOWN)
466249423Sdim      Amount = -Amount;
467249423Sdim
468249423Sdim    unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP;
469249423Sdim    TII.adjustStackPtr(SP, Amount, MBB, I);
470249423Sdim  }
471249423Sdim
472249423Sdim  MBB.erase(I);
473249423Sdim}
474249423Sdim
475249423Sdimvoid MipsSEFrameLowering::
476239310SdimprocessFunctionBeforeCalleeSavedScan(MachineFunction &MF,
477239310Sdim                                     RegScavenger *RS) const {
478239310Sdim  MachineRegisterInfo &MRI = MF.getRegInfo();
479249423Sdim  MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
480239310Sdim  unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
481239310Sdim
482239310Sdim  // Mark $fp as used if function has dedicated frame pointer.
483239310Sdim  if (hasFP(MF))
484239310Sdim    MRI.setPhysRegUsed(FP);
485243830Sdim
486249423Sdim  // Create spill slots for eh data registers if function calls eh_return.
487249423Sdim  if (MipsFI->callsEhReturn())
488249423Sdim    MipsFI->createEhDataRegsFI();
489249423Sdim
490249423Sdim  // Expand pseudo instructions which load, store or copy accumulators.
491249423Sdim  // Add an emergency spill slot if a pseudo was expanded.
492251662Sdim  if (ExpandPseudo(MF).expand()) {
493249423Sdim    // The spill slot should be half the size of the accumulator. If target is
494249423Sdim    // mips64, it should be 64-bit, otherwise it should be 32-bt.
495249423Sdim    const TargetRegisterClass *RC = STI.hasMips64() ?
496249423Sdim      &Mips::CPU64RegsRegClass : &Mips::CPURegsRegClass;
497249423Sdim    int FI = MF.getFrameInfo()->CreateStackObject(RC->getSize(),
498249423Sdim                                                  RC->getAlignment(), false);
499249423Sdim    RS->addScavengingFrameIndex(FI);
500249423Sdim  }
501249423Sdim
502243830Sdim  // Set scavenging frame index if necessary.
503243830Sdim  uint64_t MaxSPOffset = MF.getInfo<MipsFunctionInfo>()->getIncomingArgSize() +
504243830Sdim    estimateStackSize(MF);
505243830Sdim
506243830Sdim  if (isInt<16>(MaxSPOffset))
507243830Sdim    return;
508243830Sdim
509243830Sdim  const TargetRegisterClass *RC = STI.isABI_N64() ?
510243830Sdim    &Mips::CPU64RegsRegClass : &Mips::CPURegsRegClass;
511243830Sdim  int FI = MF.getFrameInfo()->CreateStackObject(RC->getSize(),
512243830Sdim                                                RC->getAlignment(), false);
513249423Sdim  RS->addScavengingFrameIndex(FI);
514239310Sdim}
515239310Sdim
516239310Sdimconst MipsFrameLowering *
517239310Sdimllvm::createMipsSEFrameLowering(const MipsSubtarget &ST) {
518239310Sdim  return new MipsSEFrameLowering(ST);
519239310Sdim}
520