LLVM 20.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"
15#include "XtensaSubtarget.h"
21#include "llvm/IR/Function.h"
22
23using namespace llvm;
24
26 : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(4), 0,
27 Align(4)),
28 TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {}
29
31 const MachineFrameInfo &MFI = MF.getFrameInfo();
34}
35
37 MachineBasicBlock &MBB) const {
38 assert(&MBB == &MF.front() && "Shrink-wrapping not yet implemented");
41 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
42 MCRegister SP = Xtensa::SP;
45
46 // First, compute final stack size.
47 uint64_t StackSize = MFI.getStackSize();
48 uint64_t PrevStackSize = StackSize;
49
50 // Round up StackSize to 16*N
51 StackSize += (16 - StackSize) & 0xf;
52
53 // No need to allocate space on the stack.
54 if (StackSize == 0 && !MFI.adjustsStack())
55 return;
56
57 // Adjust stack.
58 TII.adjustStackPtr(SP, -StackSize, MBB, MBBI);
59
60 // emit ".cfi_def_cfa_offset StackSize"
61 unsigned CFIIndex =
62 MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize));
63 BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
64 .addCFIIndex(CFIIndex);
65
66 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
67
68 if (!CSI.empty()) {
69 // Find the instruction past the last instruction that saves a
70 // callee-saved register to the stack. The callee-saved store
71 // instructions are placed at the begin of basic block, so
72 // iterate over instruction sequence and check that
73 // save instructions are placed correctly.
74 for (unsigned i = 0, e = CSI.size(); i < e; ++i) {
75#ifndef NDEBUG
76 const CalleeSavedInfo &Info = CSI[i];
77 int FI = Info.getFrameIdx();
78 int StoreFI = 0;
79
80 // Checking that the instruction is exactly as expected
81 bool IsStoreInst = false;
82 if (MBBI->getOpcode() == TargetOpcode::COPY && Info.isSpilledToReg()) {
83 Register DstReg = MBBI->getOperand(0).getReg();
84 Register Reg = MBBI->getOperand(1).getReg();
85 IsStoreInst = (Info.getDstReg() == DstReg) && (Info.getReg() == Reg);
86 } else {
87 Register Reg = TII.isStoreToStackSlot(*MBBI, StoreFI);
88 IsStoreInst = (Reg == Info.getReg()) && (StoreFI == FI);
89 }
90 assert(IsStoreInst &&
91 "Unexpected callee-saved register store instruction");
92#endif
93 ++MBBI;
94 }
95
96 // Iterate over list of callee-saved registers and emit .cfi_offset
97 // directives.
98 for (const auto &I : CSI) {
99 int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
100 Register Reg = I.getReg();
101
102 unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
103 nullptr, MRI->getDwarfRegNum(Reg, 1), Offset));
104 BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
105 .addCFIIndex(CFIIndex);
106 }
107 }
108
109 // if framepointer enabled, set it to point to the stack pointer.
110 if (hasFP(MF)) {
111 // Insert instruction "move $fp, $sp" at this location.
112 BuildMI(MBB, MBBI, DL, TII.get(Xtensa::OR), FP)
113 .addReg(SP)
114 .addReg(SP)
116
117 // emit ".cfi_def_cfa_register $fp"
119 nullptr, MRI->getDwarfRegNum(FP, true)));
120 BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
121 .addCFIIndex(CFIIndex);
122 }
123
124 if (StackSize != PrevStackSize) {
125 MFI.setStackSize(StackSize);
126
127 for (int i = MFI.getObjectIndexBegin(); i < MFI.getObjectIndexEnd(); i++) {
128 if (!MFI.isDeadObjectIndex(i)) {
129 int64_t SPOffset = MFI.getObjectOffset(i);
130
131 if (SPOffset < 0)
132 MFI.setObjectOffset(i, SPOffset - StackSize + PrevStackSize);
133 }
134 }
135 }
136}
137
139 MachineBasicBlock &MBB) const {
141 MachineFrameInfo &MFI = MF.getFrameInfo();
142 DebugLoc DL = MBBI->getDebugLoc();
143 MCRegister SP = Xtensa::SP;
144 MCRegister FP = TRI->getFrameRegister(MF);
145
146 // if framepointer enabled, restore the stack pointer.
147 if (hasFP(MF)) {
148 // We should place restore stack pointer instruction just before
149 // sequence of instructions which restores callee-saved registers.
150 // This sequence is placed at the end of the basic block,
151 // so we should find first instruction of the sequence.
153
154 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
155
156 // Find the first instruction at the end that restores a callee-saved
157 // register.
158 for (unsigned i = 0, e = CSI.size(); i < e; ++i) {
159 --I;
160#ifndef NDEBUG
161 const CalleeSavedInfo &Info = CSI[i];
162 int FI = Info.getFrameIdx();
163 int LoadFI = 0;
164
165 // Checking that the instruction is exactly as expected
166 bool IsRestoreInst = false;
167 if (I->getOpcode() == TargetOpcode::COPY && Info.isSpilledToReg()) {
168 Register Reg = I->getOperand(0).getReg();
169 Register DstReg = I->getOperand(1).getReg();
170 IsRestoreInst = (Info.getDstReg() == DstReg) && (Info.getReg() == Reg);
171 } else {
172 Register Reg = TII.isLoadFromStackSlot(*I, LoadFI);
173 IsRestoreInst = (Info.getReg() == Reg) && (LoadFI == FI);
174 }
175 assert(IsRestoreInst &&
176 "Unexpected callee-saved register restore instruction");
177#endif
178 }
179
180 BuildMI(MBB, I, DL, TII.get(Xtensa::OR), SP).addReg(FP).addReg(FP);
181 }
182
183 // Get the number of bytes from FrameInfo
184 uint64_t StackSize = MFI.getStackSize();
185
186 if (!StackSize)
187 return;
188
189 // Adjust stack.
190 TII.adjustStackPtr(SP, StackSize, MBB, MBBI);
191}
192
197 MachineBasicBlock &EntryBlock = *(MF->begin());
198
199 for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
200 // Add the callee-saved register as live-in. Do not add if the register is
201 // A0 and return address is taken, because it will be implemented in
202 // method XtensaTargetLowering::LowerRETURNADDR.
203 // It's killed at the spill, unless the register is RA and return address
204 // is taken.
205 Register Reg = CSI[i].getReg();
206 bool IsA0AndRetAddrIsTaken =
207 (Reg == Xtensa::A0) && MF->getFrameInfo().isReturnAddressTaken();
208 if (!IsA0AndRetAddrIsTaken)
209 EntryBlock.addLiveIn(Reg);
210
211 // Insert the spill to the stack frame.
212 bool IsKill = !IsA0AndRetAddrIsTaken;
213 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
214 TII.storeRegToStackSlot(EntryBlock, MI, Reg, IsKill, CSI[i].getFrameIdx(),
215 RC, TRI, Register());
216 }
217
218 return true;
219}
220
225}
226
227// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions
231 const XtensaInstrInfo &TII =
232 *static_cast<const XtensaInstrInfo *>(MF.getSubtarget().getInstrInfo());
233
234 if (!hasReservedCallFrame(MF)) {
235 int64_t Amount = I->getOperand(0).getImm();
236
237 if (I->getOpcode() == Xtensa::ADJCALLSTACKDOWN)
238 Amount = -Amount;
239
240 TII.adjustStackPtr(Xtensa::SP, Amount, MBB, I);
241 }
242
243 return MBB.erase(I);
244}
245
247 BitVector &SavedRegs,
248 RegScavenger *RS) const {
249 unsigned FP = TRI->getFrameRegister(MF);
250
252
253 // Mark $fp as used if function has dedicated frame pointer.
254 if (hasFP(MF))
255 SavedRegs.set(FP);
256}
257
259 MachineFunction &MF, RegScavenger *RS) const {
260 // Set scavenging frame index if necessary.
261 MachineFrameInfo &MFI = MF.getFrameInfo();
262 uint64_t MaxSPOffset = MFI.estimateStackSize(MF);
263
264 if (isInt<12>(MaxSPOffset))
265 return;
266
267 const TargetRegisterClass &RC = Xtensa::ARRegClass;
268 unsigned Size = TRI->getSpillSize(RC);
269 Align Alignment = TRI->getSpillAlign(RC);
270 int FI = MF.getFrameInfo().CreateStackObject(Size, Alignment, false);
271
273}
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
uint64_t Size
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
unsigned const TargetRegisterInfo * TRI
This file declares the machine register scavenger class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:165
BitVector & set()
Definition: BitVector.h:351
The CalleeSavedInfo class tracks the information need to locate where a callee saved register is in t...
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:565
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:600
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
Definition: MCDwarf.h:573
const MCRegisterInfo * getRegisterInfo() const
Definition: MCContext.h:414
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
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.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
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.
int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
bool isReturnAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
void setObjectOffset(int ObjectIdx, int64_t SPOffset)
Set the stack frame offset of the specified object.
uint64_t estimateStackSize(const MachineFunction &MF) const
Estimate and return the size of the stack frame.
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)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MCContext & getContext() const
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineBasicBlock & front() const
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:307
void addScavengingFrameIndex(int FI)
Add a scavenging frame index.
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
Information about stack frame layout on the target.
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...
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...
TargetOptions Options
bool DisableFramePointerElim(const MachineFunction &MF) const
DisableFramePointerElim - This returns true if frame pointer elimination optimization should be disab...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetInstrInfo * getInstrInfo() const
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 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...
bool hasFP(const MachineFunction &MF) const override
hasFP - Return true if the specified function should have a dedicated frame pointer register.
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...
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
void adjustStackPtr(unsigned SP, int64_t Amount, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const
Adjust SP by Amount bytes.
Register getFrameRegister(const MachineFunction &MF) const override
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39