1 //=====- SystemZFrameLowering.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 TargetFrameLowering class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "SystemZFrameLowering.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
28 using namespace llvm;
29
SystemZFrameLowering(const SystemZSubtarget & sti)30 SystemZFrameLowering::SystemZFrameLowering(const SystemZSubtarget &sti)
31 : TargetFrameLowering(TargetFrameLowering::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 }
55
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.
hasFP(const MachineFunction & MF) const59 bool SystemZFrameLowering::hasFP(const MachineFunction &MF) const {
60 const MachineFrameInfo *MFI = MF.getFrameInfo();
61 return DisableFramePointerElim(MF) || MFI->hasVarSizedObjects();
62 }
63
64 /// emitSPUpdate - Emit a series of instructions to increment / decrement the
65 /// stack pointer by a constant value.
66 static
emitSPUpdate(MachineBasicBlock & MBB,MachineBasicBlock::iterator & MBBI,int64_t NumBytes,const TargetInstrInfo & TII)67 void 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
emitPrologue(MachineFunction & MF) const94 void SystemZFrameLowering::emitPrologue(MachineFunction &MF) const {
95 MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
96 MachineFrameInfo *MFI = MF.getFrameInfo();
97 const SystemZInstrInfo &TII =
98 *static_cast<const SystemZInstrInfo*>(MF.getTarget().getInstrInfo());
99 SystemZMachineFunctionInfo *SystemZMFI =
100 MF.getInfo<SystemZMachineFunctionInfo>();
101 MachineBasicBlock::iterator MBBI = MBB.begin();
102 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
103
104 // Get the number of bytes to allocate from the FrameInfo.
105 // Note that area for callee-saved stuff is already allocated, thus we need to
106 // 'undo' the stack movement.
107 uint64_t StackSize = MFI->getStackSize();
108 StackSize -= SystemZMFI->getCalleeSavedFrameSize();
109
110 uint64_t NumBytes = StackSize - getOffsetOfLocalArea();
111
112 // Skip the callee-saved push instructions.
113 while (MBBI != MBB.end() &&
114 (MBBI->getOpcode() == SystemZ::MOV64mr ||
115 MBBI->getOpcode() == SystemZ::MOV64mrm))
116 ++MBBI;
117
118 if (MBBI != MBB.end())
119 DL = MBBI->getDebugLoc();
120
121 // adjust stack pointer: R15 -= numbytes
122 if (StackSize || MFI->hasCalls()) {
123 assert(MF.getRegInfo().isPhysRegUsed(SystemZ::R15D) &&
124 "Invalid stack frame calculation!");
125 emitSPUpdate(MBB, MBBI, -(int64_t)NumBytes, TII);
126 }
127
128 if (hasFP(MF)) {
129 // Update R11 with the new base value...
130 BuildMI(MBB, MBBI, DL, TII.get(SystemZ::MOV64rr), SystemZ::R11D)
131 .addReg(SystemZ::R15D);
132
133 // Mark the FramePtr as live-in in every block except the entry.
134 for (MachineFunction::iterator I = llvm::next(MF.begin()), E = MF.end();
135 I != E; ++I)
136 I->addLiveIn(SystemZ::R11D);
137
138 }
139 }
140
emitEpilogue(MachineFunction & MF,MachineBasicBlock & MBB) const141 void SystemZFrameLowering::emitEpilogue(MachineFunction &MF,
142 MachineBasicBlock &MBB) const {
143 const MachineFrameInfo *MFI = MF.getFrameInfo();
144 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
145 const SystemZInstrInfo &TII =
146 *static_cast<const SystemZInstrInfo*>(MF.getTarget().getInstrInfo());
147 SystemZMachineFunctionInfo *SystemZMFI =
148 MF.getInfo<SystemZMachineFunctionInfo>();
149 unsigned RetOpcode = MBBI->getOpcode();
150
151 switch (RetOpcode) {
152 case SystemZ::RET: break; // These are ok
153 default:
154 assert(0 && "Can only insert epilog into returning blocks");
155 }
156
157 // Get the number of bytes to allocate from the FrameInfo
158 // Note that area for callee-saved stuff is already allocated, thus we need to
159 // 'undo' the stack movement.
160 uint64_t StackSize =
161 MFI->getStackSize() - SystemZMFI->getCalleeSavedFrameSize();
162 uint64_t NumBytes = StackSize - getOffsetOfLocalArea();
163
164 // Skip the final terminator instruction.
165 while (MBBI != MBB.begin()) {
166 MachineBasicBlock::iterator PI = prior(MBBI);
167 --MBBI;
168 if (!PI->getDesc().isTerminator())
169 break;
170 }
171
172 // During callee-saved restores emission stack frame was not yet finialized
173 // (and thus - the stack size was unknown). Tune the offset having full stack
174 // size in hands.
175 if (StackSize || MFI->hasCalls()) {
176 assert((MBBI->getOpcode() == SystemZ::MOV64rmm ||
177 MBBI->getOpcode() == SystemZ::MOV64rm) &&
178 "Expected to see callee-save register restore code");
179 assert(MF.getRegInfo().isPhysRegUsed(SystemZ::R15D) &&
180 "Invalid stack frame calculation!");
181
182 unsigned i = 0;
183 MachineInstr &MI = *MBBI;
184 while (!MI.getOperand(i).isImm()) {
185 ++i;
186 assert(i < MI.getNumOperands() && "Unexpected restore code!");
187 }
188
189 uint64_t Offset = NumBytes + MI.getOperand(i).getImm();
190 // If Offset does not fit into 20-bit signed displacement field we need to
191 // emit some additional code...
192 if (Offset > 524287) {
193 // Fold the displacement into load instruction as much as possible.
194 NumBytes = Offset - 524287;
195 Offset = 524287;
196 emitSPUpdate(MBB, MBBI, NumBytes, TII);
197 }
198
199 MI.getOperand(i).ChangeToImmediate(Offset);
200 }
201 }
202
getFrameIndexOffset(const MachineFunction & MF,int FI) const203 int SystemZFrameLowering::getFrameIndexOffset(const MachineFunction &MF,
204 int FI) const {
205 const MachineFrameInfo *MFI = MF.getFrameInfo();
206 const SystemZMachineFunctionInfo *SystemZMFI =
207 MF.getInfo<SystemZMachineFunctionInfo>();
208 int Offset = MFI->getObjectOffset(FI) + MFI->getOffsetAdjustment();
209 uint64_t StackSize = MFI->getStackSize();
210
211 // Fixed objects are really located in the "previous" frame.
212 if (FI < 0)
213 StackSize -= SystemZMFI->getCalleeSavedFrameSize();
214
215 Offset += StackSize - getOffsetOfLocalArea();
216
217 // Skip the register save area if we generated the stack frame.
218 if (StackSize || MFI->hasCalls())
219 Offset -= getOffsetOfLocalArea();
220
221 return Offset;
222 }
223
224 bool
spillCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,const std::vector<CalleeSavedInfo> & CSI,const TargetRegisterInfo * TRI) const225 SystemZFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
226 MachineBasicBlock::iterator MI,
227 const std::vector<CalleeSavedInfo> &CSI,
228 const TargetRegisterInfo *TRI) const {
229 if (CSI.empty())
230 return false;
231
232 DebugLoc DL;
233 if (MI != MBB.end()) DL = MI->getDebugLoc();
234
235 MachineFunction &MF = *MBB.getParent();
236 const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
237 SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
238 unsigned CalleeFrameSize = 0;
239
240 // Scan the callee-saved and find the bounds of register spill area.
241 unsigned LowReg = 0, HighReg = 0, StartOffset = -1U, EndOffset = 0;
242 for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
243 unsigned Reg = CSI[i].getReg();
244 if (!SystemZ::FP64RegClass.contains(Reg)) {
245 unsigned Offset = RegSpillOffsets[Reg];
246 CalleeFrameSize += 8;
247 if (StartOffset > Offset) {
248 LowReg = Reg; StartOffset = Offset;
249 }
250 if (EndOffset < Offset) {
251 HighReg = Reg; EndOffset = RegSpillOffsets[Reg];
252 }
253 }
254 }
255
256 // Save information for epilogue inserter.
257 MFI->setCalleeSavedFrameSize(CalleeFrameSize);
258 MFI->setLowReg(LowReg); MFI->setHighReg(HighReg);
259
260 // Save GPRs
261 if (StartOffset) {
262 // Build a store instruction. Use STORE MULTIPLE instruction if there are many
263 // registers to store, otherwise - just STORE.
264 MachineInstrBuilder MIB =
265 BuildMI(MBB, MI, DL, TII.get((LowReg == HighReg ?
266 SystemZ::MOV64mr : SystemZ::MOV64mrm)));
267
268 // Add store operands.
269 MIB.addReg(SystemZ::R15D).addImm(StartOffset);
270 if (LowReg == HighReg)
271 MIB.addReg(0);
272 MIB.addReg(LowReg, RegState::Kill);
273 if (LowReg != HighReg)
274 MIB.addReg(HighReg, RegState::Kill);
275
276 // Do a second scan adding regs as being killed by instruction
277 for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
278 unsigned Reg = CSI[i].getReg();
279 // Add the callee-saved register as live-in. It's killed at the spill.
280 MBB.addLiveIn(Reg);
281 if (Reg != LowReg && Reg != HighReg)
282 MIB.addReg(Reg, RegState::ImplicitKill);
283 }
284 }
285
286 // Save FPRs
287 for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
288 unsigned Reg = CSI[i].getReg();
289 if (SystemZ::FP64RegClass.contains(Reg)) {
290 MBB.addLiveIn(Reg);
291 TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(),
292 &SystemZ::FP64RegClass, TRI);
293 }
294 }
295
296 return true;
297 }
298
299 bool
restoreCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,const std::vector<CalleeSavedInfo> & CSI,const TargetRegisterInfo * TRI) const300 SystemZFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
301 MachineBasicBlock::iterator MI,
302 const std::vector<CalleeSavedInfo> &CSI,
303 const TargetRegisterInfo *TRI) const {
304 if (CSI.empty())
305 return false;
306
307 DebugLoc DL;
308 if (MI != MBB.end()) DL = MI->getDebugLoc();
309
310 MachineFunction &MF = *MBB.getParent();
311 const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
312 SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
313
314 // Restore FP registers
315 for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
316 unsigned Reg = CSI[i].getReg();
317 if (SystemZ::FP64RegClass.contains(Reg))
318 TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(),
319 &SystemZ::FP64RegClass, TRI);
320 }
321
322 // Restore GP registers
323 unsigned LowReg = MFI->getLowReg(), HighReg = MFI->getHighReg();
324 unsigned StartOffset = RegSpillOffsets[LowReg];
325
326 if (StartOffset) {
327 // Build a load instruction. Use LOAD MULTIPLE instruction if there are many
328 // registers to load, otherwise - just LOAD.
329 MachineInstrBuilder MIB =
330 BuildMI(MBB, MI, DL, TII.get((LowReg == HighReg ?
331 SystemZ::MOV64rm : SystemZ::MOV64rmm)));
332 // Add store operands.
333 MIB.addReg(LowReg, RegState::Define);
334 if (LowReg != HighReg)
335 MIB.addReg(HighReg, RegState::Define);
336
337 MIB.addReg(hasFP(MF) ? SystemZ::R11D : SystemZ::R15D);
338 MIB.addImm(StartOffset);
339 if (LowReg == HighReg)
340 MIB.addReg(0);
341
342 // Do a second scan adding regs as being defined by instruction
343 for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
344 unsigned Reg = CSI[i].getReg();
345 if (Reg != LowReg && Reg != HighReg)
346 MIB.addReg(Reg, RegState::ImplicitDefine);
347 }
348 }
349
350 return true;
351 }
352
353 void
processFunctionBeforeCalleeSavedScan(MachineFunction & MF,RegScavenger * RS) const354 SystemZFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
355 RegScavenger *RS) const {
356 // Determine whether R15/R14 will ever be clobbered inside the function. And
357 // if yes - mark it as 'callee' saved.
358 MachineFrameInfo *FFI = MF.getFrameInfo();
359 MachineRegisterInfo &MRI = MF.getRegInfo();
360
361 // Check whether high FPRs are ever used, if yes - we need to save R15 as
362 // well.
363 static const unsigned HighFPRs[] = {
364 SystemZ::F8L, SystemZ::F9L, SystemZ::F10L, SystemZ::F11L,
365 SystemZ::F12L, SystemZ::F13L, SystemZ::F14L, SystemZ::F15L,
366 SystemZ::F8S, SystemZ::F9S, SystemZ::F10S, SystemZ::F11S,
367 SystemZ::F12S, SystemZ::F13S, SystemZ::F14S, SystemZ::F15S,
368 };
369
370 bool HighFPRsUsed = false;
371 for (unsigned i = 0, e = array_lengthof(HighFPRs); i != e; ++i)
372 HighFPRsUsed |= MRI.isPhysRegUsed(HighFPRs[i]);
373
374 if (FFI->hasCalls())
375 /* FIXME: function is varargs */
376 /* FIXME: function grabs RA */
377 /* FIXME: function calls eh_return */
378 MRI.setPhysRegUsed(SystemZ::R14D);
379
380 if (HighFPRsUsed ||
381 FFI->hasCalls() ||
382 FFI->getObjectIndexEnd() != 0 || // Contains automatic variables
383 FFI->hasVarSizedObjects() // Function calls dynamic alloca's
384 /* FIXME: function is varargs */)
385 MRI.setPhysRegUsed(SystemZ::R15D);
386 }
387