LLVM  9.0.0svn
RISCVFrameLowering.cpp
Go to the documentation of this file.
1 //===-- RISCVFrameLowering.cpp - RISCV 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 RISCV implementation of TargetFrameLowering class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "RISCVFrameLowering.h"
15 #include "RISCVSubtarget.h"
21 
22 using namespace llvm;
23 
25  const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
26 
27  const MachineFrameInfo &MFI = MF.getFrameInfo();
28  return MF.getTarget().Options.DisableFramePointerElim(MF) ||
29  RegInfo->needsStackRealignment(MF) || MFI.hasVarSizedObjects() ||
30  MFI.isFrameAddressTaken();
31 }
32 
33 // Determines the size of the frame and maximum call frame size.
34 void RISCVFrameLowering::determineFrameLayout(MachineFunction &MF) const {
35  MachineFrameInfo &MFI = MF.getFrameInfo();
37 
38  // Get the number of bytes to allocate from the FrameInfo.
39  uint64_t FrameSize = MFI.getStackSize();
40 
41  // Get the alignment.
42  uint64_t StackAlign = RI->needsStackRealignment(MF) ? MFI.getMaxAlignment()
44 
45  // Make sure the frame is aligned.
46  FrameSize = alignTo(FrameSize, StackAlign);
47 
48  // Update frame info.
49  MFI.setStackSize(FrameSize);
50 }
51 
52 void RISCVFrameLowering::adjustReg(MachineBasicBlock &MBB,
54  const DebugLoc &DL, unsigned DestReg,
55  unsigned SrcReg, int64_t Val,
56  MachineInstr::MIFlag Flag) const {
59 
60  if (DestReg == SrcReg && Val == 0)
61  return;
62 
63  if (isInt<12>(Val)) {
64  BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), DestReg)
65  .addReg(SrcReg)
66  .addImm(Val)
67  .setMIFlag(Flag);
68  } else if (isInt<32>(Val)) {
69  unsigned Opc = RISCV::ADD;
70  bool isSub = Val < 0;
71  if (isSub) {
72  Val = -Val;
73  Opc = RISCV::SUB;
74  }
75 
76  unsigned ScratchReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
77  TII->movImm32(MBB, MBBI, DL, ScratchReg, Val, Flag);
78  BuildMI(MBB, MBBI, DL, TII->get(Opc), DestReg)
79  .addReg(SrcReg)
80  .addReg(ScratchReg, RegState::Kill)
81  .setMIFlag(Flag);
82  } else {
83  report_fatal_error("adjustReg cannot yet handle adjustments >32 bits");
84  }
85 }
86 
87 // Returns the register used to hold the frame pointer.
88 static unsigned getFPReg(const RISCVSubtarget &STI) { return RISCV::X8; }
89 
90 // Returns the register used to hold the stack pointer.
91 static unsigned getSPReg(const RISCVSubtarget &STI) { return RISCV::X2; }
92 
94  MachineBasicBlock &MBB) const {
95  assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
96 
97  MachineFrameInfo &MFI = MF.getFrameInfo();
98  auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
100 
101  unsigned FPReg = getFPReg(STI);
102  unsigned SPReg = getSPReg(STI);
103 
104  // Debug location must be unknown since the first debug location is used
105  // to determine the end of the prologue.
106  DebugLoc DL;
107 
108  // Determine the correct frame layout
109  determineFrameLayout(MF);
110 
111  // FIXME (note copied from Lanai): This appears to be overallocating. Needs
112  // investigation. Get the number of bytes to allocate from the FrameInfo.
113  uint64_t StackSize = MFI.getStackSize();
114 
115  // Early exit if there is no need to allocate on the stack
116  if (StackSize == 0 && !MFI.adjustsStack())
117  return;
118 
119  // Allocate space on the stack if necessary.
120  adjustReg(MBB, MBBI, DL, SPReg, SPReg, -StackSize, MachineInstr::FrameSetup);
121 
122  // The frame pointer is callee-saved, and code has been generated for us to
123  // save it to the stack. We need to skip over the storing of callee-saved
124  // registers as the frame pointer must be modified after it has been saved
125  // to the stack, not before.
126  // FIXME: assumes exactly one instruction is used to save each callee-saved
127  // register.
128  const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
129  std::advance(MBBI, CSI.size());
130 
131  // Generate new FP.
132  if (hasFP(MF))
133  adjustReg(MBB, MBBI, DL, FPReg, SPReg,
134  StackSize - RVFI->getVarArgsSaveSize(), MachineInstr::FrameSetup);
135 }
136 
138  MachineBasicBlock &MBB) const {
140  const RISCVRegisterInfo *RI = STI.getRegisterInfo();
141  MachineFrameInfo &MFI = MF.getFrameInfo();
142  auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
143  DebugLoc DL = MBBI->getDebugLoc();
144  unsigned FPReg = getFPReg(STI);
145  unsigned SPReg = getSPReg(STI);
146 
147  // Skip to before the restores of callee-saved registers
148  // FIXME: assumes exactly one instruction is used to restore each
149  // callee-saved register.
150  auto LastFrameDestroy = std::prev(MBBI, MFI.getCalleeSavedInfo().size());
151 
152  uint64_t StackSize = MFI.getStackSize();
153 
154  // Restore the stack pointer using the value of the frame pointer. Only
155  // necessary if the stack pointer was modified, meaning the stack size is
156  // unknown.
157  if (RI->needsStackRealignment(MF) || MFI.hasVarSizedObjects()) {
158  assert(hasFP(MF) && "frame pointer should not have been eliminated");
159  adjustReg(MBB, LastFrameDestroy, DL, SPReg, FPReg,
160  -StackSize + RVFI->getVarArgsSaveSize(),
162  }
163 
164  // Deallocate stack
165  adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackSize, MachineInstr::FrameDestroy);
166 }
167 
169  int FI,
170  unsigned &FrameReg) const {
171  const MachineFrameInfo &MFI = MF.getFrameInfo();
173  const auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
174 
175  // Callee-saved registers should be referenced relative to the stack
176  // pointer (positive offset), otherwise use the frame pointer (negative
177  // offset).
178  const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
179  int MinCSFI = 0;
180  int MaxCSFI = -1;
181 
182  int Offset = MFI.getObjectOffset(FI) - getOffsetOfLocalArea() +
183  MFI.getOffsetAdjustment();
184 
185  if (CSI.size()) {
186  MinCSFI = CSI[0].getFrameIdx();
187  MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
188  }
189 
190  if (FI >= MinCSFI && FI <= MaxCSFI) {
191  FrameReg = RISCV::X2;
192  Offset += MF.getFrameInfo().getStackSize();
193  } else {
194  FrameReg = RI->getFrameRegister(MF);
195  if (hasFP(MF))
196  Offset += RVFI->getVarArgsSaveSize();
197  else
198  Offset += MF.getFrameInfo().getStackSize();
199  }
200  return Offset;
201 }
202 
204  BitVector &SavedRegs,
205  RegScavenger *RS) const {
207  // Unconditionally spill RA and FP only if the function uses a frame
208  // pointer.
209  if (hasFP(MF)) {
210  SavedRegs.set(RISCV::X1);
211  SavedRegs.set(RISCV::X8);
212  }
213 
214  // If interrupt is enabled and there are calls in the handler,
215  // unconditionally save all Caller-saved registers and
216  // all FP registers, regardless whether they are used.
217  MachineFrameInfo &MFI = MF.getFrameInfo();
218 
219  if (MF.getFunction().hasFnAttribute("interrupt") && MFI.hasCalls()) {
220 
221  static const MCPhysReg CSRegs[] = { RISCV::X1, /* ra */
222  RISCV::X5, RISCV::X6, RISCV::X7, /* t0-t2 */
223  RISCV::X10, RISCV::X11, /* a0-a1, a2-a7 */
224  RISCV::X12, RISCV::X13, RISCV::X14, RISCV::X15, RISCV::X16, RISCV::X17,
225  RISCV::X28, RISCV::X29, RISCV::X30, RISCV::X31, 0 /* t3-t6 */
226  };
227 
228  for (unsigned i = 0; CSRegs[i]; ++i)
229  SavedRegs.set(CSRegs[i]);
230 
231  if (MF.getSubtarget<RISCVSubtarget>().hasStdExtD() ||
232  MF.getSubtarget<RISCVSubtarget>().hasStdExtF()) {
233 
234  // If interrupt is enabled, this list contains all FP registers.
235  const MCPhysReg * Regs = MF.getRegInfo().getCalleeSavedRegs();
236 
237  for (unsigned i = 0; Regs[i]; ++i)
238  if (RISCV::FPR32RegClass.contains(Regs[i]) ||
239  RISCV::FPR64RegClass.contains(Regs[i]))
240  SavedRegs.set(Regs[i]);
241  }
242  }
243 }
244 
246  MachineFunction &MF, RegScavenger *RS) const {
247  const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
248  MachineFrameInfo &MFI = MF.getFrameInfo();
249  const TargetRegisterClass *RC = &RISCV::GPRRegClass;
250  // estimateStackSize has been observed to under-estimate the final stack
251  // size, so give ourselves wiggle-room by checking for stack size
252  // representable an 11-bit signed field rather than 12-bits.
253  // FIXME: It may be possible to craft a function with a small stack that
254  // still needs an emergency spill slot for branch relaxation. This case
255  // would currently be missed.
256  if (!isInt<11>(MFI.estimateStackSize(MF))) {
257  int RegScavFI = MFI.CreateStackObject(
258  RegInfo->getSpillSize(*RC), RegInfo->getSpillAlignment(*RC), false);
259  RS->addScavengingFrameIndex(RegScavFI);
260  }
261 }
262 
263 // Not preserve stack space within prologue for outgoing variables when the
264 // function contains variable size objects and let eliminateCallFramePseudoInstr
265 // preserve stack space for it.
267  return !MF.getFrameInfo().hasVarSizedObjects();
268 }
269 
270 // Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions.
274  unsigned SPReg = RISCV::X2;
275  DebugLoc DL = MI->getDebugLoc();
276 
277  if (!hasReservedCallFrame(MF)) {
278  // If space has not been reserved for a call frame, ADJCALLSTACKDOWN and
279  // ADJCALLSTACKUP must be converted to instructions manipulating the stack
280  // pointer. This is necessary when there is a variable length stack
281  // allocation (e.g. alloca), which means it's not possible to allocate
282  // space for outgoing arguments from within the function prologue.
283  int64_t Amount = MI->getOperand(0).getImm();
284 
285  if (Amount != 0) {
286  // Ensure the stack remains aligned after adjustment.
287  Amount = alignSPAdjust(Amount);
288 
289  if (MI->getOpcode() == RISCV::ADJCALLSTACKDOWN)
290  Amount = -Amount;
291 
292  adjustReg(MBB, MI, DL, SPReg, SPReg, Amount, MachineInstr::NoFlags);
293  }
294  }
295 
296  return MBB.erase(MI);
297 }
BitVector & set()
Definition: BitVector.h:397
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:139
This class represents lattice values for constants.
Definition: AllocatorList.h:23
bool hasFP(const MachineFunction &MF) const override
hasFP - Return true if the specified function should have a dedicated frame pointer register...
int getFrameIndexReference(const MachineFunction &MF, int FI, unsigned &FrameReg) const override
getFrameIndexReference - This method should return the base register and offset used to reference a f...
MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
This method is called during prolog/epilog code insertion to eliminate call frame setup and destroy p...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
const RISCVRegisterInfo * getRegisterInfo() const override
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition: Function.h:320
A debug info location.
Definition: DebugLoc.h:33
uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew=0)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
Definition: MathExtras.h:684
int getOffsetOfLocalArea() const
getOffsetOfLocalArea - This method returns the offset of the local area from the stack pointer on ent...
int CreateStackObject(uint64_t Size, unsigned 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...
unsigned getSpillSize(const TargetRegisterClass &RC) const
Return the size in bytes of the stack slot allocated to hold a spilled copy of a register from class ...
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
return AArch64::GPR64RegClass contains(Reg)
virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
static unsigned getSPReg(const RISCVSubtarget &STI)
unsigned getSpillAlignment(const TargetRegisterClass &RC) const
Return the minimum required alignment in bytes for a spill slot for a register of this class...
bool isFrameAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
const HexagonInstrInfo * TII
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
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 ...
virtual unsigned getFrameRegister(const MachineFunction &MF) const =0
Debug information queries.
bool DisableFramePointerElim(const MachineFunction &MF) const
DisableFramePointerElim - This returns true if frame pointer elimination optimization should be disab...
int alignSPAdjust(int SPAdj) const
alignSPAdjust - This method aligns the stack adjustment to the correct alignment. ...
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:200
void movImm32(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, unsigned DstReg, uint64_t Val, MachineInstr::MIFlag Flag=MachineInstr::NoFlags) const
iterator getLastNonDebugInstr()
Returns an iterator to the last non-debug instruction in the basic block, or end().
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Flag
These should be considered private to the implementation of the MCInstrDesc class.
Definition: MCInstrDesc.h:117
void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS) const override
processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
This file declares the machine register scavenger class.
unsigned const MachineRegisterInfo * MRI
static unsigned getFPReg(const RISCVSubtarget &STI)
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.
void setStackSize(uint64_t Size)
Set the size of the stack.
unsigned getMaxAlignment() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
const MachineBasicBlock & front() const
unsigned getStackAlignment() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
bool hasStdExtD() const
constexpr bool isInt< 32 >(int64_t x)
Definition: MathExtras.h:308
void addScavengingFrameIndex(int FI)
Add a scavenging frame index.
unsigned estimateStackSize(const MachineFunction &MF) const
Estimate and return the size of the stack frame.
bool hasReservedCallFrame(const MachineFunction &MF) const override
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required, we reserve argument space for call sites in the function immediately on entry to the current function.
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
const Function & getFunction() const
Return the LLVM function that this machine code represents.
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
TargetOptions Options
int getOffsetAdjustment() const
Return the correction for frame offsets.
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const RISCVSubtarget & STI
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private RISCV-...
bool needsStackRealignment(const MachineFunction &MF) const
True if storage within the function requires the stack pointer to be aligned more than the normal cal...
const RISCVInstrInfo * getInstrInfo() const override
const MCPhysReg * getCalleeSavedRegs() const
Returns list of callee saved registers.
IRTranslator LLVM IR MI
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects...
unsigned createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
bool hasCalls() const
Return true if the current function has any function calls.