blob: 7fde9a0144fb888af92589e58e4d4cd79714ca05 [file] [log] [blame]
Anton Korobeynikov33464912010-11-15 00:06:54 +00001//=====- SystemZFrameInfo.cpp - SystemZ Frame Information ------*- C++ -*-====//
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// This file contains the SystemZ implementation of TargetFrameInfo class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SystemZFrameInfo.h"
15#include "SystemZInstrBuilder.h"
16#include "SystemZInstrInfo.h"
17#include "SystemZMachineFunctionInfo.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/Target/TargetData.h"
25#include "llvm/Target/TargetOptions.h"
26#include "llvm/Support/CommandLine.h"
27
28using namespace llvm;
29
Anton Korobeynikovcd775ce2010-11-27 23:05:03 +000030SystemZFrameInfo::SystemZFrameInfo(const SystemZSubtarget &sti)
31 : TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 8, -160), STI(sti) {
32 // Fill the spill offsets map
33 static const unsigned SpillOffsTab[][2] = {
34 { SystemZ::R2D, 0x10 },
35 { SystemZ::R3D, 0x18 },
36 { SystemZ::R4D, 0x20 },
37 { SystemZ::R5D, 0x28 },
38 { SystemZ::R6D, 0x30 },
39 { SystemZ::R7D, 0x38 },
40 { SystemZ::R8D, 0x40 },
41 { SystemZ::R9D, 0x48 },
42 { SystemZ::R10D, 0x50 },
43 { SystemZ::R11D, 0x58 },
44 { SystemZ::R12D, 0x60 },
45 { SystemZ::R13D, 0x68 },
46 { SystemZ::R14D, 0x70 },
47 { SystemZ::R15D, 0x78 }
48 };
49
50 RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS);
51
52 for (unsigned i = 0, e = array_lengthof(SpillOffsTab); i != e; ++i)
53 RegSpillOffsets[SpillOffsTab[i][0]] = SpillOffsTab[i][1];
54}
Anton Korobeynikovd0c38172010-11-18 21:19:35 +000055
56/// needsFP - Return true if the specified function should have a dedicated
57/// frame pointer register. This is true if the function has variable sized
58/// allocas or if frame pointer elimination is disabled.
59bool SystemZFrameInfo::hasFP(const MachineFunction &MF) const {
60 const MachineFrameInfo *MFI = MF.getFrameInfo();
61 return DisableFramePointerElim(MF) || MFI->hasVarSizedObjects();
62}
63
Anton Korobeynikov33464912010-11-15 00:06:54 +000064/// emitSPUpdate - Emit a series of instructions to increment / decrement the
65/// stack pointer by a constant value.
66static
67void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
68 int64_t NumBytes, const TargetInstrInfo &TII) {
69 unsigned Opc; uint64_t Chunk;
70 bool isSub = NumBytes < 0;
71 uint64_t Offset = isSub ? -NumBytes : NumBytes;
72
73 if (Offset >= (1LL << 15) - 1) {
74 Opc = SystemZ::ADD64ri32;
75 Chunk = (1LL << 31) - 1;
76 } else {
77 Opc = SystemZ::ADD64ri16;
78 Chunk = (1LL << 15) - 1;
79 }
80
81 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
82
83 while (Offset) {
84 uint64_t ThisVal = (Offset > Chunk) ? Chunk : Offset;
85 MachineInstr *MI =
86 BuildMI(MBB, MBBI, DL, TII.get(Opc), SystemZ::R15D)
87 .addReg(SystemZ::R15D).addImm(isSub ? -ThisVal : ThisVal);
88 // The PSW implicit def is dead.
89 MI->getOperand(3).setIsDead();
90 Offset -= ThisVal;
91 }
92}
93
94void SystemZFrameInfo::emitPrologue(MachineFunction &MF) const {
95 MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
96 const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo();
97 MachineFrameInfo *MFI = MF.getFrameInfo();
Anton Korobeynikov33464912010-11-15 00:06:54 +000098 const SystemZInstrInfo &TII =
99 *static_cast<const SystemZInstrInfo*>(MF.getTarget().getInstrInfo());
100 SystemZMachineFunctionInfo *SystemZMFI =
101 MF.getInfo<SystemZMachineFunctionInfo>();
102 MachineBasicBlock::iterator MBBI = MBB.begin();
103 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
104
105 // Get the number of bytes to allocate from the FrameInfo.
106 // Note that area for callee-saved stuff is already allocated, thus we need to
107 // 'undo' the stack movement.
108 uint64_t StackSize = MFI->getStackSize();
109 StackSize -= SystemZMFI->getCalleeSavedFrameSize();
110
111 uint64_t NumBytes = StackSize - TFI.getOffsetOfLocalArea();
112
113 // Skip the callee-saved push instructions.
114 while (MBBI != MBB.end() &&
115 (MBBI->getOpcode() == SystemZ::MOV64mr ||
116 MBBI->getOpcode() == SystemZ::MOV64mrm))
117 ++MBBI;
118
119 if (MBBI != MBB.end())
120 DL = MBBI->getDebugLoc();
121
122 // adjust stack pointer: R15 -= numbytes
123 if (StackSize || MFI->hasCalls()) {
124 assert(MF.getRegInfo().isPhysRegUsed(SystemZ::R15D) &&
125 "Invalid stack frame calculation!");
126 emitSPUpdate(MBB, MBBI, -(int64_t)NumBytes, TII);
127 }
128
Anton Korobeynikovd0c38172010-11-18 21:19:35 +0000129 if (hasFP(MF)) {
Anton Korobeynikov33464912010-11-15 00:06:54 +0000130 // Update R11 with the new base value...
131 BuildMI(MBB, MBBI, DL, TII.get(SystemZ::MOV64rr), SystemZ::R11D)
132 .addReg(SystemZ::R15D);
133
134 // Mark the FramePtr as live-in in every block except the entry.
135 for (MachineFunction::iterator I = llvm::next(MF.begin()), E = MF.end();
136 I != E; ++I)
137 I->addLiveIn(SystemZ::R11D);
138
139 }
140}
141
142void SystemZFrameInfo::emitEpilogue(MachineFunction &MF,
143 MachineBasicBlock &MBB) const {
144 const MachineFrameInfo *MFI = MF.getFrameInfo();
145 const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo();
146 MachineBasicBlock::iterator MBBI = prior(MBB.end());
147 const SystemZInstrInfo &TII =
148 *static_cast<const SystemZInstrInfo*>(MF.getTarget().getInstrInfo());
149 SystemZMachineFunctionInfo *SystemZMFI =
150 MF.getInfo<SystemZMachineFunctionInfo>();
151 unsigned RetOpcode = MBBI->getOpcode();
152
153 switch (RetOpcode) {
154 case SystemZ::RET: break; // These are ok
155 default:
156 assert(0 && "Can only insert epilog into returning blocks");
157 }
158
159 // Get the number of bytes to allocate from the FrameInfo
160 // Note that area for callee-saved stuff is already allocated, thus we need to
161 // 'undo' the stack movement.
162 uint64_t StackSize =
163 MFI->getStackSize() - SystemZMFI->getCalleeSavedFrameSize();
164 uint64_t NumBytes = StackSize - TFI.getOffsetOfLocalArea();
165
166 // Skip the final terminator instruction.
167 while (MBBI != MBB.begin()) {
168 MachineBasicBlock::iterator PI = prior(MBBI);
169 --MBBI;
170 if (!PI->getDesc().isTerminator())
171 break;
172 }
173
174 // During callee-saved restores emission stack frame was not yet finialized
175 // (and thus - the stack size was unknown). Tune the offset having full stack
176 // size in hands.
177 if (StackSize || MFI->hasCalls()) {
178 assert((MBBI->getOpcode() == SystemZ::MOV64rmm ||
179 MBBI->getOpcode() == SystemZ::MOV64rm) &&
180 "Expected to see callee-save register restore code");
181 assert(MF.getRegInfo().isPhysRegUsed(SystemZ::R15D) &&
182 "Invalid stack frame calculation!");
183
184 unsigned i = 0;
185 MachineInstr &MI = *MBBI;
186 while (!MI.getOperand(i).isImm()) {
187 ++i;
188 assert(i < MI.getNumOperands() && "Unexpected restore code!");
189 }
190
191 uint64_t Offset = NumBytes + MI.getOperand(i).getImm();
192 // If Offset does not fit into 20-bit signed displacement field we need to
193 // emit some additional code...
194 if (Offset > 524287) {
195 // Fold the displacement into load instruction as much as possible.
196 NumBytes = Offset - 524287;
197 Offset = 524287;
198 emitSPUpdate(MBB, MBBI, NumBytes, TII);
199 }
200
201 MI.getOperand(i).ChangeToImmediate(Offset);
202 }
203}
Anton Korobeynikov82f58742010-11-20 15:59:32 +0000204
205int SystemZFrameInfo::getFrameIndexOffset(const MachineFunction &MF,
206 int FI) const {
207 const MachineFrameInfo *MFI = MF.getFrameInfo();
208 const SystemZMachineFunctionInfo *SystemZMFI =
209 MF.getInfo<SystemZMachineFunctionInfo>();
210 int Offset = MFI->getObjectOffset(FI) + MFI->getOffsetAdjustment();
211 uint64_t StackSize = MFI->getStackSize();
212
213 // Fixed objects are really located in the "previous" frame.
214 if (FI < 0)
215 StackSize -= SystemZMFI->getCalleeSavedFrameSize();
216
217 Offset += StackSize - getOffsetOfLocalArea();
218
219 // Skip the register save area if we generated the stack frame.
220 if (StackSize || MFI->hasCalls())
221 Offset -= getOffsetOfLocalArea();
222
223 return Offset;
224}
Anton Korobeynikovcd775ce2010-11-27 23:05:03 +0000225
226bool
227SystemZFrameInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
228 MachineBasicBlock::iterator MI,
229 const std::vector<CalleeSavedInfo> &CSI,
230 const TargetRegisterInfo *TRI) const {
231 if (CSI.empty())
232 return false;
233
234 DebugLoc DL;
235 if (MI != MBB.end()) DL = MI->getDebugLoc();
236
237 MachineFunction &MF = *MBB.getParent();
238 const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
239 SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
240 unsigned CalleeFrameSize = 0;
241
242 // Scan the callee-saved and find the bounds of register spill area.
243 unsigned LowReg = 0, HighReg = 0, StartOffset = -1U, EndOffset = 0;
244 for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
245 unsigned Reg = CSI[i].getReg();
246 if (!SystemZ::FP64RegClass.contains(Reg)) {
247 unsigned Offset = RegSpillOffsets[Reg];
248 CalleeFrameSize += 8;
249 if (StartOffset > Offset) {
250 LowReg = Reg; StartOffset = Offset;
251 }
252 if (EndOffset < Offset) {
253 HighReg = Reg; EndOffset = RegSpillOffsets[Reg];
254 }
255 }
256 }
257
258 // Save information for epilogue inserter.
259 MFI->setCalleeSavedFrameSize(CalleeFrameSize);
260 MFI->setLowReg(LowReg); MFI->setHighReg(HighReg);
261
262 // Save GPRs
263 if (StartOffset) {
264 // Build a store instruction. Use STORE MULTIPLE instruction if there are many
265 // registers to store, otherwise - just STORE.
266 MachineInstrBuilder MIB =
267 BuildMI(MBB, MI, DL, TII.get((LowReg == HighReg ?
268 SystemZ::MOV64mr : SystemZ::MOV64mrm)));
269
270 // Add store operands.
271 MIB.addReg(SystemZ::R15D).addImm(StartOffset);
272 if (LowReg == HighReg)
273 MIB.addReg(0);
274 MIB.addReg(LowReg, RegState::Kill);
275 if (LowReg != HighReg)
276 MIB.addReg(HighReg, RegState::Kill);
277
278 // Do a second scan adding regs as being killed by instruction
279 for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
280 unsigned Reg = CSI[i].getReg();
281 // Add the callee-saved register as live-in. It's killed at the spill.
282 MBB.addLiveIn(Reg);
283 if (Reg != LowReg && Reg != HighReg)
284 MIB.addReg(Reg, RegState::ImplicitKill);
285 }
286 }
287
288 // Save FPRs
289 for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
290 unsigned Reg = CSI[i].getReg();
291 if (SystemZ::FP64RegClass.contains(Reg)) {
292 MBB.addLiveIn(Reg);
293 TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(),
294 &SystemZ::FP64RegClass, TRI);
295 }
296 }
297
298 return true;
299}
300
301bool
302SystemZFrameInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
303 MachineBasicBlock::iterator MI,
304 const std::vector<CalleeSavedInfo> &CSI,
305 const TargetRegisterInfo *TRI) const {
306 if (CSI.empty())
307 return false;
308
309 DebugLoc DL;
310 if (MI != MBB.end()) DL = MI->getDebugLoc();
311
312 MachineFunction &MF = *MBB.getParent();
313 const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
314 SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
315
316 // Restore FP registers
317 for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
318 unsigned Reg = CSI[i].getReg();
319 if (SystemZ::FP64RegClass.contains(Reg))
320 TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(),
321 &SystemZ::FP64RegClass, TRI);
322 }
323
324 // Restore GP registers
325 unsigned LowReg = MFI->getLowReg(), HighReg = MFI->getHighReg();
326 unsigned StartOffset = RegSpillOffsets[LowReg];
327
328 if (StartOffset) {
329 // Build a load instruction. Use LOAD MULTIPLE instruction if there are many
330 // registers to load, otherwise - just LOAD.
331 MachineInstrBuilder MIB =
332 BuildMI(MBB, MI, DL, TII.get((LowReg == HighReg ?
333 SystemZ::MOV64rm : SystemZ::MOV64rmm)));
334 // Add store operands.
335 MIB.addReg(LowReg, RegState::Define);
336 if (LowReg != HighReg)
337 MIB.addReg(HighReg, RegState::Define);
338
339 MIB.addReg(hasFP(MF) ? SystemZ::R11D : SystemZ::R15D);
340 MIB.addImm(StartOffset);
341 if (LowReg == HighReg)
342 MIB.addReg(0);
343
344 // Do a second scan adding regs as being defined by instruction
345 for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
346 unsigned Reg = CSI[i].getReg();
347 if (Reg != LowReg && Reg != HighReg)
348 MIB.addReg(Reg, RegState::ImplicitDefine);
349 }
350 }
351
352 return true;
353}