blob: 432f4a1b59e247e414eb41fecd5635480a2e08d9 [file] [log] [blame]
Scott Michel266bc8f2007-12-04 22:23:35 +00001//===-- SPUTargetMachine.cpp - Define TargetMachine for Cell SPU ----------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Scott Michel266bc8f2007-12-04 22:23:35 +00007//
8//===----------------------------------------------------------------------===//
9//
10// Top-level implementation for the Cell SPU target.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SPU.h"
Anton Korobeynikov16c29b52011-01-10 12:39:04 +000015#include "SPUFrameLowering.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000016#include "SPURegisterNames.h"
Anton Korobeynikov33464912010-11-15 00:06:54 +000017#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"
Anton Korobeynikov94c5ae02010-11-27 23:05:25 +000025#include "llvm/CodeGen/RegisterScavenging.h"
Anton Korobeynikov33464912010-11-15 00:06:54 +000026#include "llvm/Target/TargetData.h"
27#include "llvm/Target/TargetOptions.h"
28#include "llvm/Support/CommandLine.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000029using namespace llvm;
30
31//===----------------------------------------------------------------------===//
Anton Korobeynikov16c29b52011-01-10 12:39:04 +000032// SPUFrameLowering:
Scott Michel266bc8f2007-12-04 22:23:35 +000033//===----------------------------------------------------------------------===//
34
Anton Korobeynikov16c29b52011-01-10 12:39:04 +000035SPUFrameLowering::SPUFrameLowering(const SPUSubtarget &sti)
36 : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 16, 0),
Anton Korobeynikov33464912010-11-15 00:06:54 +000037 Subtarget(sti) {
Scott Michel266bc8f2007-12-04 22:23:35 +000038 LR[0].first = SPU::R0;
39 LR[0].second = 16;
40}
Anton Korobeynikov33464912010-11-15 00:06:54 +000041
42
Anton Korobeynikovd0c38172010-11-18 21:19:35 +000043//--------------------------------------------------------------------------
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.
Anton Korobeynikov16c29b52011-01-10 12:39:04 +000047bool SPUFrameLowering::hasFP(const MachineFunction &MF) const {
Anton Korobeynikovd0c38172010-11-18 21:19:35 +000048 const MachineFrameInfo *MFI = MF.getFrameInfo();
49
50 return MFI->getStackSize() &&
51 (DisableFramePointerElim(MF) || MFI->hasVarSizedObjects());
52}
53
54
Anton Korobeynikov33464912010-11-15 00:06:54 +000055/// determineFrameLayout - Determine the size of the frame and maximum call
56/// frame size.
Anton Korobeynikov16c29b52011-01-10 12:39:04 +000057void SPUFrameLowering::determineFrameLayout(MachineFunction &MF) const {
Anton Korobeynikov33464912010-11-15 00:06:54 +000058 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.
Anton Korobeynikov16c29b52011-01-10 12:39:04 +000065 unsigned TargetAlign = getStackAlignment();
Anton Korobeynikov33464912010-11-15 00:06:54 +000066 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
Anton Korobeynikov16c29b52011-01-10 12:39:04 +000091void SPUFrameLowering::emitPrologue(MachineFunction &MF) const {
Anton Korobeynikov33464912010-11-15 00:06:54 +000092 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()) {
Anton Korobeynikov16c29b52011-01-10 12:39:04 +0000116 FrameSize = -(FrameSize + SPUFrameLowering::minStackSize());
Anton Korobeynikov33464912010-11-15 00:06:54 +0000117 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.
Anton Korobeynikov16c29b52011-01-10 12:39:04 +0000189 if (MBB.size() >= (unsigned) SPUFrameLowering::branchHintPenalty()) {
Jakob Stoklund Olesen4f28c1c2011-01-13 21:28:52 +0000190 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
Anton Korobeynikov33464912010-11-15 00:06:54 +0000191 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
Anton Korobeynikov16c29b52011-01-10 12:39:04 +0000200void SPUFrameLowering::emitEpilogue(MachineFunction &MF,
Anton Korobeynikov33464912010-11-15 00:06:54 +0000201 MachineBasicBlock &MBB) const {
Jakob Stoklund Olesen4f28c1c2011-01-13 21:28:52 +0000202 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
Anton Korobeynikov33464912010-11-15 00:06:54 +0000203 const SPUInstrInfo &TII =
204 *static_cast<const SPUInstrInfo*>(MF.getTarget().getInstrInfo());
205 const MachineFrameInfo *MFI = MF.getFrameInfo();
206 int FrameSize = MFI->getStackSize();
Anton Korobeynikov16c29b52011-01-10 12:39:04 +0000207 int LinkSlotOffset = SPUFrameLowering::stackSlotSize();
Anton Korobeynikov33464912010-11-15 00:06:54 +0000208 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()) {
Anton Korobeynikov16c29b52011-01-10 12:39:04 +0000216 FrameSize = FrameSize + SPUFrameLowering::minStackSize();
Anton Korobeynikov33464912010-11-15 00:06:54 +0000217 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}
Anton Korobeynikovd9e33852010-11-18 23:25:52 +0000252
Anton Korobeynikov16c29b52011-01-10 12:39:04 +0000253void SPUFrameLowering::getInitialFrameState(std::vector<MachineMove> &Moves)
254 const {
Anton Korobeynikovd9e33852010-11-18 23:25:52 +0000255 // 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}
Anton Korobeynikov94c5ae02010-11-27 23:05:25 +0000260
Anton Korobeynikov16c29b52011-01-10 12:39:04 +0000261void SPUFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
Anton Korobeynikov94c5ae02010-11-27 23:05:25 +0000262 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}