Skip to content

Commit

Permalink
[RISCV] Implement prolog and epilog insertion
Browse files Browse the repository at this point in the history
As frame pointer elimination isn't implemented until a later patch and we make 
extensive use of update_llc_test_checks.py, this changes touches a lot of the 
RISC-V tests.

Differential Revision: https://reviews.llvm.org/D39849

llvm-svn: 320357
  • Loading branch information
asb committed Dec 11, 2017
1 parent 220b1c1 commit b014e3d
Show file tree
Hide file tree
Showing 23 changed files with 1,040 additions and 49 deletions.
147 changes: 145 additions & 2 deletions llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,144 @@ using namespace llvm;

bool RISCVFrameLowering::hasFP(const MachineFunction &MF) const { return true; }

// Determines the size of the frame and maximum call frame size.
void RISCVFrameLowering::determineFrameLayout(MachineFunction &MF) const {
MachineFrameInfo &MFI = MF.getFrameInfo();
const RISCVRegisterInfo *RI = STI.getRegisterInfo();

// Get the number of bytes to allocate from the FrameInfo.
uint64_t FrameSize = MFI.getStackSize();

// Get the alignment.
uint64_t StackAlign = RI->needsStackRealignment(MF) ? MFI.getMaxAlignment()
: getStackAlignment();

// Get the maximum call frame size of all the calls.
uint64_t MaxCallFrameSize = MFI.getMaxCallFrameSize();

// If we have dynamic alloca then MaxCallFrameSize needs to be aligned so
// that allocations will be aligned.
if (MFI.hasVarSizedObjects())
MaxCallFrameSize = alignTo(MaxCallFrameSize, StackAlign);

// Update maximum call frame size.
MFI.setMaxCallFrameSize(MaxCallFrameSize);

// Include call frame size in total.
if (!(hasReservedCallFrame(MF) && MFI.adjustsStack()))
FrameSize += MaxCallFrameSize;

// Make sure the frame is aligned.
FrameSize = alignTo(FrameSize, StackAlign);

// Update frame info.
MFI.setStackSize(FrameSize);
}

void RISCVFrameLowering::adjustReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, unsigned DestReg,
unsigned SrcReg, int64_t Val,
MachineInstr::MIFlag Flag) const {
const RISCVInstrInfo *TII = STI.getInstrInfo();

if (DestReg == SrcReg && Val == 0)
return;

if (!isInt<12>(Val))
report_fatal_error("adjustReg cannot yet handle adjustments >12 bits");

BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), DestReg)
.addReg(SrcReg)
.addImm(Val)
.setMIFlag(Flag);
}

// Returns the register used to hold the frame pointer.
static unsigned getFPReg(const RISCVSubtarget &STI) { return RISCV::X8; }

// Returns the register used to hold the stack pointer.
static unsigned getSPReg(const RISCVSubtarget &STI) { return RISCV::X2; }

void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
MachineBasicBlock &MBB) const {}
MachineBasicBlock &MBB) const {
assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");

if (!hasFP(MF)) {
report_fatal_error(
"emitPrologue doesn't support framepointer-less functions");
}

MachineFrameInfo &MFI = MF.getFrameInfo();
MachineBasicBlock::iterator MBBI = MBB.begin();

unsigned FPReg = getFPReg(STI);
unsigned SPReg = getSPReg(STI);

// Debug location must be unknown since the first debug location is used
// to determine the end of the prologue.
DebugLoc DL;

// Determine the correct frame layout
determineFrameLayout(MF);

// FIXME (note copied from Lanai): This appears to be overallocating. Needs
// investigation. Get the number of bytes to allocate from the FrameInfo.
uint64_t StackSize = MFI.getStackSize();

// Early exit if there is no need to allocate on the stack
if (StackSize == 0 && !MFI.adjustsStack())
return;

// Allocate space on the stack if necessary.
adjustReg(MBB, MBBI, DL, SPReg, SPReg, -StackSize, MachineInstr::FrameSetup);

// The frame pointer is callee-saved, and code has been generated for us to
// save it to the stack. We need to skip over the storing of callee-saved
// registers as the frame pointer must be modified after it has been saved
// to the stack, not before.
// FIXME: assumes exactly one instruction is used to save each callee-saved
// register.
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
std::advance(MBBI, CSI.size());

// Generate new FP.
adjustReg(MBB, MBBI, DL, FPReg, SPReg, StackSize, MachineInstr::FrameSetup);
}

