1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-20 03:23:01 +02:00

[RISCV] Handle variable sized objects with the stack need to be realigned

Differential Revision: https://reviews.llvm.org/D68979
This commit is contained in:
Shiva Chen 2019-10-15 15:11:35 +08:00 committed by shiva
parent 636b646163
commit c94d9345a4
7 changed files with 116 additions and 25 deletions

View File

@ -32,6 +32,13 @@ bool RISCVFrameLowering::hasFP(const MachineFunction &MF) const {
MFI.isFrameAddressTaken(); MFI.isFrameAddressTaken();
} }
bool RISCVFrameLowering::hasBP(const MachineFunction &MF) const {
const MachineFrameInfo &MFI = MF.getFrameInfo();
const TargetRegisterInfo *TRI = STI.getRegisterInfo();
return MFI.hasVarSizedObjects() && TRI->needsStackRealignment(MF);
}
// Determines the size of the frame and maximum call frame size. // Determines the size of the frame and maximum call frame size.
void RISCVFrameLowering::determineFrameLayout(MachineFunction &MF) const { void RISCVFrameLowering::determineFrameLayout(MachineFunction &MF) const {
MachineFrameInfo &MFI = MF.getFrameInfo(); MachineFrameInfo &MFI = MF.getFrameInfo();
@ -108,14 +115,9 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
const RISCVInstrInfo *TII = STI.getInstrInfo(); const RISCVInstrInfo *TII = STI.getInstrInfo();
MachineBasicBlock::iterator MBBI = MBB.begin(); MachineBasicBlock::iterator MBBI = MBB.begin();
if (RI->needsStackRealignment(MF) && MFI.hasVarSizedObjects()) {
report_fatal_error(
"RISC-V backend can't currently handle functions that need stack "
"realignment and have variable sized objects");
}
Register FPReg = getFPReg(STI); Register FPReg = getFPReg(STI);
Register SPReg = getSPReg(STI); Register SPReg = getSPReg(STI);
Register BPReg = RISCVABI::getBPReg();
// Debug location must be unknown since the first debug location is used // Debug location must be unknown since the first debug location is used
// to determine the end of the prologue. // to determine the end of the prologue.
@ -229,6 +231,15 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
.addReg(VR) .addReg(VR)
.addImm(ShiftAmount); .addImm(ShiftAmount);
} }
// FP will be used to restore the frame in the epilogue, so we need
// another base register BP to record SP after re-alignment. SP will
// track the current stack after allocating variable sized objects.
if (hasBP(MF)) {
// move BP, SP
BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), BPReg)
.addReg(SPReg)
.addImm(0);
}
} }
} }
} }
@ -308,11 +319,13 @@ int RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF,
Offset += FirstSPAdjustAmount; Offset += FirstSPAdjustAmount;
else else
Offset += MF.getFrameInfo().getStackSize(); Offset += MF.getFrameInfo().getStackSize();
} else if (RI->needsStackRealignment(MF)) { } else if (RI->needsStackRealignment(MF) && !MFI.isFixedObjectIndex(FI)) {
assert(!MFI.hasVarSizedObjects() &&
"Unexpected combination of stack realignment and varsized objects");
// If the stack was realigned, the frame pointer is set in order to allow // If the stack was realigned, the frame pointer is set in order to allow
// SP to be restored, but we still access stack objects using SP. // SP to be restored, so we need another base register to record the stack
// after realignment.
if (hasBP(MF))
FrameReg = RISCVABI::getBPReg();
else
FrameReg = RISCV::X2; FrameReg = RISCV::X2;
Offset += MF.getFrameInfo().getStackSize(); Offset += MF.getFrameInfo().getStackSize();
} else { } else {
@ -335,6 +348,9 @@ void RISCVFrameLowering::determineCalleeSaves(MachineFunction &MF,
SavedRegs.set(RISCV::X1); SavedRegs.set(RISCV::X1);
SavedRegs.set(RISCV::X8); SavedRegs.set(RISCV::X8);
} }
// Mark BP as used if function has dedicated base pointer.
if (hasBP(MF))
SavedRegs.set(RISCVABI::getBPReg());
// If interrupt is enabled and there are calls in the handler, // If interrupt is enabled and there are calls in the handler,
// unconditionally save all Caller-saved registers and // unconditionally save all Caller-saved registers and

View File

@ -40,6 +40,8 @@ public:
bool hasFP(const MachineFunction &MF) const override; bool hasFP(const MachineFunction &MF) const override;
bool hasBP(const MachineFunction &MF) const;
bool hasReservedCallFrame(const MachineFunction &MF) const override; bool hasReservedCallFrame(const MachineFunction &MF) const override;
MachineBasicBlock::iterator MachineBasicBlock::iterator
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,

View File

@ -66,7 +66,7 @@ RISCVRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
} }
BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const { BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
const TargetFrameLowering *TFI = getFrameLowering(MF); const RISCVFrameLowering *TFI = getFrameLowering(MF);
BitVector Reserved(getNumRegs()); BitVector Reserved(getNumRegs());
// Mark any registers requested to be reserved as such // Mark any registers requested to be reserved as such
@ -82,6 +82,10 @@ BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
markSuperRegs(Reserved, RISCV::X4); // tp markSuperRegs(Reserved, RISCV::X4); // tp
if (TFI->hasFP(MF)) if (TFI->hasFP(MF))
markSuperRegs(Reserved, RISCV::X8); // fp markSuperRegs(Reserved, RISCV::X8); // fp
// Reserve the base register if we need to realign the stack and allocate
// variable-sized objects at runtime.
if (TFI->hasBP(MF))
markSuperRegs(Reserved, RISCVABI::getBPReg()); // bp
assert(checkAllSuperRegsMarked(Reserved)); assert(checkAllSuperRegsMarked(Reserved));
return Reserved; return Reserved;
} }

