xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp (revision 7fdf597e96a02165cfe22ff357b857d5fa15ed8a)
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"
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"
22 
23 using namespace llvm;
24 
25 XtensaFrameLowering::XtensaFrameLowering(const XtensaSubtarget &STI)
26     : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(4), 0,
27                           Align(4)),
28       TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {}
29 
30 bool XtensaFrameLowering::hasFP(const MachineFunction &MF) const {
31   const MachineFrameInfo &MFI = MF.getFrameInfo();
32   return MF.getTarget().Options.DisableFramePointerElim(MF) ||
33          MFI.hasVarSizedObjects();
34 }
35 
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();
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)
115         .setMIFlag(MachineInstr::FrameSetup);
116 
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);
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 
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);
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.
152     MachineBasicBlock::iterator I = MBBI;
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 
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());
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 
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);
225 }
226 
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());
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 
246 void XtensaFrameLowering::determineCalleeSaves(MachineFunction &MF,
247                                                BitVector &SavedRegs,
248                                                RegScavenger *RS) const {
249   unsigned FP = TRI->getFrameRegister(MF);
250 
251   TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
252 
253   // Mark $fp as used if function has dedicated frame pointer.
254   if (hasFP(MF))
255     SavedRegs.set(FP);
256 }
257 
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);
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 
272   RS->addScavengingFrameIndex(FI);
273 }
274