LLVM  8.0.1
RISCVFrameLowering.cpp
Go to the documentation of this file.
1 //===-- RISCVFrameLowering.cpp - RISCV Frame Information ------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains the RISCV implementation of TargetFrameLowering class.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "RISCVFrameLowering.h"
16 #include "RISCVSubtarget.h"
22 
23 using namespace llvm;
24 
26  const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
27 
28  const MachineFrameInfo &MFI = MF.getFrameInfo();
29  return MF.getTarget().Options.DisableFramePointerElim(MF) ||
30  RegInfo->needsStackRealignment(MF) || MFI.hasVarSizedObjects() ||
31  MFI.isFrameAddressTaken();
32 }
33 
34 // Determines the size of the frame and maximum call frame size.
35 void RISCVFrameLowering::determineFrameLayout(MachineFunction &MF) const {
36  MachineFrameInfo &MFI = MF.getFrameInfo();
38 
39  // Get the number of bytes to allocate from the FrameInfo.
40  uint64_t FrameSize = MFI.getStackSize();
41 
42  // Get the alignment.
43  uint64_t StackAlign = RI->needsStackRealignment(MF) ? MFI.getMaxAlignment()
45 
46  // Make sure the frame is aligned.
47  FrameSize = alignTo(FrameSize, StackAlign);
48 
49  // Update frame info.
50  MFI.setStackSize(FrameSize);
51 }
52 
53 void RISCVFrameLowering::adjustReg(MachineBasicBlock &MBB,
55  const DebugLoc &DL, unsigned DestReg,
56  unsigned SrcReg, int64_t Val,
57  MachineInstr::MIFlag Flag) const {
60 
61  if (DestReg == SrcReg && Val == 0)
62  return;
63 
64  if (isInt<12>(Val)) {
65  BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), DestReg)
66  .addReg(SrcReg)
67  .addImm(Val)
68  .setMIFlag(Flag);
69  } else if (isInt<32>(Val)) {
70  unsigned Opc = RISCV::ADD;
71  bool isSub = Val < 0;
72  if (isSub) {
73  Val = -Val;
74  Opc = RISCV::SUB;
75  }
76 
77  unsigned ScratchReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
78  TII->movImm32(MBB, MBBI, DL, ScratchReg, Val, Flag);
79  BuildMI(MBB, MBBI, DL, TII->get(Opc), DestReg)
80  .addReg(SrcReg)
81  .addReg(ScratchReg, RegState::Kill)
82  .setMIFlag(Flag);
83  } else {
84  report_fatal_error("adjustReg cannot yet handle adjustments >32 bits");
85  }
86 }
87 
88 // Returns the register used to hold the frame pointer.
89 static unsigned getFPReg(const RISCVSubtarget &STI) { return RISCV::X8; }
90 
91 // Returns the register used to hold the stack pointer.
92 static unsigned getSPReg(const RISCVSubtarget &STI) { return RISCV::X2; }
93 
95  MachineBasicBlock &MBB) const {
96  assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
97 
98  MachineFrameInfo &MFI = MF.getFrameInfo();
99  auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
100  MachineBasicBlock::iterator MBBI = MBB.begin();
101 
102  unsigned FPReg = getFPReg(STI);
103  unsigned SPReg = getSPReg(STI);
104 
105  // Debug location must be unknown since the first debug location is used
106  // to determine the end of the prologue.
107  DebugLoc DL;
108 
109  // Determine the correct frame layout
110  determineFrameLayout(MF);
111 
112  // FIXME (note copied from Lanai): This appears to be overallocating. Needs
113  // investigation. Get the number of bytes to allocate from the FrameInfo.
114  uint64_t StackSize = MFI.getStackSize();
115 
116  // Early exit if there is no need to allocate on the stack
117  if (StackSize == 0 && !MFI.adjustsStack())
118  return;
119 
120  // Allocate space on the stack if necessary.
121  adjustReg(MBB, MBBI, DL, SPReg, SPReg, -StackSize, MachineInstr::FrameSetup);
122 
123  // The frame pointer is callee-saved, and code has been generated for us to
124  // save it to the stack. We need to skip over the storing of callee-saved
125  // registers as the frame pointer must be modified after it has been saved
126  // to the stack, not before.
127  // FIXME: assumes exactly one instruction is used to save each callee-saved
128  // register.
129  const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
130  std::advance(MBBI, CSI.size());
131 
132  // Generate new FP.
133  if (hasFP(MF))
134  adjustReg(MBB, MBBI, DL, FPReg, SPReg,
135  StackSize - RVFI->getVarArgsSaveSize(), MachineInstr::FrameSetup);
136 }
137 
139  MachineBasicBlock &MBB) const {
141  const RISCVRegisterInfo *RI = STI.getRegisterInfo();
142  MachineFrameInfo &MFI = MF.getFrameInfo();
143  auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
144  DebugLoc DL = MBBI->getDebugLoc();
145  unsigned FPReg = getFPReg(STI);
146  unsigned SPReg = getSPReg(STI);
147 
148  // Skip to before the restores of callee-saved registers
149  // FIXME: assumes exactly one instruction is used to restore each
150  // callee-saved register.
151  auto LastFrameDestroy = std::prev(MBBI, MFI.getCalleeSavedInfo().size());
152 
153  uint64_t StackSize = MFI.getStackSize();
154 
155  // Restore the stack pointer using the value of the frame pointer. Only
156  // necessary if the stack pointer was modified, meaning the stack size is
157  // unknown.
158  if (RI->needsStackRealignment(MF) || MFI.hasVarSizedObjects()) {
159  assert(hasFP(MF) && "frame pointer should not have been eliminated");
160  adjustReg(MBB, LastFrameDestroy, DL, SPReg, FPReg,
161  -StackSize + RVFI->getVarArgsSaveSize(),
163  }
164 
165  // Deallocate stack
166  adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackSize, MachineInstr::FrameDestroy);
167 }
168 
170  int FI,
171  unsigned &FrameReg) const {
172  const MachineFrameInfo &MFI = MF.getFrameInfo();
174  const auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
175 
176  // Callee-saved registers should be referenced relative to the stack
177  // pointer (positive offset), otherwise use the frame pointer (negative
178  // offset).
179  const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
180  int MinCSFI = 0;
181  int MaxCSFI = -1;
182 
183  int Offset = MFI.getObjectOffset(FI) - getOffsetOfLocalArea() +
184  MFI.getOffsetAdjustment();
185 
186  if (CSI.size()) {
187  MinCSFI = CSI[0].getFrameIdx();
188  MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
189  }
190 
191  if (FI >= MinCSFI && FI <= MaxCSFI) {
192  FrameReg = RISCV::X2;
193  Offset += MF.getFrameInfo().getStackSize();
194  } else {
195  FrameReg = RI->getFrameRegister(MF);
196  if (hasFP(MF))
197  Offset += RVFI->getVarArgsSaveSize();
198  else
199  Offset += MF.getFrameInfo().getStackSize();
200  }
201  return Offset;
202 }
203 
205  BitVector &SavedRegs,
206  RegScavenger *RS) const {
208  // Unconditionally spill RA and FP only if the function uses a frame
209  // pointer.
210  if (hasFP(MF)) {
211  SavedRegs.set(RISCV::X1);
212  SavedRegs.set(RISCV::X8);
213  }
214 
215  // If interrupt is enabled and there are calls in the handler,
216  // unconditionally save all Caller-saved registers and
217  // all FP registers, regardless whether they are used.
218  MachineFrameInfo &MFI = MF.getFrameInfo();
219 
220  if (MF.getFunction().hasFnAttribute("interrupt") && MFI.hasCalls()) {
221 
222  static const MCPhysReg CSRegs[] = { RISCV::X1, /* ra */
223  RISCV::X5, RISCV::X6, RISCV::X7, /* t0-t2 */
224  RISCV::X10, RISCV::X11, /* a0-a1, a2-a7 */
225  RISCV::X12, RISCV::X13, RISCV::X14, RISCV::X15, RISCV::X16, RISCV::X17,
226  RISCV::X28, RISCV::X29, RISCV::X30, RISCV::X31, 0 /* t3-t6 */
227  };
228 
229  for (unsigned i = 0; CSRegs[i]; ++i)
230  SavedRegs.set(CSRegs[i]);
231 
232  if (MF.getSubtarget<RISCVSubtarget>().hasStdExtD() ||
233  MF.getSubtarget<RISCVSubtarget>().hasStdExtF()) {
234 
235  // If interrupt is enabled, this list contains all FP registers.
236  const MCPhysReg * Regs = MF.getRegInfo().getCalleeSavedRegs();
237 
238  for (unsigned i = 0; Regs[i]; ++i)
239  if (RISCV::FPR32RegClass.contains(Regs[i]) ||
240  RISCV::FPR64RegClass.contains(Regs[i]))
241  SavedRegs.set(Regs[i]);
242  }
243  }
244 }
245 
247  MachineFunction &MF, RegScavenger *RS) const {
248  const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
249  MachineFrameInfo &MFI = MF.getFrameInfo();
250  const TargetRegisterClass *RC = &RISCV::GPRRegClass;
251  // estimateStackSize has been observed to under-estimate the final stack
252  // size, so give ourselves wiggle-room by checking for stack size
253  // representable an 11-bit signed field rather than 12-bits.
254  // FIXME: It may be possible to craft a function with a small stack that
255  // still needs an emergency spill slot for branch relaxation. This case
256  // would currently be missed.
257  if (!isInt<11>(MFI.estimateStackSize(MF))) {
258  int RegScavFI = MFI.CreateStackObject(
259  RegInfo->getSpillSize(*RC), RegInfo->getSpillAlignment(*RC), false);
260  RS->addScavengingFrameIndex(RegScavFI);
261  }
262 }
263 
264 // Not preserve stack space within prologue for outgoing variables when the
265 // function contains variable size objects and let eliminateCallFramePseudoInstr
266 // preserve stack space for it.
268  return !MF.getFrameInfo().hasVarSizedObjects();
269 }
270 
271 // Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions.
275  unsigned SPReg = RISCV::X2;
276  DebugLoc DL = MI->getDebugLoc();
277 
278  if (!hasReservedCallFrame(MF)) {
279  // If space has not been reserved for a call frame, ADJCALLSTACKDOWN and
280  // ADJCALLSTACKUP must be converted to instructions manipulating the stack
281  // pointer. This is necessary when there is a variable length stack
282  // allocation (e.g. alloca), which means it's not possible to allocate
283  // space for outgoing arguments from within the function prologue.
284  int64_t Amount = MI->getOperand(0).getImm();
285 
286  if (Amount != 0) {
287  // Ensure the stack remains aligned after adjustment.
288  Amount = alignSPAdjust(Amount);
289 
290  if (MI->getOpcode() == RISCV::ADJCALLSTACKDOWN)
291  Amount = -Amount;
292 
293  adjustReg(MBB, MI, DL, SPReg, SPReg, Amount, MachineInstr::NoFlags);
294  }
295  }
296 
297  return MBB.erase(MI);
298 }
BitVector & set()
Definition: BitVector.h:398
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:140
This class represents lattice values for constants.
Definition: AllocatorList.h:24
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:321
A debug info location.
Definition: DebugLoc.h:34
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:685
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:201
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:118
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:309
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
Definition: TargetMachine.h:97
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.