LLVM 24.0.0git
SparcFrameLowering.cpp
Go to the documentation of this file.
1//===-- SparcFrameLowering.cpp - Sparc Frame Information ------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the Sparc implementation of TargetFrameLowering class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "SparcFrameLowering.h"
14#include "SparcInstrInfo.h"
16#include "SparcSubtarget.h"
24
25using namespace llvm;
26
27static cl::opt<bool>
28DisableLeafProc("disable-sparc-leaf-proc",
29 cl::init(false),
30 cl::desc("Disable Sparc leaf procedure optimization."),
32
35 ST.is64Bit() ? Align(16) : Align(8), 0,
36 ST.is64Bit() ? Align(16) : Align(8),
37 /*StackRealignable=*/false) {}
38
39void SparcFrameLowering::emitSPAdjustment(MachineFunction &MF,
42 int NumBytes,
43 unsigned ADDrr,
44 unsigned ADDri) const {
45
46 DebugLoc dl;
47 const SparcInstrInfo &TII =
48 *static_cast<const SparcInstrInfo *>(MF.getSubtarget().getInstrInfo());
49
50 if (NumBytes >= -4096 && NumBytes < 4096) {
51 BuildMI(MBB, MBBI, dl, TII.get(ADDri), SP::O6)
52 .addReg(SP::O6).addImm(NumBytes);
53 return;
54 }
55
56 // Emit this the hard way. This clobbers G1 which we always know is
57 // available here.
58 if (NumBytes >= 0) {
59 // Emit nonnegative numbers with sethi + or.
60 // sethi %hi(NumBytes), %g1
61 // or %g1, %lo(NumBytes), %g1
62 // add %sp, %g1, %sp
63 BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1)
64 .addImm(HI22(NumBytes));
65 BuildMI(MBB, MBBI, dl, TII.get(SP::ORri), SP::G1)
66 .addReg(SP::G1).addImm(LO10(NumBytes));
67 BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6)
68 .addReg(SP::O6).addReg(SP::G1);
69 return ;
70 }
71
72 // Emit negative numbers with sethi + xor.
73 // sethi %hix(NumBytes), %g1
74 // xor %g1, %lox(NumBytes), %g1
75 // add %sp, %g1, %sp
76 BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1)
77 .addImm(HIX22(NumBytes));
78 BuildMI(MBB, MBBI, dl, TII.get(SP::XORri), SP::G1)
79 .addReg(SP::G1).addImm(LOX10(NumBytes));
80 BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6)
81 .addReg(SP::O6).addReg(SP::G1);
82}
83
85 MachineBasicBlock &MBB) const {
87
88 assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
90 const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>();
92
93 // Get the number of bytes to allocate from the FrameInfo
94 int NumBytes = (int) MFI.getStackSize();
95
96 unsigned SAVEri = SP::SAVEri;
97 unsigned SAVErr = SP::SAVErr;
98 if (FuncInfo->isLeafProc()) {
99 if (NumBytes == 0)
100 return;
101 SAVEri = SP::ADDri;
102 SAVErr = SP::ADDrr;
103 }
104
105 // The SPARC ABI is a bit odd in that it requires a reserved 92-byte
106 // (128 in v9) area in the user's stack, starting at %sp. Thus, the
107 // first part of the stack that can actually be used is located at
108 // %sp + 92.
109 //
110 // We therefore need to add that offset to the total stack size
111 // after all the stack objects are placed by
112 // PrologEpilogInserter calculateFrameObjectOffsets. However, since the stack needs to be
113 // aligned *after* the extra size is added, we need to disable
114 // calculateFrameObjectOffsets's built-in stack alignment, by having
115 // targetHandlesStackFrameRounding return true.
116
117
118 // Add the extra call frame stack size, if needed. (This is the same
119 // code as in PrologEpilogInserter, but also gets disabled by
120 // targetHandlesStackFrameRounding)
121 if (MFI.adjustsStack() && hasReservedCallFrame(MF))
122 NumBytes += MFI.getMaxCallFrameSize();
123
124 // Adds the SPARC subtarget-specific spill area to the stack
125 // size. Also ensures target-required alignment.
126 NumBytes = Subtarget.getAdjustedFrameSize(NumBytes);
127
128 // Finally, ensure that the size is sufficiently aligned for the
129 // data on the stack.
130 NumBytes = alignTo(NumBytes, MFI.getMaxAlign());
131
132 // Update stack size with corrected value.
133 MFI.setStackSize(NumBytes);
134
135 emitSPAdjustment(MF, MBB, MBBI, -NumBytes, SAVErr, SAVEri);
136
137 if (MF.needsFrameMoves()) {
139 CFIBuilder.buildDefCFARegister(SP::I6);
140 CFIBuilder.buildWindowSave();
141 CFIBuilder.buildRegister(SP::O7, SP::I7);
142 }
143}
144
148 if (!hasReservedCallFrame(MF)) {
149 MachineInstr &MI = *I;
150 int Size = MI.getOperand(0).getImm();
151 if (MI.getOpcode() == SP::ADJCALLSTACKDOWN)
152 Size = -Size;
153
154 if (Size)
155 emitSPAdjustment(MF, MBB, I, Size, SP::ADDrr, SP::ADDri);
156 }
157 return MBB.erase(I);
158}
159
160
162 MachineBasicBlock &MBB) const {
164 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
165 const SparcInstrInfo &TII =
166 *static_cast<const SparcInstrInfo *>(MF.getSubtarget().getInstrInfo());
167 DebugLoc dl = MBBI->getDebugLoc();
168 assert((MBBI->getOpcode() == SP::RETL || MBBI->getOpcode() == SP::TAIL_CALL ||
169 MBBI->getOpcode() == SP::TAIL_CALLri) &&
170 "Can only put epilog before 'retl' or 'tail_call' instruction!");
171 if (!FuncInfo->isLeafProc()) {
172 BuildMI(MBB, MBBI, dl, TII.get(SP::RESTORErr), SP::G0).addReg(SP::G0)
173 .addReg(SP::G0);
174 return;
175 }
176 MachineFrameInfo &MFI = MF.getFrameInfo();
177
178 int NumBytes = (int) MFI.getStackSize();
179 if (NumBytes != 0)
180 emitSPAdjustment(MF, MBB, MBBI, NumBytes, SP::ADDrr, SP::ADDri);
181
182 // Preserve return address in %o7
183 if (MBBI->getOpcode() == SP::TAIL_CALL) {
184 MBB.addLiveIn(SP::O7);
185 BuildMI(MBB, MBBI, dl, TII.get(SP::ORrr), SP::G1)
186 .addReg(SP::G0)
187 .addReg(SP::O7);
188 BuildMI(MBB, MBBI, dl, TII.get(SP::ORrr), SP::O7)
189 .addReg(SP::G0)
190 .addReg(SP::G1);
191 }
192}
193
195 // Reserve call frame if there are no variable sized objects on the stack.
196 return !MF.getFrameInfo().hasVarSizedObjects();
197}
198
199// hasFPImpl - Return true if the specified function should have a dedicated
200// frame pointer register. This is true if the function has variable sized
201// allocas or if frame pointer elimination is disabled.
203 const MachineFrameInfo &MFI = MF.getFrameInfo();
204 return MF.disableFramePointerElim() || MFI.hasVarSizedObjects() ||
206}
207
210 Register &FrameReg) const {
211 const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>();
212 const MachineFrameInfo &MFI = MF.getFrameInfo();
213 const SparcRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
215 bool isFixed = MFI.isFixedObjectIndex(FI);
216
217 // Addressable stack objects are accessed using neg. offsets from
218 // %fp, or positive offsets from %sp.
219 bool UseFP;
220
221 // Sparc uses FP-based references in general, even when "hasFP" is
222 // false. That function is rather a misnomer, because %fp is
223 // actually always available, unless isLeafProc.
224 if (FuncInfo->isLeafProc()) {
225 // If there's a leaf proc, all offsets need to be %sp-based,
226 // because we haven't caused %fp to actually point to our frame.
227 UseFP = false;
228 } else if (isFixed) {
229 // Otherwise, argument access should always use %fp.
230 UseFP = true;
231 } else {
232 // Finally, default to using %fp.
233 UseFP = true;
234 }
235
236 int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI) +
237 Subtarget.getStackPointerBias();
238
239 if (UseFP) {
240 FrameReg = RegInfo->getFrameRegister(MF);
241 return StackOffset::getFixed(FrameOffset);
242 } else {
243 FrameReg = SP::O6; // %sp
244 return StackOffset::getFixed(FrameOffset + MF.getFrameInfo().getStackSize());
245 }
246}
247
248[[maybe_unused]] static bool verifyLeafProcRegUse(MachineRegisterInfo *MRI) {
249
250 for (unsigned reg = SP::I0; reg <= SP::I7; ++reg)
251 if (MRI->isPhysRegUsed(reg))
252 return false;
253
254 for (unsigned reg = SP::L0; reg <= SP::L7; ++reg)
255 if (MRI->isPhysRegUsed(reg))
256 return false;
257
258 return true;
259}
260
261bool SparcFrameLowering::isLeafProc(MachineFunction &MF) const
262{
263
264 MachineRegisterInfo &MRI = MF.getRegInfo();
265 MachineFrameInfo &MFI = MF.getFrameInfo();
266
267 return !(MFI.hasCalls() // has calls
268 || MRI.isPhysRegUsed(SP::L0) // Too many registers needed
269 || MRI.isPhysRegUsed(SP::O6) // %sp is used
270 || hasFP(MF) // need %fp
271 || MF.hasInlineAsm()); // has inline assembly
272}
273
274void SparcFrameLowering::remapRegsForLeafProc(MachineFunction &MF) const {
275 MachineRegisterInfo &MRI = MF.getRegInfo();
276 // Remap %i[0-7] to %o[0-7].
277 for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) {
278 if (!MRI.isPhysRegUsed(reg))
279 continue;
280
281 unsigned mapped_reg = reg - SP::I0 + SP::O0;
282
283 // Replace I register with O register.
284 MRI.replaceRegWith(reg, mapped_reg);
285
286 // Also replace register pair super-registers.
287 if ((reg - SP::I0) % 2 == 0) {
288 unsigned preg = (reg - SP::I0) / 2 + SP::I0_I1;
289 unsigned mapped_preg = preg - SP::I0_I1 + SP::O0_O1;
290 MRI.replaceRegWith(preg, mapped_preg);
291 }
292 }
293
294 // Rewrite MBB's Live-ins.
295 for (MachineBasicBlock &MBB : MF) {
296 for (unsigned reg = SP::I0_I1; reg <= SP::I6_I7; ++reg) {
297 if (!MBB.isLiveIn(reg))
298 continue;
299 MBB.removeLiveIn(reg);
300 MBB.addLiveIn(reg - SP::I0_I1 + SP::O0_O1);
301 }
302 for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) {
303 if (!MBB.isLiveIn(reg))
304 continue;
305 MBB.removeLiveIn(reg);
306 MBB.addLiveIn(reg - SP::I0 + SP::O0);
307 }
308 }
309
311#ifdef EXPENSIVE_CHECKS
312 MF.verify(0, "After LeafProc Remapping");
313#endif
314}
315
317 BitVector &SavedRegs,
318 RegScavenger *RS) const {
320 if (!DisableLeafProc && isLeafProc(MF)) {
322 MFI->setLeafProc(true);
323
324 remapRegsForLeafProc(MF);
325 }
326
327}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator MBBI
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
static cl::opt< bool > DisableLeafProc("disable-sparc-leaf-proc", cl::init(false), cl::desc("Disable Sparc leaf procedure optimization."), cl::Hidden)
static bool verifyLeafProcRegUse(MachineRegisterInfo *MRI)
static bool is64Bit(const char *name)
Helper class for creating CFI instructions and inserting them into MIR.
void buildWindowSave() const
void buildRegister(MCRegister Reg1, MCRegister Reg2) const
void buildDefCFARegister(MCRegister Reg) const
A debug info location.
Definition DebugLoc.h:126
LLVM_ABI void removeLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll())
Remove the specified register from the live in set.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI bool isLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
bool adjustsStack() const
Return true if this function adjusts the stack – e.g., when calling another function.
bool hasCalls() const
Return true if the current function has any function calls.
bool isFrameAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
Align getMaxAlign() const
Return alignment of this function's frame.
uint64_t getMaxCallFrameSize() const
Return the maximum size of a call frame that must be allocated for an outgoing function call.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
void setStackSize(uint64_t Size)
Set the size of the stack.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
bool hasInlineAsm() const
Returns true if the function contains any inline assembly.
bool needsFrameMoves() const
True if this function needs frame moves for debug or exceptions.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
LLVM_ABI bool disableFramePointerElim() const
Returns true if frame pointer elimination should be disabled for this function.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineBasicBlock & front() const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Representation of each machine instruction.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
LLVM_ABI bool isPhysRegUsed(MCRegister PhysReg, bool SkipRegMaskTest=false) const
Return true if the specified register is modified or read in this function.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
SparcFrameLowering(const SparcSubtarget &ST)
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const override
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
bool hasFPImpl(const MachineFunction &MF) const override
StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const override
getFrameIndexReference - This method should return the base register and offset used to reference a f...
MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const override
This method is called during prolog/epilog code insertion to eliminate call frame setup and destroy p...
bool hasReservedCallFrame(const MachineFunction &MF) const override
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required,...
const SparcRegisterInfo * getRegisterInfo() const override
int64_t getStackPointerBias() const
The 64-bit ABI uses biased stack and frame pointers, so the stack frame of the current function is th...
int getAdjustedFrameSize(int stackSize) const
Given a actual stack size as determined by FrameInfo, this function returns adjusted framesize which ...
StackOffset holds a fixed and a scalable offset in bytes.
Definition TypeSize.h:30
int64_t getFixed() const
Returns the fixed component of the stack.
Definition TypeSize.h:46
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
TargetFrameLowering(StackDirection D, Align StackAl, int LAO, Align TransAl=Align(1), bool StackReal=true)
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static unsigned HI22(int64_t imm)
Definition Sparc.h:173
static unsigned HIX22(int64_t imm)
Definition Sparc.h:181
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
static unsigned LOX10(int64_t imm)
Definition Sparc.h:185
static unsigned LO10(int64_t imm)
Definition Sparc.h:177
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39