void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {}
MachineBasicBlock &MBB) const {
if (!hasFP(MF)) {
report_fatal_error(
"emitEpilogue doesn't support framepointer-less functions");
}

MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
const RISCVRegisterInfo *RI = STI.getRegisterInfo();
MachineFrameInfo &MFI = MF.getFrameInfo();
DebugLoc DL = MBBI->getDebugLoc();
unsigned FPReg = getFPReg(STI);
unsigned SPReg = getSPReg(STI);

// Skip to before the restores of callee-saved registers
// FIXME: assumes exactly one instruction is used to restore each
// callee-saved register.
MachineBasicBlock::iterator LastFrameDestroy = MBBI;
std::advance(LastFrameDestroy, -MFI.getCalleeSavedInfo().size());

uint64_t StackSize = MFI.getStackSize();

// Restore the stack pointer using the value of the frame pointer. Only
// necessary if the stack pointer was modified, meaning the stack size is
// unknown.
if (RI->needsStackRealignment(MF) || MFI.hasVarSizedObjects()) {
adjustReg(MBB, LastFrameDestroy, DL, SPReg, FPReg, -StackSize,
MachineInstr::FrameDestroy);
}

// Deallocate stack
adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackSize, MachineInstr::FrameDestroy);
}

int RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF,
int FI,
Expand Down Expand Up @@ -56,3 +189,13 @@ int RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF,
}
return Offset;
}

void RISCVFrameLowering::determineCalleeSaves(MachineFunction &MF,
BitVector &SavedRegs,
RegScavenger *RS) const {
TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
// TODO: Once frame pointer elimination is implemented, don't
// unconditionally spill the frame pointer and return address.
SavedRegs.set(RISCV::X1);
SavedRegs.set(RISCV::X8);
}
15 changes: 14 additions & 1 deletion llvm/lib/Target/RISCV/RISCVFrameLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,34 @@ class RISCVFrameLowering : public TargetFrameLowering {
explicit RISCVFrameLowering(const RISCVSubtarget &STI)
: TargetFrameLowering(StackGrowsDown,
/*StackAlignment=*/16,
/*LocalAreaOffset=*/0) {}
/*LocalAreaOffset=*/0),
STI(STI) {}

void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;

int getFrameIndexReference(const MachineFunction &MF, int FI,
unsigned &FrameReg) const override;

void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
RegScavenger *RS) const override;

bool hasFP(const MachineFunction &MF) const override;

MachineBasicBlock::iterator
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI) const override {
return MBB.erase(MI);
}

protected:
const RISCVSubtarget &STI;

private:
void determineFrameLayout(MachineFunction &MF) const;
void adjustReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,
int64_t Val, MachineInstr::MIFlag Flag) const;
};
}
#endif
14 changes: 14 additions & 0 deletions llvm/test/CodeGen/RISCV/addc-adde-sube-subc.ll
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,18 @@
define i64 @addc_adde(i64 %a, i64 %b) {
; RV32I-LABEL: addc_adde:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp)
; RV32I-NEXT: sw s0, 8(sp)
; RV32I-NEXT: addi s0, sp, 16
; RV32I-NEXT: add a1, a1, a3
; RV32I-NEXT: add a2, a0, a2
; RV32I-NEXT: sltu a0, a2, a0
; RV32I-NEXT: add a1, a1, a0
; RV32I-NEXT: addi a0, a2, 0
; RV32I-NEXT: lw s0, 8(sp)
; RV32I-NEXT: lw ra, 12(sp)
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: jalr zero, ra, 0
%1 = add i64 %a, %b
ret i64 %1
Expand All @@ -20,10 +27,17 @@ define i64 @addc_adde(i64 %a, i64 %b) {
define i64 @subc_sube(i64 %a, i64 %b) {
; RV32I-LABEL: subc_sube:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp)
; RV32I-NEXT: sw s0, 8(sp)
; RV32I-NEXT: addi s0, sp, 16
; RV32I-NEXT: sub a1, a1, a3
; RV32I-NEXT: sltu a3, a0, a2
; RV32I-NEXT: sub a1, a1, a3
; RV32I-NEXT: sub a0, a0, a2
; RV32I-NEXT: lw s0, 8(sp)
; RV32I-NEXT: lw ra, 12(sp)
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: jalr zero, ra, 0
%1 = sub i64 %a, %b
ret i64 %1
Expand Down
Loading

0 comments on commit b014e3d

Please sign in to comment.