blob: b1a09ad553f070359d86a1f4d38350e123c96d07 [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"
15#include "SPUFrameInfo.h"
16#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"
25#include "llvm/Target/TargetData.h"
26#include "llvm/Target/TargetOptions.h"
27#include "llvm/Support/CommandLine.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000028using namespace llvm;
29
30//===----------------------------------------------------------------------===//
31// SPUFrameInfo:
32//===----------------------------------------------------------------------===//
33
Anton Korobeynikov33464912010-11-15 00:06:54 +000034SPUFrameInfo::SPUFrameInfo(const SPUSubtarget &sti)
35 : TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 16, 0),
36 Subtarget(sti) {
Scott Michel266bc8f2007-12-04 22:23:35 +000037 LR[0].first = SPU::R0;
38 LR[0].second = 16;
39}
Anton Korobeynikov33464912010-11-15 00:06:54 +000040
41
Anton Korobeynikovd0c38172010-11-18 21:19:35 +000042//--------------------------------------------------------------------------
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 SPUFrameInfo::hasFP(const MachineFunction &MF) const {
47 const MachineFrameInfo *MFI = MF.getFrameInfo();
48
49 return MFI->getStackSize() &&
50 (DisableFramePointerElim(MF) || MFI->hasVarSizedObjects());
51}
52
53
Anton Korobeynikov33464912010-11-15 00:06:54 +000054/// determineFrameLayout - Determine the size of the frame and maximum call
55/// frame size.
56void SPUFrameInfo::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 = MF.getTarget().getFrameInfo()->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 SPUFrameInfo::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 + SPUFrameInfo::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) SPUFrameInfo::branchHintPenalty()) {
189 MachineBasicBlock::iterator MBBI = prior(MBB.end());
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
199void SPUFrameInfo::emitEpilogue(MachineFunction &MF,
200 MachineBasicBlock &MBB) const {
201 MachineBasicBlock::iterator MBBI = prior(MBB.end());
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 = SPUFrameInfo::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 + SPUFrameInfo::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}