1//===-- SPUTargetMachine.cpp - Define TargetMachine for Cell SPU ----------===//
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// Top-level implementation for the Cell SPU target.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SPU.h"
15#include "SPUFrameLowering.h"
16#include "SPUInstrBuilder.h"
17#include "SPUInstrInfo.h"
18#include "llvm/Function.h"
19#include "llvm/CodeGen/MachineFrameInfo.h"
20#include "llvm/CodeGen/MachineFunction.h"
21#include "llvm/CodeGen/MachineInstrBuilder.h"
22#include "llvm/CodeGen/MachineModuleInfo.h"
23#include "llvm/CodeGen/MachineRegisterInfo.h"
24#include "llvm/CodeGen/RegisterScavenging.h"
25#include "llvm/Target/TargetData.h"
26#include "llvm/Target/TargetOptions.h"
27#include "llvm/Support/CommandLine.h"
28using namespace llvm;
29
30//===----------------------------------------------------------------------===//
31// SPUFrameLowering:
32//===----------------------------------------------------------------------===//
33
34SPUFrameLowering::SPUFrameLowering(const SPUSubtarget &sti)
35  : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 16, 0),
36    Subtarget(sti) {
37  LR[0].first = SPU::R0;
38  LR[0].second = 16;
39}
40
41
42//--------------------------------------------------------------------------
43// hasFP - Return true if the specified function actually has a dedicated frame
44// pointer register.  This is true if the function needs a frame pointer and has
45// a non-zero stack size.
46bool SPUFrameLowering::hasFP(const MachineFunction &MF) const {
47  const MachineFrameInfo *MFI = MF.getFrameInfo();
48
49  return MFI->getStackSize() &&
50    (DisableFramePointerElim(MF) || MFI->hasVarSizedObjects());
51}
52
53
54/// determineFrameLayout - Determine the size of the frame and maximum call
55/// frame size.
56void SPUFrameLowering::determineFrameLayout(MachineFunction &MF) const {
57  MachineFrameInfo *MFI = MF.getFrameInfo();
58
59  // Get the number of bytes to allocate from the FrameInfo
60  unsigned FrameSize = MFI->getStackSize();
61
62  // Get the alignments provided by the target, and the maximum alignment
63  // (if any) of the fixed frame objects.
64  unsigned TargetAlign = getStackAlignment();
65  unsigned Align = std::max(TargetAlign, MFI->getMaxAlignment());
66  assert(isPowerOf2_32(Align) && "Alignment is not power of 2");
67  unsigned AlignMask = Align - 1;
68
69  // Get the maximum call frame size of all the calls.
70  unsigned maxCallFrameSize = MFI->getMaxCallFrameSize();
71
72  // If we have dynamic alloca then maxCallFrameSize needs to be aligned so
73  // that allocations will be aligned.
74  if (MFI->hasVarSizedObjects())
75    maxCallFrameSize = (maxCallFrameSize + AlignMask) & ~AlignMask;
76
77  // Update maximum call frame size.
78  MFI->setMaxCallFrameSize(maxCallFrameSize);
79
80  // Include call frame size in total.
81  FrameSize += maxCallFrameSize;
82
83  // Make sure the frame is aligned.
84  FrameSize = (FrameSize + AlignMask) & ~AlignMask;
85
86  // Update frame info.
87  MFI->setStackSize(FrameSize);
88}
89
90void SPUFrameLowering::emitPrologue(MachineFunction &MF) const {
91  MachineBasicBlock &MBB = MF.front();   // Prolog goes in entry BB
92  MachineBasicBlock::iterator MBBI = MBB.begin();
93  MachineFrameInfo *MFI = MF.getFrameInfo();
94  const SPUInstrInfo &TII =
95    *static_cast<const SPUInstrInfo*>(MF.getTarget().getInstrInfo());
96  MachineModuleInfo &MMI = MF.getMMI();
97  DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
98
99  // Prepare for debug frame info.
100  bool hasDebugInfo = MMI.hasDebugInfo();
101  MCSymbol *FrameLabel = 0;
102
103  // Move MBBI back to the beginning of the function.
104  MBBI = MBB.begin();
105
106  // Work out frame sizes.
107  determineFrameLayout(MF);
108  int FrameSize = MFI->getStackSize();
109
110  assert((FrameSize & 0xf) == 0
111         && "SPURegisterInfo::emitPrologue: FrameSize not aligned");
112
113  // the "empty" frame size is 16 - just the register scavenger spill slot
114  if (FrameSize > 16 || MFI->adjustsStack()) {
115    FrameSize = -(FrameSize + SPUFrameLowering::minStackSize());
116    if (hasDebugInfo) {
117      // Mark effective beginning of when frame pointer becomes valid.
118      FrameLabel = MMI.getContext().CreateTempSymbol();
119      BuildMI(MBB, MBBI, dl, TII.get(SPU::PROLOG_LABEL)).addSym(FrameLabel);
120    }
121
122    // Adjust stack pointer, spilling $lr -> 16($sp) and $sp -> -FrameSize($sp)
123    // for the ABI
124    BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr32), SPU::R0).addImm(16)
125      .addReg(SPU::R1);
126    if (isInt<10>(FrameSize)) {
127      // Spill $sp to adjusted $sp
128      BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr32), SPU::R1).addImm(FrameSize)
129        .addReg(SPU::R1);
130      // Adjust $sp by required amout
131      BuildMI(MBB, MBBI, dl, TII.get(SPU::AIr32), SPU::R1).addReg(SPU::R1)
132        .addImm(FrameSize);
133    } else if (isInt<16>(FrameSize)) {
134      // Frame size can be loaded into ILr32n, so temporarily spill $r2 and use
135      // $r2 to adjust $sp:
136      BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr128), SPU::R2)
137        .addImm(-16)
138        .addReg(SPU::R1);
139      BuildMI(MBB, MBBI, dl, TII.get(SPU::ILr32), SPU::R2)
140        .addImm(FrameSize);
141      BuildMI(MBB, MBBI, dl, TII.get(SPU::STQXr32), SPU::R1)
142        .addReg(SPU::R2)
143        .addReg(SPU::R1);
144      BuildMI(MBB, MBBI, dl, TII.get(SPU::Ar32), SPU::R1)
145        .addReg(SPU::R1)
146        .addReg(SPU::R2);
147      BuildMI(MBB, MBBI, dl, TII.get(SPU::SFIr32), SPU::R2)
148        .addReg(SPU::R2)
149        .addImm(16);
150      BuildMI(MBB, MBBI, dl, TII.get(SPU::LQXr128), SPU::R2)
151        .addReg(SPU::R2)
152        .addReg(SPU::R1);
153    } else {
154      report_fatal_error("Unhandled frame size: " + Twine(FrameSize));
155    }
156
157    if (hasDebugInfo) {
158      std::vector<MachineMove> &Moves = MMI.getFrameMoves();
159
160      // Show update of SP.
161      MachineLocation SPDst(MachineLocation::VirtualFP);
162      MachineLocation SPSrc(MachineLocation::VirtualFP, -FrameSize);
163      Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc));
164
165      // Add callee saved registers to move list.
166      const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
167      for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
168        int Offset = MFI->getObjectOffset(CSI[I].getFrameIdx());
169        unsigned Reg = CSI[I].getReg();
170        if (Reg == SPU::R0) continue;
171        MachineLocation CSDst(MachineLocation::VirtualFP, Offset);
172        MachineLocation CSSrc(Reg);
173        Moves.push_back(MachineMove(FrameLabel, CSDst, CSSrc));
174      }
175
176      // Mark effective beginning of when frame pointer is ready.
177      MCSymbol *ReadyLabel = MMI.getContext().CreateTempSymbol();
178      BuildMI(MBB, MBBI, dl, TII.get(SPU::PROLOG_LABEL)).addSym(ReadyLabel);
179
180      MachineLocation FPDst(SPU::R1);
181      MachineLocation FPSrc(MachineLocation::VirtualFP);
182      Moves.push_back(MachineMove(ReadyLabel, FPDst, FPSrc));
183    }
184  }
185}
186
187void SPUFrameLowering::emitEpilogue(MachineFunction &MF,
188                                MachineBasicBlock &MBB) const {
189  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
190  const SPUInstrInfo &TII =
191    *static_cast<const SPUInstrInfo*>(MF.getTarget().getInstrInfo());
192  const MachineFrameInfo *MFI = MF.getFrameInfo();
193  int FrameSize = MFI->getStackSize();
194  int LinkSlotOffset = SPUFrameLowering::stackSlotSize();
195  DebugLoc dl = MBBI->getDebugLoc();
196
197  assert(MBBI->getOpcode() == SPU::RET &&
198         "Can only insert epilog into returning blocks");
199  assert((FrameSize & 0xf) == 0 && "FrameSize not aligned");
200
201  // the "empty" frame size is 16 - just the register scavenger spill slot
202  if (FrameSize > 16 || MFI->adjustsStack()) {
203    FrameSize = FrameSize + SPUFrameLowering::minStackSize();
204    if (isInt<10>(FrameSize + LinkSlotOffset)) {
205      // Reload $lr, adjust $sp by required amount
206      // Note: We do this to slightly improve dual issue -- not by much, but it
207      // is an opportunity for dual issue.
208      BuildMI(MBB, MBBI, dl, TII.get(SPU::LQDr128), SPU::R0)
209        .addImm(FrameSize + LinkSlotOffset)
210        .addReg(SPU::R1);
211      BuildMI(MBB, MBBI, dl, TII.get(SPU::AIr32), SPU::R1)
212        .addReg(SPU::R1)
213        .addImm(FrameSize);
214    } else if (FrameSize <= (1 << 16) - 1 && FrameSize >= -(1 << 16)) {
215      // Frame size can be loaded into ILr32n, so temporarily spill $r2 and use
216      // $r2 to adjust $sp:
217      BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr128), SPU::R2)
218        .addImm(16)
219        .addReg(SPU::R1);
220      BuildMI(MBB, MBBI, dl, TII.get(SPU::ILr32), SPU::R2)
221        .addImm(FrameSize);
222      BuildMI(MBB, MBBI, dl, TII.get(SPU::Ar32), SPU::R1)
223        .addReg(SPU::R1)
224        .addReg(SPU::R2);
225      BuildMI(MBB, MBBI, dl, TII.get(SPU::LQDr128), SPU::R0)
226        .addImm(16)
227        .addReg(SPU::R1);
228      BuildMI(MBB, MBBI, dl, TII.get(SPU::SFIr32), SPU::R2).
229        addReg(SPU::R2)
230        .addImm(16);
231      BuildMI(MBB, MBBI, dl, TII.get(SPU::LQXr128), SPU::R2)
232        .addReg(SPU::R2)
233        .addReg(SPU::R1);
234    } else {
235      report_fatal_error("Unhandled frame size: " + Twine(FrameSize));
236    }
237  }
238}
239
240void SPUFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
241                                                        RegScavenger *RS) const{
242  // Mark LR and SP unused, since the prolog spills them to stack and
243  // we don't want anyone else to spill them for us.
244  //
245  // Also, unless R2 is really used someday, don't spill it automatically.
246  MF.getRegInfo().setPhysRegUnused(SPU::R0);
247  MF.getRegInfo().setPhysRegUnused(SPU::R1);
248  MF.getRegInfo().setPhysRegUnused(SPU::R2);
249
250  MachineFrameInfo *MFI = MF.getFrameInfo();
251  const TargetRegisterClass *RC = &SPU::R32CRegClass;
252  RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
253                                                     RC->getAlignment(),
254                                                     false));
255}
256