LLVM 20.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>();
91 const SparcInstrInfo &TII =
92 *static_cast<const SparcInstrInfo *>(Subtarget.getInstrInfo());
93 const SparcRegisterInfo &RegInfo =
94 *static_cast<const SparcRegisterInfo *>(Subtarget.getRegisterInfo());
96 // Debug location must be unknown since the first debug location is used
97 // to determine the end of the prologue.
98 DebugLoc dl;
99
100 // Get the number of bytes to allocate from the FrameInfo
101 int NumBytes = (int) MFI.getStackSize();
102
103 unsigned SAVEri = SP::SAVEri;
104 unsigned SAVErr = SP::SAVErr;
105 if (FuncInfo->isLeafProc()) {
106 if (NumBytes == 0)
107 return;
108 SAVEri = SP::ADDri;
109 SAVErr = SP::ADDrr;
110 }
111
112 // The SPARC ABI is a bit odd in that it requires a reserved 92-byte
113 // (128 in v9) area in the user's stack, starting at %sp. Thus, the
114 // first part of the stack that can actually be used is located at
115 // %sp + 92.
116 //
117 // We therefore need to add that offset to the total stack size
118 // after all the stack objects are placed by
119 // PrologEpilogInserter calculateFrameObjectOffsets. However, since the stack needs to be
120 // aligned *after* the extra size is added, we need to disable
121 // calculateFrameObjectOffsets's built-in stack alignment, by having
122 // targetHandlesStackFrameRounding return true.
123
124
125 // Add the extra call frame stack size, if needed. (This is the same
126 // code as in PrologEpilogInserter, but also gets disabled by
127 // targetHandlesStackFrameRounding)
128 if (MFI.adjustsStack() && hasReservedCallFrame(MF))
129 NumBytes += MFI.getMaxCallFrameSize();
130
131 // Adds the SPARC subtarget-specific spill area to the stack
132 // size. Also ensures target-required alignment.
133 NumBytes = Subtarget.getAdjustedFrameSize(NumBytes);
134
135 // Finally, ensure that the size is sufficiently aligned for the
136 // data on the stack.
137 NumBytes = alignTo(NumBytes, MFI.getMaxAlign());
138
139 // Update stack size with corrected value.
140 MFI.setStackSize(NumBytes);
141
142 emitSPAdjustment(MF, MBB, MBBI, -NumBytes, SAVErr, SAVEri);
143
144 unsigned regFP = RegInfo.getDwarfRegNum(SP::I6, true);
145
146 // Emit ".cfi_def_cfa_register 30".
147 unsigned CFIIndex =
149 BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
150 .addCFIIndex(CFIIndex);
151
152 // Emit ".cfi_window_save".
153 CFIIndex = MF.addFrameInst(MCCFIInstruction::createWindowSave(nullptr));
154 BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
155 .addCFIIndex(CFIIndex);
156
157 unsigned regInRA = RegInfo.getDwarfRegNum(SP::I7, true);
158 unsigned regOutRA = RegInfo.getDwarfRegNum(SP::O7, true);
159 // Emit ".cfi_register 15, 31".
160 CFIIndex = MF.addFrameInst(
161 MCCFIInstruction::createRegister(nullptr, regOutRA, regInRA));
162 BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
163 .addCFIIndex(CFIIndex);
164}
165
169 if (!hasReservedCallFrame(MF)) {
170 MachineInstr &MI = *I;
171 int Size = MI.getOperand(0).getImm();
172 if (MI.getOpcode() == SP::ADJCALLSTACKDOWN)
173 Size = -Size;
174
175 if (Size)
176 emitSPAdjustment(MF, MBB, I, Size, SP::ADDrr, SP::ADDri);
177 }
178 return MBB.erase(I);
179}
180
181
183 MachineBasicBlock &MBB) const {
186 const SparcInstrInfo &TII =
187 *static_cast<const SparcInstrInfo *>(MF.getSubtarget().getInstrInfo());
188 DebugLoc dl = MBBI->getDebugLoc();
189 assert((MBBI->getOpcode() == SP::RETL || MBBI->getOpcode() == SP::TAIL_CALL ||
190 MBBI->getOpcode() == SP::TAIL_CALLri) &&
191 "Can only put epilog before 'retl' or 'tail_call' instruction!");
192 if (!FuncInfo->isLeafProc()) {
193 BuildMI(MBB, MBBI, dl, TII.get(SP::RESTORErr), SP::G0).addReg(SP::G0)
194 .addReg(SP::G0);
195 return;
196 }
197 MachineFrameInfo &MFI = MF.getFrameInfo();
198
199 int NumBytes = (int) MFI.getStackSize();
200 if (NumBytes != 0)
201 emitSPAdjustment(MF, MBB, MBBI, NumBytes, SP::ADDrr, SP::ADDri);
202
203 // Preserve return address in %o7
204 if (MBBI->getOpcode() == SP::TAIL_CALL) {
205 MBB.addLiveIn(SP::O7);
206 BuildMI(MBB, MBBI, dl, TII.get(SP::ORrr), SP::G1)
207 .addReg(SP::G0)
208 .addReg(SP::O7);
209 BuildMI(MBB, MBBI, dl, TII.get(SP::ORrr), SP::O7)
210 .addReg(SP::G0)
211 .addReg(SP::G1);
212 }
213}
214
216 // Reserve call frame if there are no variable sized objects on the stack.
217 return !MF.getFrameInfo().hasVarSizedObjects();
218}
219
220// hasFPImpl - Return true if the specified function should have a dedicated
221// frame pointer register. This is true if the function has variable sized
222// allocas or if frame pointer elimination is disabled.
224 const MachineFrameInfo &MFI = MF.getFrameInfo();
225 return MF.getTarget().Options.DisableFramePointerElim(MF) ||
227}
228
231 Register &FrameReg) const {
232 const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>();
233 const MachineFrameInfo &MFI = MF.getFrameInfo();
234 const SparcRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
236 bool isFixed = MFI.isFixedObjectIndex(FI);
237
238 // Addressable stack objects are accessed using neg. offsets from
239 // %fp, or positive offsets from %sp.
240 bool UseFP;
241
242 // Sparc uses FP-based references in general, even when "hasFP" is
243 // false. That function is rather a misnomer, because %fp is
244 // actually always available, unless isLeafProc.
245 if (FuncInfo->isLeafProc()) {
246 // If there's a leaf proc, all offsets need to be %sp-based,
247 // because we haven't caused %fp to actually point to our frame.
248 UseFP = false;
249 } else if (isFixed) {
250 // Otherwise, argument access should always use %fp.
251 UseFP = true;
252 } else {
253 // Finally, default to using %fp.
254 UseFP = true;
255 }
256
257 int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI) +
258 Subtarget.getStackPointerBias();
259
260 if (UseFP) {
261 FrameReg = RegInfo->getFrameRegister(MF);
262 return StackOffset::getFixed(FrameOffset);
263 } else {
264 FrameReg = SP::O6; // %sp
265 return StackOffset::getFixed(FrameOffset + MF.getFrameInfo().getStackSize());
266 }
267}
268
270{
271
272 for (unsigned reg = SP::I0; reg <= SP::I7; ++reg)
273 if (MRI->isPhysRegUsed(reg))
274 return false;
275
276 for (unsigned reg = SP::L0; reg <= SP::L7; ++reg)
277 if (MRI->isPhysRegUsed(reg))
278 return false;
279
280 return true;
281}
282
283bool SparcFrameLowering::isLeafProc(MachineFunction &MF) const
284{
285
287 MachineFrameInfo &MFI = MF.getFrameInfo();
288
289 return !(MFI.hasCalls() // has calls
290 || MRI.isPhysRegUsed(SP::L0) // Too many registers needed
291 || MRI.isPhysRegUsed(SP::O6) // %sp is used
292 || hasFP(MF) // need %fp
293 || MF.hasInlineAsm()); // has inline assembly
294}
295
296void SparcFrameLowering::remapRegsForLeafProc(MachineFunction &MF) const {
298 // Remap %i[0-7] to %o[0-7].
299 for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) {
300 if (!MRI.isPhysRegUsed(reg))
301 continue;
302
303 unsigned mapped_reg = reg - SP::I0 + SP::O0;
304
305 // Replace I register with O register.
306 MRI.replaceRegWith(reg, mapped_reg);
307
308 // Also replace register pair super-registers.
309 if ((reg - SP::I0) % 2 == 0) {
310 unsigned preg = (reg - SP::I0) / 2 + SP::I0_I1;
311 unsigned mapped_preg = preg - SP::I0_I1 + SP::O0_O1;
312 MRI.replaceRegWith(preg, mapped_preg);
313 }
314 }
315
316 // Rewrite MBB's Live-ins.
317 for (MachineBasicBlock &MBB : MF) {
318 for (unsigned reg = SP::I0_I1; reg <= SP::I6_I7; ++reg) {
319 if (!MBB.isLiveIn(reg))
320 continue;
321 MBB.removeLiveIn(reg);
322 MBB.addLiveIn(reg - SP::I0_I1 + SP::O0_O1);
323 }
324 for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) {
325 if (!MBB.isLiveIn(reg))
326 continue;
327 MBB.removeLiveIn(reg);
328 MBB.addLiveIn(reg - SP::I0 + SP::O0);
329 }
330 }
331
333#ifdef EXPENSIVE_CHECKS
334 MF.verify(0, "After LeafProc Remapping");
335#endif
336}
337
339 BitVector &SavedRegs,
340 RegScavenger *RS) const {
342 if (!DisableLeafProc && isLeafProc(MF)) {
344 MFI->setLeafProc(true);
345
346 remapRegsForLeafProc(MF);
347 }
348
349}
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator MBBI
#define LLVM_ATTRIBUTE_UNUSED
Definition: Compiler.h:282
uint64_t Size
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static cl::opt< bool > DisableLeafProc("disable-sparc-leaf-proc", cl::init(false), cl::desc("Disable Sparc leaf procedure optimization."), cl::Hidden)
static bool LLVM_ATTRIBUTE_UNUSED verifyLeafProcRegUse(MachineRegisterInfo *MRI)
static bool is64Bit(const char *name)
A debug info location.
Definition: DebugLoc.h:33
static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register, SMLoc Loc={})
.cfi_def_cfa_register modifies a rule for computing CFA.
Definition: MCDwarf.h:582
static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1, unsigned Register2, SMLoc Loc={})
.cfi_register Previous value of Register1 is saved in register Register2.
Definition: MCDwarf.h:632
static MCCFIInstruction createWindowSave(MCSymbol *L, SMLoc Loc={})
.cfi_window_save SPARC register window is saved.
Definition: MCDwarf.h:638
void removeLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll())
Remove the specified register from the live in set.
iterator getLastNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the last non-debug instruction in the basic block, or end().
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
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 the alignment in bytes that this function must be aligned to, which is greater than the defaul...
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.
unsigned addFrameInst(const MCCFIInstruction &Inst)
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.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineBasicBlock & front() const
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
Definition: MachineInstr.h:69
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
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 SparcInstrInfo * getInstrInfo() const override
StackOffset holds a fixed and a scalable offset in bytes.
Definition: TypeSize.h:33
int64_t getFixed() const
Returns the fixed component of the stack.
Definition: TypeSize.h:49
Information about stack frame layout on the target.
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...
TargetOptions Options
bool DisableFramePointerElim(const MachineFunction &MF) const
DisableFramePointerElim - This returns true if frame pointer elimination optimization should be disab...
virtual const TargetInstrInfo * getInstrInfo() const
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:443
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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:174
static unsigned HIX22(int64_t imm)
Definition: Sparc.h:182
static unsigned LOX10(int64_t imm)
Definition: Sparc.h:186
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:155
static unsigned LO10(int64_t imm)
Definition: Sparc.h:178
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
Register getFrameRegister(const MachineFunction &MF) const override