1 //===- XtensaFrameLowering.cpp - Xtensa Frame Information -----------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file contains the Xtensa implementation of TargetFrameLowering class.
11 //===----------------------------------------------------------------------===//
13 #include "XtensaFrameLowering.h"
14 #include "XtensaInstrInfo.h"
15 #include "XtensaSubtarget.h"
16 #include "llvm/CodeGen/MachineFrameInfo.h"
17 #include "llvm/CodeGen/MachineInstrBuilder.h"
18 #include "llvm/CodeGen/MachineModuleInfo.h"
19 #include "llvm/CodeGen/MachineRegisterInfo.h"
20 #include "llvm/CodeGen/RegisterScavenging.h"
21 #include "llvm/IR/Function.h"
25 XtensaFrameLowering::XtensaFrameLowering(const XtensaSubtarget
&STI
)
26 : TargetFrameLowering(TargetFrameLowering::StackGrowsDown
, Align(4), 0,
28 TII(*STI
.getInstrInfo()), TRI(STI
.getRegisterInfo()) {}
30 bool XtensaFrameLowering::hasFP(const MachineFunction
&MF
) const {
31 const MachineFrameInfo
&MFI
= MF
.getFrameInfo();
32 return MF
.getTarget().Options
.DisableFramePointerElim(MF
) ||
33 MFI
.hasVarSizedObjects();
36 void XtensaFrameLowering::emitPrologue(MachineFunction
&MF
,
37 MachineBasicBlock
&MBB
) const {
38 assert(&MBB
== &MF
.front() && "Shrink-wrapping not yet implemented");
39 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
40 MachineBasicBlock::iterator MBBI
= MBB
.begin();
41 DebugLoc DL
= MBBI
!= MBB
.end() ? MBBI
->getDebugLoc() : DebugLoc();
42 MCRegister SP
= Xtensa::SP
;
43 MCRegister FP
= TRI
->getFrameRegister(MF
);
44 const MCRegisterInfo
*MRI
= MF
.getContext().getRegisterInfo();
46 // First, compute final stack size.
47 uint64_t StackSize
= MFI
.getStackSize();
48 uint64_t PrevStackSize
= StackSize
;
50 // Round up StackSize to 16*N
51 StackSize
+= (16 - StackSize
) & 0xf;
53 // No need to allocate space on the stack.
54 if (StackSize
== 0 && !MFI
.adjustsStack())
58 TII
.adjustStackPtr(SP
, -StackSize
, MBB
, MBBI
);
60 // emit ".cfi_def_cfa_offset StackSize"
62 MF
.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize
));
63 BuildMI(MBB
, MBBI
, DL
, TII
.get(TargetOpcode::CFI_INSTRUCTION
))
64 .addCFIIndex(CFIIndex
);
66 const std::vector
<CalleeSavedInfo
> &CSI
= MFI
.getCalleeSavedInfo();
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
) {
76 const CalleeSavedInfo
&Info
= CSI
[i
];
77 int FI
= Info
.getFrameIdx();
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
);
87 Register Reg
= TII
.isStoreToStackSlot(*MBBI
, StoreFI
);
88 IsStoreInst
= (Reg
== Info
.getReg()) && (StoreFI
== FI
);
91 "Unexpected callee-saved register store instruction");
96 // Iterate over list of callee-saved registers and emit .cfi_offset
98 for (const auto &I
: CSI
) {
99 int64_t Offset
= MFI
.getObjectOffset(I
.getFrameIdx());
100 Register Reg
= I
.getReg();
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
);
109 // if framepointer enabled, set it to point to the stack pointer.
111 // Insert instruction "move $fp, $sp" at this location.
112 BuildMI(MBB
, MBBI
, DL
, TII
.get(Xtensa::OR
), FP
)
115 .setMIFlag(MachineInstr::FrameSetup
);
117 // emit ".cfi_def_cfa_register $fp"
118 unsigned CFIIndex
= MF
.addFrameInst(MCCFIInstruction::createDefCfaRegister(
119 nullptr, MRI
->getDwarfRegNum(FP
, true)));
120 BuildMI(MBB
, MBBI
, DL
, TII
.get(TargetOpcode::CFI_INSTRUCTION
))
121 .addCFIIndex(CFIIndex
);
124 if (StackSize
!= PrevStackSize
) {
125 MFI
.setStackSize(StackSize
);
127 for (int i
= MFI
.getObjectIndexBegin(); i
< MFI
.getObjectIndexEnd(); i
++) {
128 if (!MFI
.isDeadObjectIndex(i
)) {
129 int64_t SPOffset
= MFI
.getObjectOffset(i
);
132 MFI
.setObjectOffset(i
, SPOffset
- StackSize
+ PrevStackSize
);
138 void XtensaFrameLowering::emitEpilogue(MachineFunction
&MF
,
139 MachineBasicBlock
&MBB
) const {
140 MachineBasicBlock::iterator MBBI
= MBB
.getLastNonDebugInstr();
141 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
142 DebugLoc DL
= MBBI
->getDebugLoc();
143 MCRegister SP
= Xtensa::SP
;
144 MCRegister FP
= TRI
->getFrameRegister(MF
);
146 // if framepointer enabled, restore the stack pointer.
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.
152 MachineBasicBlock::iterator I
= MBBI
;
154 const std::vector
<CalleeSavedInfo
> &CSI
= MFI
.getCalleeSavedInfo();
156 // Find the first instruction at the end that restores a callee-saved
158 for (unsigned i
= 0, e
= CSI
.size(); i
< e
; ++i
) {
161 const CalleeSavedInfo
&Info
= CSI
[i
];
162 int FI
= Info
.getFrameIdx();
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
);
172 Register Reg
= TII
.isLoadFromStackSlot(*I
, LoadFI
);
173 IsRestoreInst
= (Info
.getReg() == Reg
) && (LoadFI
== FI
);
175 assert(IsRestoreInst
&&
176 "Unexpected callee-saved register restore instruction");
180 BuildMI(MBB
, I
, DL
, TII
.get(Xtensa::OR
), SP
).addReg(FP
).addReg(FP
);
183 // Get the number of bytes from FrameInfo
184 uint64_t StackSize
= MFI
.getStackSize();
190 TII
.adjustStackPtr(SP
, StackSize
, MBB
, MBBI
);
193 bool XtensaFrameLowering::spillCalleeSavedRegisters(
194 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MI
,
195 ArrayRef
<CalleeSavedInfo
> CSI
, const TargetRegisterInfo
*TRI
) const {
196 MachineFunction
*MF
= MBB
.getParent();
197 MachineBasicBlock
&EntryBlock
= *(MF
->begin());
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
205 Register Reg
= CSI
[i
].getReg();
206 bool IsA0AndRetAddrIsTaken
=
207 (Reg
== Xtensa::A0
) && MF
->getFrameInfo().isReturnAddressTaken();
208 if (!IsA0AndRetAddrIsTaken
)
209 EntryBlock
.addLiveIn(Reg
);
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());
221 bool XtensaFrameLowering::restoreCalleeSavedRegisters(
222 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MI
,
223 MutableArrayRef
<CalleeSavedInfo
> CSI
, const TargetRegisterInfo
*TRI
) const {
224 return TargetFrameLowering::restoreCalleeSavedRegisters(MBB
, MI
, CSI
, TRI
);
227 // Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions
228 MachineBasicBlock::iterator
XtensaFrameLowering::eliminateCallFramePseudoInstr(
229 MachineFunction
&MF
, MachineBasicBlock
&MBB
,
230 MachineBasicBlock::iterator I
) const {
231 const XtensaInstrInfo
&TII
=
232 *static_cast<const XtensaInstrInfo
*>(MF
.getSubtarget().getInstrInfo());
234 if (!hasReservedCallFrame(MF
)) {
235 int64_t Amount
= I
->getOperand(0).getImm();
237 if (I
->getOpcode() == Xtensa::ADJCALLSTACKDOWN
)
240 TII
.adjustStackPtr(Xtensa::SP
, Amount
, MBB
, I
);
246 void XtensaFrameLowering::determineCalleeSaves(MachineFunction
&MF
,
247 BitVector
&SavedRegs
,
248 RegScavenger
*RS
) const {
249 unsigned FP
= TRI
->getFrameRegister(MF
);
251 TargetFrameLowering::determineCalleeSaves(MF
, SavedRegs
, RS
);
253 // Mark $fp as used if function has dedicated frame pointer.
258 void XtensaFrameLowering::processFunctionBeforeFrameFinalized(
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
);
264 if (isInt
<12>(MaxSPOffset
))
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);
272 RS
->addScavengingFrameIndex(FI
);