blob: daa7b7a7ea9a1ac44299c422d5fd92918124ab1f [file] [log] [blame]
Alex Bradbury89718422017-10-19 21:37:38 +00001//===-- RISCVFrameLowering.cpp - RISCV Frame Information ------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Alex Bradbury89718422017-10-19 21:37:38 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the RISCV implementation of TargetFrameLowering class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "RISCVFrameLowering.h"
Alex Bradburyc85be0d2018-01-10 19:41:03 +000014#include "RISCVMachineFunctionInfo.h"
Alex Bradbury89718422017-10-19 21:37:38 +000015#include "RISCVSubtarget.h"
16#include "llvm/CodeGen/MachineFrameInfo.h"
17#include "llvm/CodeGen/MachineFunction.h"
18#include "llvm/CodeGen/MachineInstrBuilder.h"
19#include "llvm/CodeGen/MachineRegisterInfo.h"
Alex Bradbury0715d352018-01-11 11:17:19 +000020#include "llvm/CodeGen/RegisterScavenging.h"
Simon Cookaed9d6d2019-10-22 21:25:01 +010021#include "llvm/IR/DiagnosticInfo.h"
Hsiangkai Wang04ddf392019-06-12 03:04:22 +000022#include "llvm/MC/MCDwarf.h"
Alex Bradbury89718422017-10-19 21:37:38 +000023
24using namespace llvm;
25
Alex Bradbury7d6aa1f2018-01-18 11:34:02 +000026bool RISCVFrameLowering::hasFP(const MachineFunction &MF) const {
27 const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
28
29 const MachineFrameInfo &MFI = MF.getFrameInfo();
30 return MF.getTarget().Options.DisableFramePointerElim(MF) ||
31 RegInfo->needsStackRealignment(MF) || MFI.hasVarSizedObjects() ||
32 MFI.isFrameAddressTaken();
33}
Alex Bradbury89718422017-10-19 21:37:38 +000034
Alex Bradburyb014e3d2017-12-11 12:34:11 +000035// Determines the size of the frame and maximum call frame size.
36void RISCVFrameLowering::determineFrameLayout(MachineFunction &MF) const {
37 MachineFrameInfo &MFI = MF.getFrameInfo();
38 const RISCVRegisterInfo *RI = STI.getRegisterInfo();
39
40 // Get the number of bytes to allocate from the FrameInfo.
41 uint64_t FrameSize = MFI.getStackSize();
42
43 // Get the alignment.
Sam Elliottcd44aee2019-08-08 14:40:54 +000044 unsigned StackAlign = getStackAlignment();
45 if (RI->needsStackRealignment(MF)) {
46 unsigned MaxStackAlign = std::max(StackAlign, MFI.getMaxAlignment());
47 FrameSize += (MaxStackAlign - StackAlign);
48 StackAlign = MaxStackAlign;
49 }
50
51 // Set Max Call Frame Size
52 uint64_t MaxCallSize = alignTo(MFI.getMaxCallFrameSize(), StackAlign);
53 MFI.setMaxCallFrameSize(MaxCallSize);
Alex Bradburyb014e3d2017-12-11 12:34:11 +000054
Alex Bradburyb014e3d2017-12-11 12:34:11 +000055 // Make sure the frame is aligned.
56 FrameSize = alignTo(FrameSize, StackAlign);
57
58 // Update frame info.
59 MFI.setStackSize(FrameSize);
60}
61
62void RISCVFrameLowering::adjustReg(MachineBasicBlock &MBB,
63 MachineBasicBlock::iterator MBBI,
Luis Marquesfa06e952019-08-16 14:27:50 +000064 const DebugLoc &DL, Register DestReg,
65 Register SrcReg, int64_t Val,
Alex Bradburyb014e3d2017-12-11 12:34:11 +000066 MachineInstr::MIFlag Flag) const {
Alex Bradbury9fea4882018-01-10 19:53:46 +000067 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
Alex Bradburyb014e3d2017-12-11 12:34:11 +000068 const RISCVInstrInfo *TII = STI.getInstrInfo();
69
70 if (DestReg == SrcReg && Val == 0)
71 return;
72
Alex Bradbury9fea4882018-01-10 19:53:46 +000073 if (isInt<12>(Val)) {
74 BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), DestReg)
75 .addReg(SrcReg)
76 .addImm(Val)
77 .setMIFlag(Flag);
Shiva Chena49a16d2019-09-13 04:03:32 +000078 } else {
Alex Bradbury9fea4882018-01-10 19:53:46 +000079 unsigned Opc = RISCV::ADD;
80 bool isSub = Val < 0;
81 if (isSub) {
82 Val = -Val;
83 Opc = RISCV::SUB;
84 }
Alex Bradburyb014e3d2017-12-11 12:34:11 +000085
Daniel Sanders38368742019-08-12 22:41:02 +000086 Register ScratchReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
Shiva Chena49a16d2019-09-13 04:03:32 +000087 TII->movImm(MBB, MBBI, DL, ScratchReg, Val, Flag);
Alex Bradbury9fea4882018-01-10 19:53:46 +000088 BuildMI(MBB, MBBI, DL, TII->get(Opc), DestReg)
89 .addReg(SrcReg)
90 .addReg(ScratchReg, RegState::Kill)
91 .setMIFlag(Flag);
Alex Bradbury9fea4882018-01-10 19:53:46 +000092 }
Alex Bradburyb014e3d2017-12-11 12:34:11 +000093}
94
95// Returns the register used to hold the frame pointer.
Luis Marquesfa06e952019-08-16 14:27:50 +000096static Register getFPReg(const RISCVSubtarget &STI) { return RISCV::X8; }
Alex Bradburyb014e3d2017-12-11 12:34:11 +000097
98// Returns the register used to hold the stack pointer.
Luis Marquesfa06e952019-08-16 14:27:50 +000099static Register getSPReg(const RISCVSubtarget &STI) { return RISCV::X2; }
Alex Bradburyb014e3d2017-12-11 12:34:11 +0000100
Alex Bradbury89718422017-10-19 21:37:38 +0000101void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
Alex Bradburyb014e3d2017-12-11 12:34:11 +0000102 MachineBasicBlock &MBB) const {
103 assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
104
Alex Bradburyb014e3d2017-12-11 12:34:11 +0000105 MachineFrameInfo &MFI = MF.getFrameInfo();
Alex Bradburyc85be0d2018-01-10 19:41:03 +0000106 auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
Hsiangkai Wang04ddf392019-06-12 03:04:22 +0000107 const RISCVRegisterInfo *RI = STI.getRegisterInfo();
108 const RISCVInstrInfo *TII = STI.getInstrInfo();
Alex Bradburyb014e3d2017-12-11 12:34:11 +0000109 MachineBasicBlock::iterator MBBI = MBB.begin();
110
Sam Elliottcd44aee2019-08-08 14:40:54 +0000111 if (RI->needsStackRealignment(MF) && MFI.hasVarSizedObjects()) {
112 report_fatal_error(
113 "RISC-V backend can't currently handle functions that need stack "
114 "realignment and have variable sized objects");
115 }
116
Luis Marquesfa06e952019-08-16 14:27:50 +0000117 Register FPReg = getFPReg(STI);
118 Register SPReg = getSPReg(STI);
Alex Bradburyb014e3d2017-12-11 12:34:11 +0000119
120 // Debug location must be unknown since the first debug location is used
121 // to determine the end of the prologue.
122 DebugLoc DL;
123
124 // Determine the correct frame layout
125 determineFrameLayout(MF);
126
127 // FIXME (note copied from Lanai): This appears to be overallocating. Needs
128 // investigation. Get the number of bytes to allocate from the FrameInfo.
129 uint64_t StackSize = MFI.getStackSize();
130
131 // Early exit if there is no need to allocate on the stack
132 if (StackSize == 0 && !MFI.adjustsStack())
133 return;
134
Simon Cookaed9d6d2019-10-22 21:25:01 +0100135 // If the stack pointer has been marked as reserved, then produce an error if
136 // the frame requires stack allocation
137 if (STI.isRegisterReservedByUser(SPReg))
138 MF.getFunction().getContext().diagnose(DiagnosticInfoUnsupported{
139 MF.getFunction(), "Stack pointer required, but has been reserved."});
140
Shiva Chenff55e2e2019-10-04 02:00:57 +0000141 uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF);
142 // Split the SP adjustment to reduce the offsets of callee saved spill.
143 if (FirstSPAdjustAmount)
144 StackSize = FirstSPAdjustAmount;
145
Alex Bradburyb014e3d2017-12-11 12:34:11 +0000146 // Allocate space on the stack if necessary.
147 adjustReg(MBB, MBBI, DL, SPReg, SPReg, -StackSize, MachineInstr::FrameSetup);
148
Hsiangkai Wang04ddf392019-06-12 03:04:22 +0000149 // Emit ".cfi_def_cfa_offset StackSize"
150 unsigned CFIIndex = MF.addFrameInst(
151 MCCFIInstruction::createDefCfaOffset(nullptr, -StackSize));
152 BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
153 .addCFIIndex(CFIIndex);
154
Alex Bradburyb014e3d2017-12-11 12:34:11 +0000155 // The frame pointer is callee-saved, and code has been generated for us to
156 // save it to the stack. We need to skip over the storing of callee-saved
157 // registers as the frame pointer must be modified after it has been saved
158 // to the stack, not before.
159 // FIXME: assumes exactly one instruction is used to save each callee-saved
160 // register.
161 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
162 std::advance(MBBI, CSI.size());
163
Hsiangkai Wang04ddf392019-06-12 03:04:22 +0000164 // Iterate over list of callee-saved registers and emit .cfi_offset
165 // directives.
166 for (const auto &Entry : CSI) {
167 int64_t Offset = MFI.getObjectOffset(Entry.getFrameIdx());
Luis Marquesfa06e952019-08-16 14:27:50 +0000168 Register Reg = Entry.getReg();
Hsiangkai Wang04ddf392019-06-12 03:04:22 +0000169 unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
170 nullptr, RI->getDwarfRegNum(Reg, true), Offset));
171 BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
172 .addCFIIndex(CFIIndex);
173 }
174
Alex Bradburyb014e3d2017-12-11 12:34:11 +0000175 // Generate new FP.
Hsiangkai Wang04ddf392019-06-12 03:04:22 +0000176 if (hasFP(MF)) {
Simon Cookaed9d6d2019-10-22 21:25:01 +0100177 if (STI.isRegisterReservedByUser(FPReg))
178 MF.getFunction().getContext().diagnose(DiagnosticInfoUnsupported{
179 MF.getFunction(), "Frame pointer required, but has been reserved."});
180
Alex Bradbury7d6aa1f2018-01-18 11:34:02 +0000181 adjustReg(MBB, MBBI, DL, FPReg, SPReg,
182 StackSize - RVFI->getVarArgsSaveSize(), MachineInstr::FrameSetup);
Hsiangkai Wang04ddf392019-06-12 03:04:22 +0000183
184 // Emit ".cfi_def_cfa $fp, 0"
185 unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfa(
186 nullptr, RI->getDwarfRegNum(FPReg, true), 0));
187 BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
188 .addCFIIndex(CFIIndex);
Shiva Chenff55e2e2019-10-04 02:00:57 +0000189 }
Sam Elliottcd44aee2019-08-08 14:40:54 +0000190
Shiva Chenff55e2e2019-10-04 02:00:57 +0000191 // Emit the second SP adjustment after saving callee saved registers.
192 if (FirstSPAdjustAmount) {
193 uint64_t SecondSPAdjustAmount = MFI.getStackSize() - FirstSPAdjustAmount;
194 assert(SecondSPAdjustAmount > 0 &&
195 "SecondSPAdjustAmount should be greater than zero");
196 adjustReg(MBB, MBBI, DL, SPReg, SPReg, -SecondSPAdjustAmount,
197 MachineInstr::FrameSetup);
198 // Emit ".cfi_def_cfa_offset StackSize"
199 unsigned CFIIndex = MF.addFrameInst(
200 MCCFIInstruction::createDefCfaOffset(nullptr, -MFI.getStackSize()));
201 BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
202 .addCFIIndex(CFIIndex);
203 }
204
205 if (hasFP(MF)) {
Sam Elliottcd44aee2019-08-08 14:40:54 +0000206 // Realign Stack
207 const RISCVRegisterInfo *RI = STI.getRegisterInfo();
208 if (RI->needsStackRealignment(MF)) {
209 unsigned MaxAlignment = MFI.getMaxAlignment();
210
211 const RISCVInstrInfo *TII = STI.getInstrInfo();
212 if (isInt<12>(-(int)MaxAlignment)) {
213 BuildMI(MBB, MBBI, DL, TII->get(RISCV::ANDI), SPReg)
214 .addReg(SPReg)
215 .addImm(-(int)MaxAlignment);
216 } else {
217 unsigned ShiftAmount = countTrailingZeros(MaxAlignment);
Luis Marquesfa06e952019-08-16 14:27:50 +0000218 Register VR =
Sam Elliottcd44aee2019-08-08 14:40:54 +0000219 MF.getRegInfo().createVirtualRegister(&RISCV::GPRRegClass);
220 BuildMI(MBB, MBBI, DL, TII->get(RISCV::SRLI), VR)
221 .addReg(SPReg)
222 .addImm(ShiftAmount);
223 BuildMI(MBB, MBBI, DL, TII->get(RISCV::SLLI), SPReg)
224 .addReg(VR)
225 .addImm(ShiftAmount);
226 }
227 }
Hsiangkai Wang04ddf392019-06-12 03:04:22 +0000228 }
Alex Bradburyb014e3d2017-12-11 12:34:11 +0000229}
Alex Bradbury89718422017-10-19 21:37:38 +0000230
231void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
Alex Bradburyb014e3d2017-12-11 12:34:11 +0000232 MachineBasicBlock &MBB) const {
Alex Bradburyb014e3d2017-12-11 12:34:11 +0000233 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
234 const RISCVRegisterInfo *RI = STI.getRegisterInfo();
235 MachineFrameInfo &MFI = MF.getFrameInfo();
Alex Bradburyc85be0d2018-01-10 19:41:03 +0000236 auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
Alex Bradburyb014e3d2017-12-11 12:34:11 +0000237 DebugLoc DL = MBBI->getDebugLoc();
Hsiangkai Wang04ddf392019-06-12 03:04:22 +0000238 const RISCVInstrInfo *TII = STI.getInstrInfo();
Luis Marquesfa06e952019-08-16 14:27:50 +0000239 Register FPReg = getFPReg(STI);
240 Register SPReg = getSPReg(STI);
Alex Bradburyb014e3d2017-12-11 12:34:11 +0000241
242 // Skip to before the restores of callee-saved registers
243 // FIXME: assumes exactly one instruction is used to restore each
244 // callee-saved register.
Ana Pazos61b28ede72018-08-24 23:13:59 +0000245 auto LastFrameDestroy = std::prev(MBBI, MFI.getCalleeSavedInfo().size());
Alex Bradburyb014e3d2017-12-11 12:34:11 +0000246
247 uint64_t StackSize = MFI.getStackSize();
Hsiangkai Wang04ddf392019-06-12 03:04:22 +0000248 uint64_t FPOffset = StackSize - RVFI->getVarArgsSaveSize();
Alex Bradburyb014e3d2017-12-11 12:34:11 +0000249
250 // Restore the stack pointer using the value of the frame pointer. Only
251 // necessary if the stack pointer was modified, meaning the stack size is
252 // unknown.
253 if (RI->needsStackRealignment(MF) || MFI.hasVarSizedObjects()) {
Alex Bradbury7d6aa1f2018-01-18 11:34:02 +0000254 assert(hasFP(MF) && "frame pointer should not have been eliminated");
Hsiangkai Wang04ddf392019-06-12 03:04:22 +0000255 adjustReg(MBB, LastFrameDestroy, DL, SPReg, FPReg, -FPOffset,
Alex Bradburyb014e3d2017-12-11 12:34:11 +0000256 MachineInstr::FrameDestroy);
257 }
258
Shiva Chenff55e2e2019-10-04 02:00:57 +0000259 uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF);
260 if (FirstSPAdjustAmount) {
261 uint64_t SecondSPAdjustAmount = MFI.getStackSize() - FirstSPAdjustAmount;
262 assert(SecondSPAdjustAmount > 0 &&
263 "SecondSPAdjustAmount should be greater than zero");
264
265 adjustReg(MBB, LastFrameDestroy, DL, SPReg, SPReg, SecondSPAdjustAmount,
266 MachineInstr::FrameDestroy);
267
268 // Emit ".cfi_def_cfa_offset FirstSPAdjustAmount"
269 unsigned CFIIndex =
270 MF.addFrameInst(
271 MCCFIInstruction::createDefCfaOffset(nullptr,
272 -FirstSPAdjustAmount));
273 BuildMI(MBB, LastFrameDestroy, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
274 .addCFIIndex(CFIIndex);
275 }
276
Hsiangkai Wang04ddf392019-06-12 03:04:22 +0000277 if (hasFP(MF)) {
278 // To find the instruction restoring FP from stack.
279 for (auto &I = LastFrameDestroy; I != MBBI; ++I) {
280 if (I->mayLoad() && I->getOperand(0).isReg()) {
Daniel Sanders38368742019-08-12 22:41:02 +0000281 Register DestReg = I->getOperand(0).getReg();
Hsiangkai Wang04ddf392019-06-12 03:04:22 +0000282 if (DestReg == FPReg) {
283 // If there is frame pointer, after restoring $fp registers, we
284 // need adjust CFA to ($sp - FPOffset).
285 // Emit ".cfi_def_cfa $sp, -FPOffset"
286 unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfa(
287 nullptr, RI->getDwarfRegNum(SPReg, true), -FPOffset));
288 BuildMI(MBB, std::next(I), DL,
289 TII->get(TargetOpcode::CFI_INSTRUCTION))
290 .addCFIIndex(CFIIndex);
291 break;
292 }
293 }
294 }
295 }
296
297 // Add CFI directives for callee-saved registers.
298 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
299 // Iterate over list of callee-saved registers and emit .cfi_restore
300 // directives.
301 for (const auto &Entry : CSI) {
Luis Marquesfa06e952019-08-16 14:27:50 +0000302 Register Reg = Entry.getReg();
Hsiangkai Wang04ddf392019-06-12 03:04:22 +0000303 unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createRestore(
304 nullptr, RI->getDwarfRegNum(Reg, true)));
305 BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
306 .addCFIIndex(CFIIndex);
307 }
308
Shiva Chenff55e2e2019-10-04 02:00:57 +0000309 if (FirstSPAdjustAmount)
310 StackSize = FirstSPAdjustAmount;
311
Alex Bradburyb014e3d2017-12-11 12:34:11 +0000312 // Deallocate stack
313 adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackSize, MachineInstr::FrameDestroy);
Hsiangkai Wang04ddf392019-06-12 03:04:22 +0000314
315 // After restoring $sp, we need to adjust CFA to $(sp + 0)
316 // Emit ".cfi_def_cfa_offset 0"
317 unsigned CFIIndex =
318 MF.addFrameInst(MCCFIInstruction::createDefCfaOffset(nullptr, 0));
319 BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
320 .addCFIIndex(CFIIndex);
Alex Bradburyb014e3d2017-12-11 12:34:11 +0000321}
Alex Bradbury660bcce2017-12-11 11:53:54 +0000322
323int RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF,
324 int FI,
325 unsigned &FrameReg) const {
326 const MachineFrameInfo &MFI = MF.getFrameInfo();
327 const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo();
Alex Bradburyc85be0d2018-01-10 19:41:03 +0000328 const auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
Alex Bradbury660bcce2017-12-11 11:53:54 +0000329
330 // Callee-saved registers should be referenced relative to the stack
331 // pointer (positive offset), otherwise use the frame pointer (negative
332 // offset).
333 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
334 int MinCSFI = 0;
335 int MaxCSFI = -1;
336
337 int Offset = MFI.getObjectOffset(FI) - getOffsetOfLocalArea() +
338 MFI.getOffsetAdjustment();
339
Shiva Chenff55e2e2019-10-04 02:00:57 +0000340 uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF);
341
Alex Bradbury660bcce2017-12-11 11:53:54 +0000342 if (CSI.size()) {
343 MinCSFI = CSI[0].getFrameIdx();
344 MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
345 }
346
Alex Bradbury660bcce2017-12-11 11:53:54 +0000347 if (FI >= MinCSFI && FI <= MaxCSFI) {
348 FrameReg = RISCV::X2;
Shiva Chenff55e2e2019-10-04 02:00:57 +0000349
350 if (FirstSPAdjustAmount)
351 Offset += FirstSPAdjustAmount;
352 else
353 Offset += MF.getFrameInfo().getStackSize();
Sam Elliottcd44aee2019-08-08 14:40:54 +0000354 } else if (RI->needsStackRealignment(MF)) {
355 assert(!MFI.hasVarSizedObjects() &&
356 "Unexpected combination of stack realignment and varsized objects");
357 // If the stack was realigned, the frame pointer is set in order to allow
358 // SP to be restored, but we still access stack objects using SP.
359 FrameReg = RISCV::X2;
360 Offset += MF.getFrameInfo().getStackSize();
Alex Bradburyc85be0d2018-01-10 19:41:03 +0000361 } else {
362 FrameReg = RI->getFrameRegister(MF);
Alex Bradbury7d6aa1f2018-01-18 11:34:02 +0000363 if (hasFP(MF))
364 Offset += RVFI->getVarArgsSaveSize();
365 else
366 Offset += MF.getFrameInfo().getStackSize();
Alex Bradbury660bcce2017-12-11 11:53:54 +0000367 }
368 return Offset;
369}
Alex Bradburyb014e3d2017-12-11 12:34:11 +0000370
371void RISCVFrameLowering::determineCalleeSaves(MachineFunction &MF,
372 BitVector &SavedRegs,
373 RegScavenger *RS) const {
374 TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
Alex Bradbury7d6aa1f2018-01-18 11:34:02 +0000375 // Unconditionally spill RA and FP only if the function uses a frame
376 // pointer.
377 if (hasFP(MF)) {
378 SavedRegs.set(RISCV::X1);
379 SavedRegs.set(RISCV::X8);
380 }
Ana Pazos2e4106b2018-07-26 17:49:43 +0000381
382 // If interrupt is enabled and there are calls in the handler,
383 // unconditionally save all Caller-saved registers and
384 // all FP registers, regardless whether they are used.
385 MachineFrameInfo &MFI = MF.getFrameInfo();
386
387 if (MF.getFunction().hasFnAttribute("interrupt") && MFI.hasCalls()) {
388
389 static const MCPhysReg CSRegs[] = { RISCV::X1, /* ra */
390 RISCV::X5, RISCV::X6, RISCV::X7, /* t0-t2 */
391 RISCV::X10, RISCV::X11, /* a0-a1, a2-a7 */
392 RISCV::X12, RISCV::X13, RISCV::X14, RISCV::X15, RISCV::X16, RISCV::X17,
393 RISCV::X28, RISCV::X29, RISCV::X30, RISCV::X31, 0 /* t3-t6 */
394 };
395
396 for (unsigned i = 0; CSRegs[i]; ++i)
397 SavedRegs.set(CSRegs[i]);
398
399 if (MF.getSubtarget<RISCVSubtarget>().hasStdExtD() ||
400 MF.getSubtarget<RISCVSubtarget>().hasStdExtF()) {
401
402 // If interrupt is enabled, this list contains all FP registers.
403 const MCPhysReg * Regs = MF.getRegInfo().getCalleeSavedRegs();
404
405 for (unsigned i = 0; Regs[i]; ++i)
406 if (RISCV::FPR32RegClass.contains(Regs[i]) ||
407 RISCV::FPR64RegClass.contains(Regs[i]))
408 SavedRegs.set(Regs[i]);
409 }
410 }
Alex Bradburyb014e3d2017-12-11 12:34:11 +0000411}
Alex Bradbury0715d352018-01-11 11:17:19 +0000412
413void RISCVFrameLowering::processFunctionBeforeFrameFinalized(
414 MachineFunction &MF, RegScavenger *RS) const {
415 const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
416 MachineFrameInfo &MFI = MF.getFrameInfo();
417 const TargetRegisterClass *RC = &RISCV::GPRRegClass;
418 // estimateStackSize has been observed to under-estimate the final stack
419 // size, so give ourselves wiggle-room by checking for stack size
420 // representable an 11-bit signed field rather than 12-bits.
421 // FIXME: It may be possible to craft a function with a small stack that
422 // still needs an emergency spill slot for branch relaxation. This case
423 // would currently be missed.
424 if (!isInt<11>(MFI.estimateStackSize(MF))) {
425 int RegScavFI = MFI.CreateStackObject(
426 RegInfo->getSpillSize(*RC), RegInfo->getSpillAlignment(*RC), false);
427 RS->addScavengingFrameIndex(RegScavFI);
428 }
429}
Shiva Chencbd498a2018-03-20 01:39:17 +0000430
431// Not preserve stack space within prologue for outgoing variables when the
432// function contains variable size objects and let eliminateCallFramePseudoInstr
433// preserve stack space for it.
434bool RISCVFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
435 return !MF.getFrameInfo().hasVarSizedObjects();
436}
437
438// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions.
439MachineBasicBlock::iterator RISCVFrameLowering::eliminateCallFramePseudoInstr(
440 MachineFunction &MF, MachineBasicBlock &MBB,
441 MachineBasicBlock::iterator MI) const {
Luis Marquesfa06e952019-08-16 14:27:50 +0000442 Register SPReg = RISCV::X2;
Shiva Chencbd498a2018-03-20 01:39:17 +0000443 DebugLoc DL = MI->getDebugLoc();
444
445 if (!hasReservedCallFrame(MF)) {
446 // If space has not been reserved for a call frame, ADJCALLSTACKDOWN and
447 // ADJCALLSTACKUP must be converted to instructions manipulating the stack
448 // pointer. This is necessary when there is a variable length stack
449 // allocation (e.g. alloca), which means it's not possible to allocate
450 // space for outgoing arguments from within the function prologue.
451 int64_t Amount = MI->getOperand(0).getImm();
452
453 if (Amount != 0) {
454 // Ensure the stack remains aligned after adjustment.
455 Amount = alignSPAdjust(Amount);
456
457 if (MI->getOpcode() == RISCV::ADJCALLSTACKDOWN)
458 Amount = -Amount;
459
460 adjustReg(MBB, MI, DL, SPReg, SPReg, Amount, MachineInstr::NoFlags);
461 }
462 }
463
464 return MBB.erase(MI);
465}
Shiva Chenff55e2e2019-10-04 02:00:57 +0000466
467// We would like to split the SP adjustment to reduce prologue/epilogue
468// as following instructions. In this way, the offset of the callee saved
469// register could fit in a single store.
470// add sp,sp,-2032
471// sw ra,2028(sp)
472// sw s0,2024(sp)
473// sw s1,2020(sp)
474// sw s3,2012(sp)
475// sw s4,2008(sp)
476// add sp,sp,-64
477uint64_t
478RISCVFrameLowering::getFirstSPAdjustAmount(const MachineFunction &MF) const {
479 const MachineFrameInfo &MFI = MF.getFrameInfo();
480 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
481 uint64_t StackSize = MFI.getStackSize();
482 uint64_t StackAlign = getStackAlignment();
483
484 // FIXME: Disable SplitSPAdjust if save-restore libcall enabled when the patch
485 // landing. The callee saved registers will be pushed by the
486 // save-restore libcalls, so we don't have to split the SP adjustment
487 // in this case.
488 //
489 // Return the FirstSPAdjustAmount if the StackSize can not fit in signed
490 // 12-bit and there exists a callee saved register need to be pushed.
491 if (!isInt<12>(StackSize) && (CSI.size() > 0)) {
492 // FirstSPAdjustAmount is choosed as (2048 - StackAlign)
493 // because 2048 will cause sp = sp + 2048 in epilogue split into
494 // multi-instructions. The offset smaller than 2048 can fit in signle
495 // load/store instruction and we have to stick with the stack alignment.
496 // 2048 is 16-byte alignment. The stack alignment for RV32 and RV64 is 16,
497 // for RV32E is 4. So (2048 - StackAlign) will satisfy the stack alignment.
498 return 2048 - StackAlign;
499 }
500 return 0;
501}