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
27#define DEBUG_TYPE "sparc-frame-lowering"
28
31 ST.is64Bit() ? Align(16) : Align(8), 0,
32 ST.is64Bit() ? Align(16) : Align(8),
33 /*StackRealignable=*/false),
34 STI(ST) {}
35
36void SparcFrameLowering::emitSPAdjustment(MachineFunction &MF,
39 const DebugLoc &dl, int NumBytes,
40 unsigned ADDrr,
41 unsigned ADDri) const {
42
43 const SparcInstrInfo &TII =
44 *static_cast<const SparcInstrInfo *>(MF.getSubtarget().getInstrInfo());
45
46 if (NumBytes >= -4096 && NumBytes < 4096) {
47 BuildMI(MBB, MBBI, dl, TII.get(ADDri), SP::O6)
48 .addReg(SP::O6).addImm(NumBytes);
49 return;
50 }
51
52 // Emit this the hard way. This clobbers G1 which we always know is
53 // available here.
54 if (NumBytes >= 0) {
55 // Emit nonnegative numbers with sethi + or.
56 // sethi %hi(NumBytes), %g1
57 // or %g1, %lo(NumBytes), %g1
58 // add %sp, %g1, %sp
59 BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1)
60 .addImm(HI22(NumBytes));
61 BuildMI(MBB, MBBI, dl, TII.get(SP::ORri), SP::G1)
62 .addReg(SP::G1).addImm(LO10(NumBytes));
63 BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6)
64 .addReg(SP::O6).addReg(SP::G1);
65 return ;
66 }
67
68 // Emit negative numbers with sethi + xor.
69 // sethi %hix(NumBytes), %g1
70 // xor %g1, %lox(NumBytes), %g1
71 // add %sp, %g1, %sp
72 BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1)
73 .addImm(HIX22(NumBytes));
74 BuildMI(MBB, MBBI, dl, TII.get(SP::XORri), SP::G1)
75 .addReg(SP::G1).addImm(LOX10(NumBytes));
76 BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6)
77 .addReg(SP::O6).addReg(SP::G1);
78}
79
81 MachineBasicBlock &MBB) const {
83
84 assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
88
89 // Get the number of bytes to allocate from the FrameInfo
90 int NumBytes = (int) MFI.getStackSize();
91
92 unsigned SAVEri = SP::SAVEri;
93 unsigned SAVErr = SP::SAVErr;
94 if (FuncInfo->isLeafProc()) {
95 if (NumBytes == 0)
96 return;
97 SAVEri = SP::ADDri;
98 SAVErr = SP::ADDrr;
99 }
100
101 // The SPARC ABI is a bit odd in that it requires a reserved 92-byte
102 // (128 in v9) area in the user's stack, starting at %sp. Thus, the
103 // first part of the stack that can actually be used is located at
104 // %sp + 92.
105 //
106 // We therefore need to add that offset to the total stack size
107 // after all the stack objects are placed by
108 // PrologEpilogInserter calculateFrameObjectOffsets. However, since the stack needs to be
109 // aligned *after* the extra size is added, we need to disable
110 // calculateFrameObjectOffsets's built-in stack alignment, by having
111 // targetHandlesStackFrameRounding return true.
112
113
114 // Add the extra call frame stack size, if needed. (This is the same
115 // code as in PrologEpilogInserter, but also gets disabled by
116 // targetHandlesStackFrameRounding)
117 if (MFI.adjustsStack() && hasReservedCallFrame(MF))
118 NumBytes += MFI.getMaxCallFrameSize();
119
120 // Adds the SPARC subtarget-specific spill area to the stack
121 // size. Also ensures target-required alignment.
122 NumBytes = Subtarget.getAdjustedFrameSize(NumBytes);
123
124 // Finally, ensure that the size is sufficiently aligned for the
125 // data on the stack.
126 NumBytes = alignTo(NumBytes, MFI.getMaxAlign());
127
128 // Update stack size with corrected value.
129 MFI.setStackSize(NumBytes);
130
131 emitSPAdjustment(MF, MBB, MBBI, DebugLoc(), -NumBytes, SAVErr, SAVEri);
132
133 if (MF.needsFrameMoves()) {
135 if (FuncInfo->isLeafProc()) {
136 CFIBuilder.buildDefCFAOffset(NumBytes + Subtarget.getStackPointerBias());
137 } else {
138 CFIBuilder.buildDefCFARegister(SP::I6);
139 CFIBuilder.buildWindowSave();
140 CFIBuilder.buildRegister(SP::O7, SP::I7);
141 }
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, DebugLoc(), 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)
173 .addReg(SP::G0)
174 .addReg(SP::G0)
176 return;
177 }
178 MachineFrameInfo &MFI = MF.getFrameInfo();
179
180 int NumBytes = (int) MFI.getStackSize();
181 if (NumBytes != 0)
182 emitSPAdjustment(MF, MBB, MBBI, dl, NumBytes, SP::ADDrr, SP::ADDri);
183
184 // Preserve return address in %o7
185 if (MBBI->getOpcode() == SP::TAIL_CALL) {
186 MBB.addLiveIn(SP::O7);
187 BuildMI(MBB, MBBI, dl, TII.get(SP::ORrr), SP::G1)
188 .addReg(SP::G0)
189 .addReg(SP::O7);
190 BuildMI(MBB, MBBI, dl, TII.get(SP::ORrr), SP::O7)
191 .addReg(SP::G0)
192 .addReg(SP::G1)
194 }
195}
196
198 // Reserve call frame if there are no variable sized objects on the stack.
199 return !MF.getFrameInfo().hasVarSizedObjects();
200}
201
202// hasFPImpl - Return true if the specified function should have a dedicated
203// frame pointer register. This is true if the function has variable sized
204// allocas or if frame pointer elimination is disabled.
206 const MachineFrameInfo &MFI = MF.getFrameInfo();
207 return MF.disableFramePointerElim() || MFI.hasVarSizedObjects() ||
209}
210
213 Register &FrameReg) const {
215 const MachineFrameInfo &MFI = MF.getFrameInfo();
216 const SparcRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
218 bool isFixed = MFI.isFixedObjectIndex(FI);
219
220 // Addressable stack objects are accessed using neg. offsets from
221 // %fp, or positive offsets from %sp.
222 bool UseFP;
223
224 // Sparc uses FP-based references in general, even when "hasFP" is
225 // false. That function is rather a misnomer, because %fp is
226 // actually always available, unless isLeafProc.
227 if (FuncInfo->isLeafProc()) {
228 // If there's a leaf proc, all offsets need to be %sp-based,
229 // because we haven't caused %fp to actually point to our frame.
230 UseFP = false;
231 } else if (isFixed) {
232 // Otherwise, argument access should always use %fp.
233 UseFP = true;
234 } else {
235 // Finally, default to using %fp.
236 UseFP = true;
237 }
238
239 int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI) +
240 Subtarget.getStackPointerBias();
241
242 if (UseFP) {
243 FrameReg = RegInfo->getFrameRegister(MF);
244 return StackOffset::getFixed(FrameOffset);
245 } else {
246 FrameReg = SP::O6; // %sp
247 return StackOffset::getFixed(FrameOffset + MF.getFrameInfo().getStackSize());
248 }
249}
250
251[[maybe_unused]] static bool verifyLeafProcRegUse(MachineRegisterInfo *MRI) {
252
253 for (unsigned reg = SP::I0; reg <= SP::I7; ++reg)
254 if (MRI->isPhysRegUsed(reg))
255 return false;
256
257 for (unsigned reg = SP::L0; reg <= SP::L7; ++reg)
258 if (MRI->isPhysRegUsed(reg))
259 return false;
260
261 return true;
262}
263
264bool SparcFrameLowering::isLeafProc(MachineFunction &MF) const
265{
266
267 MachineRegisterInfo &MRI = MF.getRegInfo();
268 MachineFrameInfo &MFI = MF.getFrameInfo();
269 SparcMachineFunctionInfo *SMFI = MF.getInfo<SparcMachineFunctionInfo>();
270
271 return !(MFI.hasCalls() // has calls
272 || MRI.isPhysRegUsed(SP::L0) // Too many registers needed
273 || MRI.isPhysRegUsed(SP::O6) // %sp is used
274 || hasFP(MF) // need %fp
275 || MF.hasInlineAsm() // has inline assembly
276 || SMFI->isLargeProc()); // is a large procedure
277}
278
279void SparcFrameLowering::remapRegsForLeafProc(MachineFunction &MF) const {
280 MachineRegisterInfo &MRI = MF.getRegInfo();
281 SmallVector<MCRegister, 2> UntrackedLiveIns;
282
283 // Remap %i[0-7] to %o[0-7].
284 for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) {
285 if (!MRI.isPhysRegUsed(reg))
286 continue;
287
288 unsigned mapped_reg = reg - SP::I0 + SP::O0;
289
290 // Reserved registers are not tracked by liveness
291 if (MRI.isReserved(reg) && !MRI.isReserved(mapped_reg))
292 UntrackedLiveIns.push_back(mapped_reg);
293
294 // Replace I register with O register.
295 MRI.replaceRegWith(reg, mapped_reg);
296
297 // Also replace register pair super-registers.
298 if ((reg - SP::I0) % 2 == 0) {
299 unsigned preg = (reg - SP::I0) / 2 + SP::I0_I1;
300 unsigned mapped_preg = preg - SP::I0_I1 + SP::O0_O1;
301 MRI.replaceRegWith(preg, mapped_preg);
302 }
303 }
304
305 // Rewrite MBB's Live-ins.
306 for (MachineBasicBlock &MBB : MF) {
307 for (unsigned reg = SP::I0_I1; reg <= SP::I6_I7; ++reg) {
308 if (!MBB.isLiveIn(reg))
309 continue;
310 MBB.removeLiveIn(reg);
311 MBB.addLiveIn(reg - SP::I0_I1 + SP::O0_O1);
312 }
313 for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) {
314 if (!MBB.isLiveIn(reg))
315 continue;
316 MBB.removeLiveIn(reg);
317 MBB.addLiveIn(reg - SP::I0 + SP::O0);
318 }
319 for (MCRegister Reg : UntrackedLiveIns)
320 if (!MBB.isLiveIn(Reg))
322 }
323 for (MCRegister Reg : UntrackedLiveIns)
325
327#ifdef EXPENSIVE_CHECKS
328 MF.verify(0, "After LeafProc Remapping");
329#endif
330}
331
333 const MachineFunction &MF) {
334 uint64_t FuncSize = 0;
335 for (auto &MBB : MF)
336 for (auto &MI : MBB) {
337 // Be conservative here and count the DS too.
338 uint64_t Multiplier = MI.hasDelaySlot() ? 2 : 1;
339 FuncSize += (TII->getInstSizeInBytes(MI) * Multiplier);
340 }
341 return FuncSize;
342}
343
345 BitVector &SavedRegs,
346 RegScavenger *RS) const {
349 const SparcInstrInfo *TII = STI.getInstrInfo();
351
352 bool IsLargeFunction = !isInt<23>(estimateFunctionSizeInBytes(TII, MF));
353 MFI->setLargeProc(IsLargeFunction);
354
355 if (!Subtarget.getCLOpts().disable_sparc_leaf_proc && isLeafProc(MF)) {
356 MFI->setLeafProc(true);
357
358 remapRegsForLeafProc(MF);
359 }
360}
361
363 MachineFunction &MF, RegScavenger *RS) const {
364 const SparcRegisterInfo *RI = STI.getRegisterInfo();
365 const TargetRegisterClass &RC =
366 STI.is64Bit() ? SP::I64RegsRegClass : SP::IntRegsRegClass;
367 MachineFrameInfo &MFI = MF.getFrameInfo();
369
370 // Far branches beyond 23-bit offset require a spill slot for scratch
371 // register.
372 if (SMFI->isLargeProc()) {
373 int FI =
374 MFI.CreateSpillStackObject(RI->getSpillSize(RC), RI->getSpillAlign(RC));
375 RS->addScavengingFrameIndex(FI);
376 if (SMFI->getBranchRelaxationSpillFrameIndex() == -1)
378 LLVM_DEBUG(dbgs() << "Allocated FI(" << FI
379 << ") as the emergency spill slot.\n");
380 }
381}
382
384 MachineFunction &MF, RegScavenger *RS) const {
386 return;
387
388 // PEI takes the entry block's parameter DBG_VALUEs out of the function
389 // while determineCalleeSaves runs, so remapRegsForLeafProc missed them.
391 auto Remap = [&MRI](unsigned Reg, unsigned MappedReg) {
392 for (MachineOperand &MO : make_early_inc_range(MRI.reg_operands(Reg)))
393 if (MO.isDebug())
394 MO.setReg(MappedReg);
395 };
396 for (unsigned Reg = SP::I0; Reg <= SP::I7; ++Reg)
397 Remap(Reg, Reg - SP::I0 + SP::O0);
398 for (unsigned Reg = SP::I0_I1; Reg <= SP::I6_I7; ++Reg)
399 Remap(Reg, Reg - SP::I0_I1 + SP::O0_O1);
400}
const AArch64Subtarget & Subtarget
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator MBBI
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
static uint64_t estimateFunctionSizeInBytes(const LoongArchInstrInfo *TII, const MachineFunction &MF)
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
MachineRegisterInfo & MRI
This file declares the machine register scavenger class.
static bool verifyLeafProcRegUse(MachineRegisterInfo *MRI)
#define LLVM_DEBUG(...)
Definition Debug.h:119
static bool is64Bit(const char *name)
Helper class for creating CFI instructions and inserting them into MIR.
void buildDefCFAOffset(int64_t Offset, MCSymbol *Label=nullptr) const
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.
LLVM_ABI int CreateSpillStackObject(uint64_t Size, Align Alignment, TargetStackID::Value StackID=TargetStackID::Default)
Create a new statically sized stack object that represents a spill slot, returning a nonnegative iden...
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.
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 & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
bool isReserved(MCRegister PhysReg) const
isReserved - Returns true when PhysReg is a reserved register.
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 push_back(const T &Elt)
void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS) const override
processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...
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 processFunctionBeforeFrameIndicesReplaced(MachineFunction &MF, RegScavenger *RS) const override
processFunctionBeforeFrameIndicesReplaced - This method is called immediately before MO_FrameIndex op...
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,...
StackOffset holds a fixed and a scalable offset in bytes.
Definition TypeSize.h:31
int64_t getFixed() const
Returns the fixed component of the stack.
Definition TypeSize.h:47
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)
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.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
static unsigned HI22(int64_t imm)
Definition Sparc.h:202
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:649
static unsigned HIX22(int64_t imm)
Definition Sparc.h:210
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:149
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
static unsigned LOX10(int64_t imm)
Definition Sparc.h:214
static unsigned LO10(int64_t imm)
Definition Sparc.h:206
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39