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