LLVM 24.0.0git
XtensaFrameLowering.cpp
Go to the documentation of this file.
1//===- XtensaFrameLowering.cpp - Xtensa 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 Xtensa implementation of TargetFrameLowering class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "XtensaFrameLowering.h"
14#include "XtensaInstrInfo.h"
16#include "XtensaSubtarget.h"
22#include "llvm/IR/Function.h"
23
24using namespace llvm;
25
26// Minimum frame = reg save area (4 words) plus static chain (1 word)
27// and the total number of words must be a multiple of 128 bits.
28// Width of a word, in units (bytes).
29#define UNITS_PER_WORD 4
30#define MIN_FRAME_SIZE (8 * UNITS_PER_WORD)
31
34 Align(4)),
35 STI(STI), TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {}
36
38 const MachineFrameInfo &MFI = MF.getFrameInfo();
40}
41
43 MachineBasicBlock &MBB) const {
44 assert(&MBB == &MF.front() && "Shrink-wrapping not yet implemented");
47 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
48 MCRegister SP = Xtensa::SP;
49 MCRegister FP = TRI->getFrameRegister(MF);
50 const MCRegisterInfo *MRI = MF.getContext().getRegisterInfo();
52
53 // First, compute final stack size.
54 uint64_t StackSize = MFI.getStackSize();
55 uint64_t PrevStackSize = StackSize;
56
57 // Round up StackSize to 16*N
58 StackSize += (16 - StackSize) & 0xf;
59
60 if (STI.isWindowedABI()) {
61 StackSize += 32;
62 uint64_t MaxAlignment = MFI.getMaxAlign().value();
63 if (MaxAlignment > 32)
64 StackSize += MaxAlignment;
65
66 if (StackSize <= 32760) {
67 BuildMI(MBB, MBBI, DL, TII.get(Xtensa::ENTRY))
68 .addReg(SP)
69 .addImm(StackSize);
70 } else {
71 // Use a8 as a temporary since a0-a7 may be live.
72 MCRegister TmpReg = Xtensa::A8;
73
74 BuildMI(MBB, MBBI, DL, TII.get(Xtensa::ENTRY))
75 .addReg(SP)
77 TII.loadImmediate(MBB, MBBI, &TmpReg, StackSize - MIN_FRAME_SIZE);
78 BuildMI(MBB, MBBI, DL, TII.get(Xtensa::SUB), TmpReg)
79 .addReg(SP)
80 .addReg(TmpReg);
81 BuildMI(MBB, MBBI, DL, TII.get(Xtensa::MOVSP), SP).addReg(TmpReg);
82 }
83
84 // Calculate how much is needed to have the correct alignment.
85 // Change offset to: alignment + difference.
86 // For example, in case of alignment of 128:
87 // diff_to_128_aligned_address = (128 - (SP & 127))
88 // new_offset = SP + diff_to_128_aligned_address
89 // This is safe to do because we increased the stack size by MaxAlignment.
90 MCRegister Reg, RegMisAlign;
91 if (MaxAlignment > 32) {
92 TII.loadImmediate(MBB, MBBI, &RegMisAlign, MaxAlignment - 1);
93 TII.loadImmediate(MBB, MBBI, &Reg, MaxAlignment);
94 BuildMI(MBB, MBBI, DL, TII.get(Xtensa::AND))
95 .addReg(RegMisAlign, RegState::Define)
96 .addReg(FP)
97 .addReg(RegMisAlign);
98 BuildMI(MBB, MBBI, DL, TII.get(Xtensa::SUB), RegMisAlign)
99 .addReg(Reg)
100 .addReg(RegMisAlign);
101 BuildMI(MBB, MBBI, DL, TII.get(Xtensa::ADD), SP)
102 .addReg(SP)
103 .addReg(RegMisAlign, RegState::Kill);
104 }
105
106 // Store FP register in A8, because FP may be used to pass function
107 // arguments
108 if (XtensaFI->isSaveFrameRegister()) {
109 BuildMI(MBB, MBBI, DL, TII.get(Xtensa::OR), Xtensa::A8)
110 .addReg(FP)
111 .addReg(FP);
112 }
113
114 // if framepointer enabled, set it to point to the stack pointer.
115 if (hasFP(MF)) {
116 // Insert instruction "move $fp, $sp" at this location.
117 BuildMI(MBB, MBBI, DL, TII.get(Xtensa::OR), FP)
118 .addReg(SP)
119 .addReg(SP)
121
123 nullptr, MRI->getDwarfRegNum(FP, true), StackSize);
124 unsigned CFIIndex = MF.addFrameInst(Inst);
125 BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
126 .addCFIIndex(CFIIndex);
127 } else {
128 // emit ".cfi_def_cfa_offset StackSize"
129 unsigned CFIIndex = MF.addFrameInst(
130 MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize));
131 BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
132 .addCFIIndex(CFIIndex);
133 }
134 } else {
135 // No need to allocate space on the stack.
136 if (StackSize == 0 && !MFI.adjustsStack())
137 return;
138
139 // Adjust stack.
140 TII.adjustStackPtr(SP, -StackSize, MBB, MBBI);
141
142 // emit ".cfi_def_cfa_offset StackSize"
143 unsigned CFIIndex =
144 MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize));
145 BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
146 .addCFIIndex(CFIIndex);
147
148 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
149
150 if (!CSI.empty()) {
151 // Find the instruction past the last instruction that saves a
152 // callee-saved register to the stack. The callee-saved store
153 // instructions are placed at the begin of basic block, so
154 // iterate over instruction sequence and check that
155 // save instructions are placed correctly.
156 for (unsigned i = 0, e = CSI.size(); i < e; ++i) {
157#ifndef NDEBUG
158 const CalleeSavedInfo &Info = CSI[i];
159 int FI = Info.getFrameIdx();
160 int StoreFI = 0;
161
162 // Checking that the instruction is exactly as expected
163 bool IsStoreInst = false;
164 if (MBBI->getOpcode() == TargetOpcode::COPY && Info.isSpilledToReg()) {
165 Register DstReg = MBBI->getOperand(0).getReg();
166 Register Reg = MBBI->getOperand(1).getReg();
167 IsStoreInst = Info.getDstReg() == DstReg.asMCReg() &&
168 Info.getReg() == Reg.asMCReg();
169 } else {
170 Register Reg = TII.isStoreToStackSlot(*MBBI, StoreFI);
171 IsStoreInst = Reg.asMCReg() == Info.getReg() && StoreFI == FI;
172 }
173 assert(IsStoreInst &&
174 "Unexpected callee-saved register store instruction");
175#endif
176 ++MBBI;
177 }
178
179 // Iterate over list of callee-saved registers and emit .cfi_offset
180 // directives.
181 for (const auto &I : CSI) {
182 int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
183 MCRegister Reg = I.getReg();
184
185 unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
186 nullptr, MRI->getDwarfRegNum(Reg, 1), Offset));
187 BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
188 .addCFIIndex(CFIIndex);
189 }
190 }
191
192 // if framepointer enabled, set it to point to the stack pointer.
193 if (hasFP(MF)) {
194 // Insert instruction "move $fp, $sp" at this location.
195 BuildMI(MBB, MBBI, DL, TII.get(Xtensa::OR), FP)
196 .addReg(SP)
197 .addReg(SP)
199
200 // emit ".cfi_def_cfa_register $fp"
201 unsigned CFIIndex =
203 nullptr, MRI->getDwarfRegNum(FP, true)));
204 BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
205 .addCFIIndex(CFIIndex);
206 }
207 }
208
209 if (StackSize != PrevStackSize) {
210 MFI.setStackSize(StackSize);
211
212 for (int i = MFI.getObjectIndexBegin(); i < MFI.getObjectIndexEnd(); i++) {
213 if (!MFI.isDeadObjectIndex(i)) {
214 int64_t SPOffset = MFI.getObjectOffset(i);
215
216 if (SPOffset < 0)
217 MFI.setObjectOffset(i, SPOffset - StackSize + PrevStackSize);
218 }
219 }
220 }
221}
222
224 MachineBasicBlock &MBB) const {
225 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
226 MachineFrameInfo &MFI = MF.getFrameInfo();
227 DebugLoc DL = MBBI->getDebugLoc();
228 MCRegister SP = Xtensa::SP;
229 MCRegister FP = TRI->getFrameRegister(MF);
230
231 // if framepointer enabled, restore the stack pointer.
232 if (hasFP(MF)) {
233 // We should place restore stack pointer instruction just before
234 // sequence of instructions which restores callee-saved registers.
235 // This sequence is placed at the end of the basic block,
236 // so we should find first instruction of the sequence.
238
239 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
240
241 // Find the first instruction at the end that restores a callee-saved
242 // register.
243 for (unsigned i = 0, e = CSI.size(); i < e; ++i) {
244 --I;
245#ifndef NDEBUG
246 const CalleeSavedInfo &Info = CSI[i];
247 int FI = Info.getFrameIdx();
248 int LoadFI = 0;
249
250 // Checking that the instruction is exactly as expected
251 bool IsRestoreInst = false;
252 if (I->getOpcode() == TargetOpcode::COPY && Info.isSpilledToReg()) {
253 Register Reg = I->getOperand(0).getReg();
254 Register DstReg = I->getOperand(1).getReg();
255 IsRestoreInst = Info.getDstReg() == DstReg.asMCReg() &&
256 Info.getReg() == Reg.asMCReg();
257 } else {
258 Register Reg = TII.isLoadFromStackSlot(*I, LoadFI);
259 IsRestoreInst = Info.getReg() == Reg.asMCReg() && LoadFI == FI;
260 }
261 assert(IsRestoreInst &&
262 "Unexpected callee-saved register restore instruction");
263#endif
264 }
265 if (STI.isWindowedABI()) {
266 // In most architectures, we need to explicitly restore the stack pointer
267 // before returning.
268 //
269 // For Xtensa Windowed Register option, it is not needed to explicitly
270 // restore the stack pointer. Reason being is that on function return,
271 // the window of the caller (including the old stack pointer) gets
272 // restored anyways.
273 } else {
274 BuildMI(MBB, I, DL, TII.get(Xtensa::OR), SP).addReg(FP).addReg(FP);
275 }
276 }
277
278 if (STI.isWindowedABI())
279 return;
280
281 // Get the number of bytes from FrameInfo
282 uint64_t StackSize = MFI.getStackSize();
283
284 if (!StackSize)
285 return;
286
287 // Adjust stack.
288 TII.adjustStackPtr(SP, StackSize, MBB, MBBI);
289}
290
293 ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
294 MachineFunction *MF = MBB.getParent();
295 MachineBasicBlock &EntryBlock = *(MF->begin());
296
297 if (STI.isWindowedABI())
298 return true;
299
300 for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
301 // Add the callee-saved register as live-in. Do not add if the register is
302 // A0 and return address is taken, because it will be implemented in
303 // method XtensaTargetLowering::LowerRETURNADDR.
304 // It's killed at the spill, unless the register is RA and return address
305 // is taken.
306 MCRegister Reg = CSI[i].getReg();
307 bool IsA0AndRetAddrIsTaken =
308 (Reg == Xtensa::A0) && MF->getFrameInfo().isReturnAddressTaken();
309 if (!IsA0AndRetAddrIsTaken)
310 EntryBlock.addLiveIn(Reg);
311
312 // Insert the spill to the stack frame.
313 bool IsKill = !IsA0AndRetAddrIsTaken;
314 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
315 TII.storeRegToStackSlot(EntryBlock, MI, Reg, IsKill, CSI[i].getFrameIdx(),
316 RC, Register());
317 }
318
319 return true;
320}
321
329
330// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions
334 if (!hasReservedCallFrame(MF)) {
335 int64_t Amount = I->getOperand(0).getImm();
336
337 if (I->getOpcode() == Xtensa::ADJCALLSTACKDOWN)
338 Amount = -Amount;
339
340 TII.adjustStackPtr(Xtensa::SP, Amount, MBB, I);
341 }
342
343 return MBB.erase(I);
344}
345
347 BitVector &SavedRegs,
348 RegScavenger *RS) const {
349 MCRegister FP = TRI->getFrameRegister(MF);
350
351 if (STI.isWindowedABI()) {
352 return;
353 }
354
356
357 // Mark $fp as used if function has dedicated frame pointer.
358 if (hasFP(MF))
359 SavedRegs.set(FP);
360}
361
363 MachineFunction &MF, RegScavenger *RS) const {
364 // Set scavenging frame index if necessary.
365 MachineFrameInfo &MFI = MF.getFrameInfo();
366 uint64_t MaxSPOffset = MFI.estimateStackSize(MF);
367 auto *XtensaFI = MF.getInfo<XtensaMachineFunctionInfo>();
368 unsigned ScavSlotsNum = 0;
369
370 if (!isInt<12>(MaxSPOffset))
371 ScavSlotsNum = 1;
372
373 // Far branches over 18-bit offset require a spill slot for scratch register.
374 bool IsLargeFunction = !isInt<18>(MF.estimateFunctionSizeInBytes());
375 if (IsLargeFunction)
376 ScavSlotsNum = std::max(ScavSlotsNum, 1u);
377
378 const TargetRegisterClass &RC = Xtensa::ARRegClass;
379 unsigned Size = TRI->getSpillSize(RC);
380 Align Alignment = TRI->getSpillAlign(RC);
381 for (unsigned I = 0; I < ScavSlotsNum; I++) {
382 int FI = MFI.CreateSpillStackObject(Size, Alignment);
383 RS->addScavengingFrameIndex(FI);
384
385 if (IsLargeFunction &&
386 XtensaFI->getBranchRelaxationScratchFrameIndex() == -1)
387 XtensaFI->setBranchRelaxationScratchFrameIndex(FI);
388 }
389}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
Promote Memory to Register
Definition Mem2Reg.cpp:110
This file declares the machine register scavenger class.
#define MIN_FRAME_SIZE
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
BitVector & set()
Set all bits in the bitvector.
Definition BitVector.h:366
The CalleeSavedInfo class tracks the information need to locate where a callee saved register is in t...
A debug info location.
Definition DebugLoc.h:126
static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register, SMLoc Loc={})
.cfi_def_cfa_register modifies a rule for computing CFA.
Definition MCDwarf.h:635
static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa defines a rule for computing CFA as: take address from Register and add Offset to it.
Definition MCDwarf.h:628
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
Definition MCDwarf.h:670
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
Definition MCDwarf.h:643
const MCRegisterInfo * getRegisterInfo() const
Definition MCContext.h:411
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
virtual int64_t getDwarfRegNum(MCRegister Reg, bool isEH) const
Map a target register to an equivalent dwarf register number.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
MachineInstrBundleIterator< MachineInstr > iterator
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 isReturnAddressTaken() 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.
void setObjectOffset(int ObjectIdx, int64_t SPOffset)
Set the stack frame offset of the specified object.
LLVM_ABI uint64_t estimateStackSize(const MachineFunction &MF) const
Estimate and return the size of the stack frame.
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...
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
int getObjectIndexEnd() const
Return one past the maximum frame object index.
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.
int getObjectIndexBegin() const
Return the minimum frame object index.
bool isDeadObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a dead object.
unsigned addFrameInst(const MCCFIInstruction &Inst)
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MCContext & getContext() const
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
int64_t estimateFunctionSizeInBytes()
Return an estimate of the function's code size, taking into account block and function alignment.
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) 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.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:294
Wrapper class representing virtual and physical registers.
Definition Register.h:20
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
Definition Register.h:107
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
virtual bool hasReservedCallFrame(const MachineFunction &MF) const
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required,...
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)
virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, MutableArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const
restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee saved registers and returns...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS) const override
processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...
bool hasFPImpl(const MachineFunction &MF) const override
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, MutableArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override
restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee saved registers and returns...
void emitPrologue(MachineFunction &, MachineBasicBlock &) const override
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
XtensaFrameLowering(const XtensaSubtarget &STI)
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override
spillCalleeSavedRegisters - Issues instruction(s) to spill all callee saved registers and returns tru...
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...
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
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
@ Kill
The last use of a register.
@ Define
Register definition.
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
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77