View File

@ -66,6 +66,12 @@ ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits,
return ABI_LP64; return ABI_LP64;
return ABI_ILP32; return ABI_ILP32;
} }
// To avoid the BP value clobbered by a function call, we need to choose a
// callee saved register to save the value. RV32E only has X8 and X9 as callee
// saved registers and X8 will be used as fp. So we choose X9 as bp.
Register getBPReg() { return RISCV::X9; }
} // namespace RISCVABI } // namespace RISCVABI
namespace RISCVFeatures { namespace RISCVFeatures {

View File

@ -13,6 +13,7 @@
#ifndef LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVBASEINFO_H #ifndef LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVBASEINFO_H
#define LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVBASEINFO_H #define LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVBASEINFO_H
#include "RISCVRegisterInfo.h"
#include "MCTargetDesc/RISCVMCTargetDesc.h" #include "MCTargetDesc/RISCVMCTargetDesc.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/StringSwitch.h"
@ -195,6 +196,9 @@ enum ABI {
ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits, ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits,
StringRef ABIName); StringRef ABIName);
// Returns the register used to hold the stack pointer after realignment.
Register getBPReg();
} // namespace RISCVABI } // namespace RISCVABI
namespace RISCVFeatures { namespace RISCVFeatures {

View File

@ -1,13 +0,0 @@
; RUN: not llc -mtriple=riscv32 < %s 2>&1 | FileCheck %s
; RUN: not llc -mtriple=riscv64 < %s 2>&1 | FileCheck %s
; CHECK: LLVM ERROR: RISC-V backend can't currently handle functions that need stack realignment and have variable sized objects
declare void @callee(i8*, i32*)
define void @caller(i32 %n) nounwind {
%1 = alloca i8, i32 %n
%2 = alloca i32, align 64
call void @callee(i8* %1, i32 *%2)
ret void
}

View File

@ -0,0 +1,72 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV32I
; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64I
declare void @callee(i8*, i32*)
define void @caller(i32 %n) {
; RV32I-LABEL: caller:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -128
; RV32I-NEXT: .cfi_def_cfa_offset 128
; RV32I-NEXT: sw ra, 124(sp)
; RV32I-NEXT: sw s0, 120(sp)
; RV32I-NEXT: sw s1, 116(sp)
; RV32I-NEXT: .cfi_offset ra, -4
; RV32I-NEXT: .cfi_offset s0, -8
; RV32I-NEXT: .cfi_offset s1, -12
; RV32I-NEXT: addi s0, sp, 128
; RV32I-NEXT: .cfi_def_cfa s0, 0
; RV32I-NEXT: andi sp, sp, -64
; RV32I-NEXT: mv s1, sp
; RV32I-NEXT: addi a0, a0, 15
; RV32I-NEXT: andi a0, a0, -16
; RV32I-NEXT: sub a0, sp, a0
; RV32I-NEXT: mv sp, a0
; RV32I-NEXT: addi a1, s1, 64
; RV32I-NEXT: call callee
; RV32I-NEXT: addi sp, s0, -128
; RV32I-NEXT: lw s1, 116(sp)
; RV32I-NEXT: lw s0, 120(sp)
; RV32I-NEXT: lw ra, 124(sp)
; RV32I-NEXT: addi sp, sp, 128
; RV32I-NEXT: ret
;
; RV64I-LABEL: caller:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -128
; RV64I-NEXT: .cfi_def_cfa_offset 128
; RV64I-NEXT: sd ra, 120(sp)
; RV64I-NEXT: sd s0, 112(sp)
; RV64I-NEXT: sd s1, 104(sp)
; RV64I-NEXT: .cfi_offset ra, -8
; RV64I-NEXT: .cfi_offset s0, -16
; RV64I-NEXT: .cfi_offset s1, -24
; RV64I-NEXT: addi s0, sp, 128
; RV64I-NEXT: .cfi_def_cfa s0, 0
; RV64I-NEXT: andi sp, sp, -64
; RV64I-NEXT: mv s1, sp
; RV64I-NEXT: slli a0, a0, 32
; RV64I-NEXT: srli a0, a0, 32
; RV64I-NEXT: addi a0, a0, 15
; RV64I-NEXT: addi a1, zero, 1
; RV64I-NEXT: slli a1, a1, 33
; RV64I-NEXT: addi a1, a1, -16
; RV64I-NEXT: and a0, a0, a1
; RV64I-NEXT: sub a0, sp, a0
; RV64I-NEXT: mv sp, a0
; RV64I-NEXT: addi a1, s1, 64
; RV64I-NEXT: call callee
; RV64I-NEXT: addi sp, s0, -128
; RV64I-NEXT: ld s1, 104(sp)
; RV64I-NEXT: ld s0, 112(sp)
; RV64I-NEXT: ld ra, 120(sp)
; RV64I-NEXT: addi sp, sp, 128
; RV64I-NEXT: ret
%1 = alloca i8, i32 %n
%2 = alloca i32, align 64
call void @callee(i8* %1, i32 *%2)
ret void
}