AMDGPU: Mark test as XFAIL in expensive_checks builds
[llvm-project.git] / llvm / lib / Target / Xtensa / XtensaFrameLowering.cpp
blob005ba10b813133f11c1798915635cba8c3d1935b
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.
11 //===----------------------------------------------------------------------===//
13 #include "XtensaFrameLowering.h"
14 #include "XtensaInstrInfo.h"
15 #include "XtensaMachineFunctionInfo.h"
16 #include "XtensaSubtarget.h"
17 #include "llvm/CodeGen/MachineFrameInfo.h"
18 #include "llvm/CodeGen/MachineInstrBuilder.h"
19 #include "llvm/CodeGen/MachineModuleInfo.h"
20 #include "llvm/CodeGen/MachineRegisterInfo.h"
21 #include "llvm/CodeGen/RegisterScavenging.h"
22 #include "llvm/IR/Function.h"
24 using namespace llvm;
26 XtensaFrameLowering::XtensaFrameLowering(const XtensaSubtarget &STI)
27 : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(4), 0,
28 Align(4)),
29 TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {}
31 bool XtensaFrameLowering::hasFPImpl(const MachineFunction &MF) const {
32 const MachineFrameInfo &MFI = MF.getFrameInfo();
33 return MF.getTarget().Options.DisableFramePointerElim(MF) ||
34 MFI.hasVarSizedObjects();
37 void XtensaFrameLowering::emitPrologue(MachineFunction &MF,
38 MachineBasicBlock &MBB) const {
39 assert(&MBB == &MF.front() && "Shrink-wrapping not yet implemented");
40 MachineFrameInfo &MFI = MF.getFrameInfo();
41 MachineBasicBlock::iterator MBBI = MBB.begin();
42 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
43 MCRegister SP = Xtensa::SP;
44 MCRegister FP = TRI->getFrameRegister(MF);
45 const MCRegisterInfo *MRI = MF.getContext().getRegisterInfo();
47 // First, compute final stack size.
48 uint64_t StackSize = MFI.getStackSize();
49 uint64_t PrevStackSize = StackSize;
51 // Round up StackSize to 16*N
52 StackSize += (16 - StackSize) & 0xf;
54 // No need to allocate space on the stack.
55 if (StackSize == 0 && !MFI.adjustsStack())
56 return;
58 // Adjust stack.
59 TII.adjustStackPtr(SP, -StackSize, MBB, MBBI);
61 // emit ".cfi_def_cfa_offset StackSize"
62 unsigned CFIIndex =
63 MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize));
64 BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
65 .addCFIIndex(CFIIndex);
67 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
69 if (!CSI.empty()) {
70 // Find the instruction past the last instruction that saves a
71 // callee-saved register to the stack. The callee-saved store
72 // instructions are placed at the begin of basic block, so
73 // iterate over instruction sequence and check that
74 // save instructions are placed correctly.
75 for (unsigned i = 0, e = CSI.size(); i < e; ++i) {
76 #ifndef NDEBUG
77 const CalleeSavedInfo &Info = CSI[i];
78 int FI = Info.getFrameIdx();
79 int StoreFI = 0;
81 // Checking that the instruction is exactly as expected
82 bool IsStoreInst = false;
83 if (MBBI->getOpcode() == TargetOpcode::COPY && Info.isSpilledToReg()) {
84 Register DstReg = MBBI->getOperand(0).getReg();
85 Register Reg = MBBI->getOperand(1).getReg();
86 IsStoreInst = (Info.getDstReg() == DstReg) && (Info.getReg() == Reg);
87 } else {
88 Register Reg = TII.isStoreToStackSlot(*MBBI, StoreFI);
89 IsStoreInst = (Reg == Info.getReg()) && (StoreFI == FI);
91 assert(IsStoreInst &&
92 "Unexpected callee-saved register store instruction");
93 #endif
94 ++MBBI;
97 // Iterate over list of callee-saved registers and emit .cfi_offset
98 // directives.
99 for (const auto &I : CSI) {
100 int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
101 Register Reg = I.getReg();
103 unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
104 nullptr, MRI->getDwarfRegNum(Reg, 1), Offset));
105 BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
106 .addCFIIndex(CFIIndex);
110 // if framepointer enabled, set it to point to the stack pointer.
111 if (hasFP(MF)) {
112 // Insert instruction "move $fp, $sp" at this location.
113 BuildMI(MBB, MBBI, DL, TII.get(Xtensa::OR), FP)
114 .addReg(SP)
115 .addReg(SP)
116 .setMIFlag(MachineInstr::FrameSetup);
118 // emit ".cfi_def_cfa_register $fp"
119 unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(
120 nullptr, MRI->getDwarfRegNum(FP, true)));
121 BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
122 .addCFIIndex(CFIIndex);
125 if (StackSize != PrevStackSize) {
126 MFI.setStackSize(StackSize);
128 for (int i = MFI.getObjectIndexBegin(); i < MFI.getObjectIndexEnd(); i++) {
129 if (!MFI.isDeadObjectIndex(i)) {
130 int64_t SPOffset = MFI.getObjectOffset(i);
132 if (SPOffset < 0)
133 MFI.setObjectOffset(i, SPOffset - StackSize + PrevStackSize);
139 void XtensaFrameLowering::emitEpilogue(MachineFunction &MF,
140 MachineBasicBlock &MBB) const {
141 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
142 MachineFrameInfo &MFI = MF.getFrameInfo();
143 DebugLoc DL = MBBI->getDebugLoc();
144 MCRegister SP = Xtensa::SP;
145 MCRegister FP = TRI->getFrameRegister(MF);
147 // if framepointer enabled, restore the stack pointer.
148 if (hasFP(MF)) {
149 // We should place restore stack pointer instruction just before
150 // sequence of instructions which restores callee-saved registers.
151 // This sequence is placed at the end of the basic block,
152 // so we should find first instruction of the sequence.
153 MachineBasicBlock::iterator I = MBBI;
155 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
157 // Find the first instruction at the end that restores a callee-saved
158 // register.
159 for (unsigned i = 0, e = CSI.size(); i < e; ++i) {
160 --I;
161 #ifndef NDEBUG
162 const CalleeSavedInfo &Info = CSI[i];
163 int FI = Info.getFrameIdx();
164 int LoadFI = 0;
166 // Checking that the instruction is exactly as expected
167 bool IsRestoreInst = false;
168 if (I->getOpcode() == TargetOpcode::COPY && Info.isSpilledToReg()) {
169 Register Reg = I->getOperand(0).getReg();
170 Register DstReg = I->getOperand(1).getReg();
171 IsRestoreInst = (Info.getDstReg() == DstReg) && (Info.getReg() == Reg);
172 } else {
173 Register Reg = TII.isLoadFromStackSlot(*I, LoadFI);
174 IsRestoreInst = (Info.getReg() == Reg) && (LoadFI == FI);
176 assert(IsRestoreInst &&
177 "Unexpected callee-saved register restore instruction");
178 #endif
181 BuildMI(MBB, I, DL, TII.get(Xtensa::OR), SP).addReg(FP).addReg(FP);
184 // Get the number of bytes from FrameInfo
185 uint64_t StackSize = MFI.getStackSize();
187 if (!StackSize)
188 return;
190 // Adjust stack.
191 TII.adjustStackPtr(SP, StackSize, MBB, MBBI);
194 bool XtensaFrameLowering::spillCalleeSavedRegisters(
195 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
196 ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
197 MachineFunction *MF = MBB.getParent();
198 MachineBasicBlock &EntryBlock = *(MF->begin());
200 for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
201 // Add the callee-saved register as live-in. Do not add if the register is
202 // A0 and return address is taken, because it will be implemented in
203 // method XtensaTargetLowering::LowerRETURNADDR.
204 // It's killed at the spill, unless the register is RA and return address
205 // is taken.
206 Register Reg = CSI[i].getReg();
207 bool IsA0AndRetAddrIsTaken =
208 (Reg == Xtensa::A0) && MF->getFrameInfo().isReturnAddressTaken();
209 if (!IsA0AndRetAddrIsTaken)
210 EntryBlock.addLiveIn(Reg);
212 // Insert the spill to the stack frame.
213 bool IsKill = !IsA0AndRetAddrIsTaken;
214 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
215 TII.storeRegToStackSlot(EntryBlock, MI, Reg, IsKill, CSI[i].getFrameIdx(),
216 RC, TRI, Register());
219 return true;
222 bool XtensaFrameLowering::restoreCalleeSavedRegisters(
223 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
224 MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
225 return TargetFrameLowering::restoreCalleeSavedRegisters(MBB, MI, CSI, TRI);
228 // Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions
229 MachineBasicBlock::iterator XtensaFrameLowering::eliminateCallFramePseudoInstr(
230 MachineFunction &MF, MachineBasicBlock &MBB,
231 MachineBasicBlock::iterator I) const {
232 const XtensaInstrInfo &TII =
233 *static_cast<const XtensaInstrInfo *>(MF.getSubtarget().getInstrInfo());
235 if (!hasReservedCallFrame(MF)) {
236 int64_t Amount = I->getOperand(0).getImm();
238 if (I->getOpcode() == Xtensa::ADJCALLSTACKDOWN)
239 Amount = -Amount;
241 TII.adjustStackPtr(Xtensa::SP, Amount, MBB, I);
244 return MBB.erase(I);
247 void XtensaFrameLowering::determineCalleeSaves(MachineFunction &MF,
248 BitVector &SavedRegs,
249 RegScavenger *RS) const {
250 unsigned FP = TRI->getFrameRegister(MF);
252 TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
254 // Mark $fp as used if function has dedicated frame pointer.
255 if (hasFP(MF))
256 SavedRegs.set(FP);
259 void XtensaFrameLowering::processFunctionBeforeFrameFinalized(
260 MachineFunction &MF, RegScavenger *RS) const {
261 // Set scavenging frame index if necessary.
262 MachineFrameInfo &MFI = MF.getFrameInfo();
263 uint64_t MaxSPOffset = MFI.estimateStackSize(MF);
264 auto *XtensaFI = MF.getInfo<XtensaMachineFunctionInfo>();
265 unsigned ScavSlotsNum = 0;
267 if (!isInt<12>(MaxSPOffset))
268 ScavSlotsNum = 1;
270 // Far branches over 18-bit offset require a spill slot for scratch register.
271 bool IsLargeFunction = !isInt<18>(MF.estimateFunctionSizeInBytes());
272 if (IsLargeFunction)
273 ScavSlotsNum = std::max(ScavSlotsNum, 1u);
275 const TargetRegisterClass &RC = Xtensa::ARRegClass;
276 unsigned Size = TRI->getSpillSize(RC);
277 Align Alignment = TRI->getSpillAlign(RC);
278 for (unsigned I = 0; I < ScavSlotsNum; I++) {
279 int FI = MFI.CreateStackObject(Size, Alignment, false);
280 RS->addScavengingFrameIndex(FI);
282 if (IsLargeFunction &&
283 XtensaFI->getBranchRelaxationScratchFrameIndex() == -1)
284 XtensaFI->setBranchRelaxationScratchFrameIndex(FI);