1 //=====- SystemZFrameInfo.cpp - SystemZ Frame Information ------*- C++ -*-====//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains the SystemZ implementation of TargetFrameInfo class.
12 //===----------------------------------------------------------------------===//
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"
30 SystemZFrameInfo::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 }
50 RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS);
52 for (unsigned i = 0, e = array_lengthof(SpillOffsTab); i != e; ++i)
53 RegSpillOffsets[SpillOffsTab[i][0]] = SpillOffsTab[i][1];
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.
59 bool SystemZFrameInfo::hasFP(const MachineFunction &MF) const {
60 const MachineFrameInfo *MFI = MF.getFrameInfo();
61 return DisableFramePointerElim(MF) || MFI->hasVarSizedObjects();
64 /// emitSPUpdate - Emit a series of instructions to increment / decrement the
65 /// stack pointer by a constant value.
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;
73 if (Offset >= (1LL << 15) - 1) {
74 Opc = SystemZ::ADD64ri32;
75 Chunk = (1LL << 31) - 1;
77 Opc = SystemZ::ADD64ri16;
78 Chunk = (1LL << 15) - 1;
81 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
84 uint64_t ThisVal = (Offset > Chunk) ? Chunk : Offset;
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();
94 void 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();
98 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();
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();
111 uint64_t NumBytes = StackSize - TFI.getOffsetOfLocalArea();
113 // Skip the callee-saved push instructions.
114 while (MBBI != MBB.end() &&
115 (MBBI->getOpcode() == SystemZ::MOV64mr ||
116 MBBI->getOpcode() == SystemZ::MOV64mrm))
119 if (MBBI != MBB.end())
120 DL = MBBI->getDebugLoc();
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);
130 // Update R11 with the new base value...
131 BuildMI(MBB, MBBI, DL, TII.get(SystemZ::MOV64rr), SystemZ::R11D)
132 .addReg(SystemZ::R15D);
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();
137 I->addLiveIn(SystemZ::R11D);
142 void 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();
154 case SystemZ::RET: break; // These are ok
156 assert(0 && "Can only insert epilog into returning blocks");
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.
163 MFI->getStackSize() - SystemZMFI->getCalleeSavedFrameSize();
164 uint64_t NumBytes = StackSize - TFI.getOffsetOfLocalArea();
166 // Skip the final terminator instruction.
167 while (MBBI != MBB.begin()) {
168 MachineBasicBlock::iterator PI = prior(MBBI);
170 if (!PI->getDesc().isTerminator())
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
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!");
185 MachineInstr &MI = *MBBI;
186 while (!MI.getOperand(i).isImm()) {
188 assert(i < MI.getNumOperands() && "Unexpected restore code!");
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;
198 emitSPUpdate(MBB, MBBI, NumBytes, TII);
201 MI.getOperand(i).ChangeToImmediate(Offset);
205 int SystemZFrameInfo::getFrameIndexOffset(const MachineFunction &MF,
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();
213 // Fixed objects are really located in the "previous" frame.
215 StackSize -= SystemZMFI->getCalleeSavedFrameSize();
217 Offset += StackSize - getOffsetOfLocalArea();
219 // Skip the register save area if we generated the stack frame.
220 if (StackSize || MFI->hasCalls())
221 Offset -= getOffsetOfLocalArea();
227 SystemZFrameInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
228 MachineBasicBlock::iterator MI,
229 const std::vector<CalleeSavedInfo> &CSI,
230 const TargetRegisterInfo *TRI) const {
235 if (MI != MBB.end()) DL = MI->getDebugLoc();
237 MachineFunction &MF = *MBB.getParent();
238 const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
239 SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
240 unsigned CalleeFrameSize = 0;
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;
252 if (EndOffset < Offset) {
253 HighReg = Reg; EndOffset = RegSpillOffsets[Reg];
258 // Save information for epilogue inserter.
259 MFI->setCalleeSavedFrameSize(CalleeFrameSize);
260 MFI->setLowReg(LowReg); MFI->setHighReg(HighReg);
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)));
270 // Add store operands.
271 MIB.addReg(SystemZ::R15D).addImm(StartOffset);
272 if (LowReg == HighReg)
274 MIB.addReg(LowReg, RegState::Kill);
275 if (LowReg != HighReg)
276 MIB.addReg(HighReg, RegState::Kill);
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.
283 if (Reg != LowReg && Reg != HighReg)
284 MIB.addReg(Reg, RegState::ImplicitKill);
289 for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
290 unsigned Reg = CSI[i].getReg();
291 if (SystemZ::FP64RegClass.contains(Reg)) {
293 TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(),
294 &SystemZ::FP64RegClass, TRI);
302 SystemZFrameInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
303 MachineBasicBlock::iterator MI,
304 const std::vector<CalleeSavedInfo> &CSI,
305 const TargetRegisterInfo *TRI) const {
310 if (MI != MBB.end()) DL = MI->getDebugLoc();
312 MachineFunction &MF = *MBB.getParent();
313 const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
314 SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
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);
324 // Restore GP registers
325 unsigned LowReg = MFI->getLowReg(), HighReg = MFI->getHighReg();
326 unsigned StartOffset = RegSpillOffsets[LowReg];
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);
339 MIB.addReg(hasFP(MF) ? SystemZ::R11D : SystemZ::R15D);
340 MIB.addImm(StartOffset);
341 if (LowReg == HighReg)
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);