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 int NumBytes,
40 unsigned ADDrr,
41 unsigned ADDri) const {
42
43 DebugLoc dl;
44 const SparcInstrInfo &TII =
45 *static_cast<const SparcInstrInfo *>(MF.getSubtarget().getInstrInfo());
46
47 if (NumBytes >= -4096 && NumBytes < 4096) {
48 BuildMI(MBB, MBBI, dl, TII.get(ADDri), SP::O6)
49 .addReg(SP::O6).addImm(NumBytes);
50 return;
51 }
52
53 // Emit this the hard way. This clobbers G1 which we always know is
54 // available here.
55 if (NumBytes >= 0) {
56 // Emit nonnegative numbers with sethi + or.
57 // sethi %hi(NumBytes), %g1
58 // or %g1, %lo(NumBytes), %g1
59 // add %sp, %g1, %sp
60 BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1)
61 .addImm(HI22(NumBytes));
62 BuildMI(MBB, MBBI, dl, TII.get(SP::ORri), SP::G1)
63 .addReg(SP::G1).addImm(LO10(NumBytes));
64 BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6)
65 .addReg(SP::O6).addReg(SP::G1);
66 return ;
67 }
68
69 // Emit negative numbers with sethi + xor.
70 // sethi %hix(NumBytes), %g1
71 // xor %g1, %lox(NumBytes), %g1
72 // add %sp, %g1, %sp
73 BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1)
74 .addImm(HIX22(NumBytes));
75 BuildMI(MBB, MBBI, dl, TII.get(SP::XORri), SP::G1)
76 .addReg(SP::G1).addImm(LOX10(NumBytes));
77 BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6)
78 .addReg(SP::O6).addReg(SP::G1);
79}
80
82 MachineBasicBlock &MBB) const {
84
85 assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
87 const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>();
89
90 // Get the number of bytes to allocate from the FrameInfo
91 int NumBytes = (int) MFI.getStackSize();
92
93 unsigned SAVEri = SP::SAVEri;
94 unsigned SAVErr = SP::SAVErr;
95 if (FuncInfo->isLeafProc()) {
96 if (NumBytes == 0)
97 return;
98 SAVEri = SP::ADDri;
99 SAVErr = SP::ADDrr;
100 }
101
102 // The SPARC ABI is a bit odd in that it requires a reserved 92-byte
103 // (128 in v9) area in the user's stack, starting at %sp. Thus, the
104 // first part of the stack that can actually be used is located at
105 // %sp + 92.
106 //
107 // We therefore need to add that offset to the total stack size
108 // after all the stack objects are placed by
109 // PrologEpilogInserter calculateFrameObjectOffsets. However, since the stack needs to be
110 // aligned *after* the extra size is added, we need to disable
111 // calculateFrameObjectOffsets's built-in stack alignment, by having
112 // targetHandlesStackFrameRounding return true.
113
114
115 // Add the extra call frame stack size, if needed. (This is the same
116 // code as in PrologEpilogInserter, but also gets disabled by
117 // targetHandlesStackFrameRounding)
118 if (MFI.adjustsStack() && hasReservedCallFrame(MF))
119 NumBytes += MFI.getMaxCallFrameSize();
120
121 // Adds the SPARC subtarget-specific spill area to the stack
122 // size. Also ensures target-required alignment.
123 NumBytes = Subtarget.getAdjustedFrameSize(NumBytes);
124
125 // Finally, ensure that the size is sufficiently aligned for the
126 // data on the stack.
127 NumBytes = alignTo(NumBytes, MFI.getMaxAlign());
128
129 // Update stack size with corrected value.
130 MFI.setStackSize(NumBytes);
131
132 emitSPAdjustment(MF, MBB, MBBI, -NumBytes, SAVErr, SAVEri);
133
134 if (MF.needsFrameMoves()) {
136 CFIBuilder.buildDefCFARegister(SP::I6);
137 CFIBuilder.buildWindowSave();
138 CFIBuilder.buildRegister(SP::O7, SP::I7);
139 }
140}
141
145 if (!hasReservedCallFrame(MF)) {
146 MachineInstr &MI = *I;
147 int Size = MI.getOperand(0).getImm();
148 if (MI.getOpcode() == SP::ADJCALLSTACKDOWN)
149 Size = -Size;
150
151 if (Size)
152 emitSPAdjustment(MF, MBB, I, Size, SP::ADDrr, SP::ADDri);
153 }
154 return MBB.erase(I);
155}
156
157
159 MachineBasicBlock &MBB) const {
161 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
162 const SparcInstrInfo &TII =
163 *static_cast<const SparcInstrInfo *>(MF.getSubtarget().getInstrInfo());
164 DebugLoc dl = MBBI->getDebugLoc();
165 assert((MBBI->getOpcode() == SP::RETL || MBBI->getOpcode() == SP::TAIL_CALL ||
166 MBBI->getOpcode() == SP::TAIL_CALLri) &&
167 "Can only put epilog before 'retl' or 'tail_call' instruction!");
168 if (!FuncInfo->isLeafProc()) {
169 BuildMI(MBB, MBBI, dl, TII.get(SP::RESTORErr), SP::G0).addReg(SP::G0)
170 .addReg(SP::G0);
171 return;
172 }
173 MachineFrameInfo &MFI = MF.getFrameInfo();
174
175 int NumBytes = (int) MFI.getStackSize();
176 if (NumBytes != 0)
177 emitSPAdjustment(MF, MBB, MBBI, NumBytes, SP::ADDrr, SP::ADDri);
178
179 // Preserve return address in %o7
180 if (MBBI->getOpcode() == SP::TAIL_CALL) {
181 MBB.addLiveIn(SP::O7);
182 BuildMI(MBB, MBBI, dl, TII.get(SP::ORrr), SP::G1)
183 .addReg(SP::G0)
184 .addReg(SP::O7);
185 BuildMI(MBB, MBBI, dl, TII.get(SP::ORrr), SP::O7)
186 .addReg(SP::G0)
187 .addReg(SP::G1);
188 }
189}
190
192 // Reserve call frame if there are no variable sized objects on the stack.
193 return !MF.getFrameInfo().hasVarSizedObjects();
194}
195
196// hasFPImpl - Return true if the specified function should have a dedicated
197// frame pointer register. This is true if the function has variable sized
198// allocas or if frame pointer elimination is disabled.
200 const MachineFrameInfo &MFI = MF.getFrameInfo();
201 return MF.disableFramePointerElim() || MFI.hasVarSizedObjects() ||
203}
204
207 Register &FrameReg) const {
208 const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>();
209 const MachineFrameInfo &MFI = MF.getFrameInfo();
210 const SparcRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
212 bool isFixed = MFI.isFixedObjectIndex(FI);
213
214 // Addressable stack objects are accessed using neg. offsets from
215 // %fp, or positive offsets from %sp.
216 bool UseFP;
217
218 // Sparc uses FP-based references in general, even when "hasFP" is
219 // false. That function is rather a misnomer, because %fp is
220 // actually always available, unless isLeafProc.
221 if (FuncInfo->isLeafProc()) {
222 // If there's a leaf proc, all offsets need to be %sp-based,
223 // because we haven't caused %fp to actually point to our frame.
224 UseFP = false;
225 } else if (isFixed) {
226 // Otherwise, argument access should always use %fp.
227 UseFP = true;
228 } else {
229 // Finally, default to using %fp.
230 UseFP = true;
231 }
232
233 int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI) +
234 Subtarget.getStackPointerBias();
235
236 if (UseFP) {
237 FrameReg = RegInfo->getFrameRegister(MF);
238 return StackOffset::getFixed(FrameOffset);
239 } else {
240 FrameReg = SP::O6; // %sp
241 return StackOffset::getFixed(FrameOffset + MF.getFrameInfo().getStackSize());
242 }
243}
244
245[[maybe_unused]] static bool verifyLeafProcRegUse(MachineRegisterInfo *MRI) {
246
247 for (unsigned reg = SP::I0; reg <= SP::I7; ++reg)
248 if (MRI->isPhysRegUsed(reg))
249 return false;
250
251 for (unsigned reg = SP::L0; reg <= SP::L7; ++reg)
252 if (MRI->isPhysRegUsed(reg))
253 return false;
254
255 return true;
256}
257
258bool SparcFrameLowering::isLeafProc(MachineFunction &MF) const
259{
260
261 MachineRegisterInfo &MRI = MF.getRegInfo();
262 MachineFrameInfo &MFI = MF.getFrameInfo();
263 SparcMachineFunctionInfo *SMFI = MF.getInfo<SparcMachineFunctionInfo>();
264
265 return !(MFI.hasCalls() // has calls
266 || MRI.isPhysRegUsed(SP::L0) // Too many registers needed
267 || MRI.isPhysRegUsed(SP::O6) // %sp is used
268 || hasFP(MF) // need %fp
269 || MF.hasInlineAsm() // has inline assembly
270 || SMFI->isLargeProc()); // is a large procedure
271}
272
273void SparcFrameLowering::remapRegsForLeafProc(MachineFunction &MF) const {
274 MachineRegisterInfo &MRI = MF.getRegInfo();
275 // Remap %i[0-7] to %o[0-7].
276 for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) {
277 if (!MRI.isPhysRegUsed(reg))
278 continue;
279
280 unsigned mapped_reg = reg - SP::I0 + SP::O0;
281
282 // Replace I register with O register.
283 MRI.replaceRegWith(reg, mapped_reg);
284
285 // Also replace register pair super-registers.
286 if ((reg - SP::I0) % 2 == 0) {
287 unsigned preg = (reg - SP::I0) / 2 + SP::I0_I1;
288 unsigned mapped_preg = preg - SP::I0_I1 + SP::O0_O1;
289 MRI.replaceRegWith(preg, mapped_preg);
290 }
291 }
292
293 // Rewrite MBB's Live-ins.
294 for (MachineBasicBlock &MBB : MF) {
295 for (unsigned reg = SP::I0_I1; reg <= SP::I6_I7; ++reg) {
296 if (!MBB.isLiveIn(reg))
297 continue;
298 MBB.removeLiveIn(reg);
299 MBB.addLiveIn(reg - SP::I0_I1 + SP::O0_O1);
300 }
301 for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) {
302 if (!MBB.isLiveIn(reg))
303 continue;
304 MBB.removeLiveIn(reg);
305 MBB.addLiveIn(reg - SP::I0 + SP::O0);
306 }
307 }
308
310#ifdef EXPENSIVE_CHECKS
311 MF.verify(0, "After LeafProc Remapping");
312#endif
313}
314
316 const MachineFunction &MF) {
317 uint64_t FuncSize = 0;
318 for (auto &MBB : MF)
319 for (auto &MI : MBB) {
320 // Be conservative here and count the DS too.
321 uint64_t Multiplier = MI.hasDelaySlot() ? 2 : 1;
322 FuncSize += (TII->getInstSizeInBytes(MI) * Multiplier);
323 }
324 return FuncSize;
325}
326
328 BitVector &SavedRegs,
329 RegScavenger *RS) const {
332 const SparcInstrInfo *TII = STI.getInstrInfo();
333 const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>();
334
335 bool IsLargeFunction = !isInt<23>(estimateFunctionSizeInBytes(TII, MF));
336 MFI->setLargeProc(IsLargeFunction);
337
338 if (!Subtarget.getCLOpts().disable_sparc_leaf_proc && isLeafProc(MF)) {
339 MFI->setLeafProc(true);
340
341 remapRegsForLeafProc(MF);
342 }
343}
344
346 MachineFunction &MF, RegScavenger *RS) const {
347 const SparcRegisterInfo *RI = STI.getRegisterInfo();
348 const TargetRegisterClass &RC =
349 STI.is64Bit() ? SP::I64RegsRegClass : SP::IntRegsRegClass;
350 MachineFrameInfo &MFI = MF.getFrameInfo();
352
353 // Far branches beyond 23-bit offset require a spill slot for scratch
354 // register.
355 if (SMFI->isLargeProc()) {
356 int FI =
357 MFI.CreateSpillStackObject(RI->getSpillSize(RC), RI->getSpillAlign(RC));
358 RS->addScavengingFrameIndex(FI);
359 if (SMFI->getBranchRelaxationSpillFrameIndex() == -1)
361 LLVM_DEBUG(dbgs() << "Allocated FI(" << FI
362 << ") as the emergency spill slot.\n");
363 }
364}
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
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 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 & 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 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 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 ...
const SparcOptions & getCLOpts() const
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:173
static unsigned HIX22(int64_t imm)
Definition Sparc.h:181
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
static unsigned LOX10(int64_t imm)
Definition Sparc.h:185
static unsigned LO10(int64_t imm)
Definition Sparc.h:177
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