Starting to refactor Target to separate out code that's needed to fully describe
[oota-llvm.git] / lib / Target / CellSPU / SPUFrameLowering.cpp
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 "SPURegisterNames.h"
17 #include "SPUInstrBuilder.h"
18 #include "SPUInstrInfo.h"
19 #include "llvm/Function.h"
20 #include "llvm/CodeGen/MachineFrameInfo.h"
21 #include "llvm/CodeGen/MachineFunction.h"
22 #include "llvm/CodeGen/MachineInstrBuilder.h"
23 #include "llvm/CodeGen/MachineModuleInfo.h"
24 #include "llvm/CodeGen/MachineRegisterInfo.h"
25 #include "llvm/CodeGen/RegisterScavenging.h"
26 #include "llvm/Target/TargetData.h"
27 #include "llvm/Target/TargetOptions.h"
28 #include "llvm/Support/CommandLine.h"
29 using namespace llvm;
30
31 //===----------------------------------------------------------------------===//
32 // SPUFrameLowering:
33 //===----------------------------------------------------------------------===//
34
35 SPUFrameLowering::SPUFrameLowering(const SPUSubtarget &sti)
36   : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 16, 0),
37     Subtarget(sti) {
38   LR[0].first = SPU::R0;
39   LR[0].second = 16;
40 }
41
42
43 //--------------------------------------------------------------------------
44 // hasFP - Return true if the specified function actually has a dedicated frame
45 // pointer register.  This is true if the function needs a frame pointer and has
46 // a non-zero stack size.
47 bool SPUFrameLowering::hasFP(const MachineFunction &MF) const {
48   const MachineFrameInfo *MFI = MF.getFrameInfo();
49
50   return MFI->getStackSize() &&
51     (DisableFramePointerElim(MF) || MFI->hasVarSizedObjects());
52 }
53
54
55 /// determineFrameLayout - Determine the size of the frame and maximum call
56 /// frame size.
57 void 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
91 void 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   } else {
186     // This is a leaf function -- insert a branch hint iff there are
187     // sufficient number instructions in the basic block. Note that
188     // this is just a best guess based on the basic block's size.
189     if (MBB.size() >= (unsigned) SPUFrameLowering::branchHintPenalty()) {
190       MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
191       dl = MBBI->getDebugLoc();
192
193       // Insert terminator label
194       BuildMI(MBB, MBBI, dl, TII.get(SPU::PROLOG_LABEL))
195         .addSym(MMI.getContext().CreateTempSymbol());
196     }
197   }
198 }
199
200 void SPUFrameLowering::emitEpilogue(MachineFunction &MF,
201                                 MachineBasicBlock &MBB) const {
202   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
203   const SPUInstrInfo &TII =
204     *static_cast<const SPUInstrInfo*>(MF.getTarget().getInstrInfo());
205   const MachineFrameInfo *MFI = MF.getFrameInfo();
206   int FrameSize = MFI->getStackSize();
207   int LinkSlotOffset = SPUFrameLowering::stackSlotSize();
208   DebugLoc dl = MBBI->getDebugLoc();
209
210   assert(MBBI->getOpcode() == SPU::RET &&
211          "Can only insert epilog into returning blocks");
212   assert((FrameSize & 0xf) == 0 && "FrameSize not aligned");
213
214   // the "empty" frame size is 16 - just the register scavenger spill slot
215   if (FrameSize > 16 || MFI->adjustsStack()) {
216     FrameSize = FrameSize + SPUFrameLowering::minStackSize();
217     if (isInt<10>(FrameSize + LinkSlotOffset)) {
218       // Reload $lr, adjust $sp by required amount
219       // Note: We do this to slightly improve dual issue -- not by much, but it
220       // is an opportunity for dual issue.
221       BuildMI(MBB, MBBI, dl, TII.get(SPU::LQDr128), SPU::R0)
222         .addImm(FrameSize + LinkSlotOffset)
223         .addReg(SPU::R1);
224       BuildMI(MBB, MBBI, dl, TII.get(SPU::AIr32), SPU::R1)
225         .addReg(SPU::R1)
226         .addImm(FrameSize);
227     } else if (FrameSize <= (1 << 16) - 1 && FrameSize >= -(1 << 16)) {
228       // Frame size can be loaded into ILr32n, so temporarily spill $r2 and use
229       // $r2 to adjust $sp:
230       BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr128), SPU::R2)
231         .addImm(16)
232         .addReg(SPU::R1);
233       BuildMI(MBB, MBBI, dl, TII.get(SPU::ILr32), SPU::R2)
234         .addImm(FrameSize);
235       BuildMI(MBB, MBBI, dl, TII.get(SPU::Ar32), SPU::R1)
236         .addReg(SPU::R1)
237         .addReg(SPU::R2);
238       BuildMI(MBB, MBBI, dl, TII.get(SPU::LQDr128), SPU::R0)
239         .addImm(16)
240         .addReg(SPU::R1);
241       BuildMI(MBB, MBBI, dl, TII.get(SPU::SFIr32), SPU::R2).
242         addReg(SPU::R2)
243         .addImm(16);
244       BuildMI(MBB, MBBI, dl, TII.get(SPU::LQXr128), SPU::R2)
245         .addReg(SPU::R2)
246         .addReg(SPU::R1);
247     } else {
248       report_fatal_error("Unhandled frame size: " + Twine(FrameSize));
249     }
250   }
251 }
252
253 void SPUFrameLowering::getInitialFrameState(std::vector<MachineMove> &Moves)
254                                                                          const {
255   // Initial state of the frame pointer is R1.
256   MachineLocation Dst(MachineLocation::VirtualFP);
257   MachineLocation Src(SPU::R1, 0);
258   Moves.push_back(MachineMove(0, Dst, Src));
259 }
260
261 void SPUFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
262                                                         RegScavenger *RS) const{
263   // Mark LR and SP unused, since the prolog spills them to stack and
264   // we don't want anyone else to spill them for us.
265   //
266   // Also, unless R2 is really used someday, don't spill it automatically.
267   MF.getRegInfo().setPhysRegUnused(SPU::R0);
268   MF.getRegInfo().setPhysRegUnused(SPU::R1);
269   MF.getRegInfo().setPhysRegUnused(SPU::R2);
270
271   MachineFrameInfo *MFI = MF.getFrameInfo();
272   const TargetRegisterClass *RC = &SPU::R32CRegClass;
273   RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
274                                                      RC->getAlignment(),
275                                                      false));
276 }