]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/lib/Target/CellSPU/SPUFrameLowering.cpp
Copy head to stable/9 as part of 9.0-RELEASE release cycle.
[FreeBSD/stable/9.git] / contrib / llvm / 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 "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"
28 using namespace llvm;
29
30 //===----------------------------------------------------------------------===//
31 // SPUFrameLowering:
32 //===----------------------------------------------------------------------===//
33
34 SPUFrameLowering::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.
46 bool 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.
56 void 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
90 void 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   } else {
185     // This is a leaf function -- insert a branch hint iff there are
186     // sufficient number instructions in the basic block. Note that
187     // this is just a best guess based on the basic block's size.
188     if (MBB.size() >= (unsigned) SPUFrameLowering::branchHintPenalty()) {
189       MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
190       dl = MBBI->getDebugLoc();
191
192       // Insert terminator label
193       BuildMI(MBB, MBBI, dl, TII.get(SPU::PROLOG_LABEL))
194         .addSym(MMI.getContext().CreateTempSymbol());
195     }
196   }
197 }
198
199 void SPUFrameLowering::emitEpilogue(MachineFunction &MF,
200                                 MachineBasicBlock &MBB) const {
201   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
202   const SPUInstrInfo &TII =
203     *static_cast<const SPUInstrInfo*>(MF.getTarget().getInstrInfo());
204   const MachineFrameInfo *MFI = MF.getFrameInfo();
205   int FrameSize = MFI->getStackSize();
206   int LinkSlotOffset = SPUFrameLowering::stackSlotSize();
207   DebugLoc dl = MBBI->getDebugLoc();
208
209   assert(MBBI->getOpcode() == SPU::RET &&
210          "Can only insert epilog into returning blocks");
211   assert((FrameSize & 0xf) == 0 && "FrameSize not aligned");
212
213   // the "empty" frame size is 16 - just the register scavenger spill slot
214   if (FrameSize > 16 || MFI->adjustsStack()) {
215     FrameSize = FrameSize + SPUFrameLowering::minStackSize();
216     if (isInt<10>(FrameSize + LinkSlotOffset)) {
217       // Reload $lr, adjust $sp by required amount
218       // Note: We do this to slightly improve dual issue -- not by much, but it
219       // is an opportunity for dual issue.
220       BuildMI(MBB, MBBI, dl, TII.get(SPU::LQDr128), SPU::R0)
221         .addImm(FrameSize + LinkSlotOffset)
222         .addReg(SPU::R1);
223       BuildMI(MBB, MBBI, dl, TII.get(SPU::AIr32), SPU::R1)
224         .addReg(SPU::R1)
225         .addImm(FrameSize);
226     } else if (FrameSize <= (1 << 16) - 1 && FrameSize >= -(1 << 16)) {
227       // Frame size can be loaded into ILr32n, so temporarily spill $r2 and use
228       // $r2 to adjust $sp:
229       BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr128), SPU::R2)
230         .addImm(16)
231         .addReg(SPU::R1);
232       BuildMI(MBB, MBBI, dl, TII.get(SPU::ILr32), SPU::R2)
233         .addImm(FrameSize);
234       BuildMI(MBB, MBBI, dl, TII.get(SPU::Ar32), SPU::R1)
235         .addReg(SPU::R1)
236         .addReg(SPU::R2);
237       BuildMI(MBB, MBBI, dl, TII.get(SPU::LQDr128), SPU::R0)
238         .addImm(16)
239         .addReg(SPU::R1);
240       BuildMI(MBB, MBBI, dl, TII.get(SPU::SFIr32), SPU::R2).
241         addReg(SPU::R2)
242         .addImm(16);
243       BuildMI(MBB, MBBI, dl, TII.get(SPU::LQXr128), SPU::R2)
244         .addReg(SPU::R2)
245         .addReg(SPU::R1);
246     } else {
247       report_fatal_error("Unhandled frame size: " + Twine(FrameSize));
248     }
249   }
250 }
251
252 void SPUFrameLowering::getInitialFrameState(std::vector<MachineMove> &Moves)
253                                                                          const {
254   // Initial state of the frame pointer is R1.
255   MachineLocation Dst(MachineLocation::VirtualFP);
256   MachineLocation Src(SPU::R1, 0);
257   Moves.push_back(MachineMove(0, Dst, Src));
258 }
259
260 void SPUFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
261                                                         RegScavenger *RS) const{
262   // Mark LR and SP unused, since the prolog spills them to stack and
263   // we don't want anyone else to spill them for us.
264   //
265   // Also, unless R2 is really used someday, don't spill it automatically.
266   MF.getRegInfo().setPhysRegUnused(SPU::R0);
267   MF.getRegInfo().setPhysRegUnused(SPU::R1);
268   MF.getRegInfo().setPhysRegUnused(SPU::R2);
269
270   MachineFrameInfo *MFI = MF.getFrameInfo();
271   const TargetRegisterClass *RC = &SPU::R32CRegClass;
272   RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
273                                                      RC->getAlignment(),
274                                                      false));
275 }