[llvm] cf6cf0c - [RISCV] Handle variable sized objects with the stack need to be realigned
via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 15 20:44:27 PST 2019
Author: Shiva Chen
Date: 2019-11-16T12:39:53+08:00
New Revision: cf6cf0cd147ac2524c3533fd7c7ada7f95f6da60
URL: https://github.com/llvm/llvm-project/commit/cf6cf0cd147ac2524c3533fd7c7ada7f95f6da60
DIFF: https://github.com/llvm/llvm-project/commit/cf6cf0cd147ac2524c3533fd7c7ada7f95f6da60.diff
LOG: [RISCV] Handle variable sized objects with the stack need to be realigned
Differential Revision: https://reviews.llvm.org/D68979
Added:
llvm/test/CodeGen/RISCV/stack-realignment-with-variable-sized-objects.ll
Modified:
llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
llvm/lib/Target/RISCV/RISCVFrameLowering.h
llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp
llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h
Removed:
llvm/test/CodeGen/RISCV/stack-realignment-unsupported.ll
################################################################################
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index 4ba4606612b3..61516960b393 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -32,6 +32,13 @@ bool RISCVFrameLowering::hasFP(const MachineFunction &MF) const {
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.
void RISCVFrameLowering::determineFrameLayout(MachineFunction &MF) const {
MachineFrameInfo &MFI = MF.getFrameInfo();
@@ -108,14 +115,9 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
const RISCVInstrInfo *TII = STI.getInstrInfo();
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 SPReg = getSPReg(STI);
+ Register BPReg = RISCVABI::getBPReg();
// Debug location must be unknown since the first debug location is used
// to determine the end of the prologue.
@@ -229,6 +231,15 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
.addReg(VR)
.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,12 +319,14 @@ int RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF,
Offset += FirstSPAdjustAmount;
else
Offset += MF.getFrameInfo().getStackSize();
- } else if (RI->needsStackRealignment(MF)) {
- assert(!MFI.hasVarSizedObjects() &&
- "Unexpected combination of stack realignment and varsized objects");
+ } else if (RI->needsStackRealignment(MF) && !MFI.isFixedObjectIndex(FI)) {
// 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.
- FrameReg = RISCV::X2;
+ // 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;
Offset += MF.getFrameInfo().getStackSize();
} else {
FrameReg = RI->getFrameRegister(MF);
@@ -335,6 +348,9 @@ void RISCVFrameLowering::determineCalleeSaves(MachineFunction &MF,
SavedRegs.set(RISCV::X1);
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,
// unconditionally save all Caller-saved registers and
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.h b/llvm/lib/Target/RISCV/RISCVFrameLowering.h
index f4a5949773d9..3a16cf93cf10 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.h
@@ -40,6 +40,8 @@ class RISCVFrameLowering : public TargetFrameLowering {
bool hasFP(const MachineFunction &MF) const override;
+ bool hasBP(const MachineFunction &MF) const;
+
bool hasReservedCallFrame(const MachineFunction &MF) const override;
MachineBasicBlock::iterator
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
index d4c65a0b22ba..1d41994ef1e3 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
@@ -66,7 +66,7 @@ RISCVRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
}
BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
- const TargetFrameLowering *TFI = getFrameLowering(MF);
+ const RISCVFrameLowering *TFI = getFrameLowering(MF);
BitVector Reserved(getNumRegs());
// 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
if (TFI->hasFP(MF))
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));
return Reserved;
}
diff --git a/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp b/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp
index bc5395768ca1..9c54c3749a19 100644
--- a/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp
+++ b/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp
@@ -66,6 +66,12 @@ ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits,
return ABI_LP64;
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 RISCVFeatures {
diff --git a/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h
index 30e475e80a01..738f635ada97 100644
--- a/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h
@@ -13,6 +13,7 @@
#ifndef LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVBASEINFO_H
#define LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVBASEINFO_H
+#include "RISCVRegisterInfo.h"
#include "MCTargetDesc/RISCVMCTargetDesc.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
@@ -195,6 +196,9 @@ enum ABI {
ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits,
StringRef ABIName);
+// Returns the register used to hold the stack pointer after realignment.
+Register getBPReg();
+
} // namespace RISCVABI
namespace RISCVFeatures {
diff --git a/llvm/test/CodeGen/RISCV/stack-realignment-unsupported.ll b/llvm/test/CodeGen/RISCV/stack-realignment-unsupported.ll
deleted file mode 100644
index f2f11b073cfb..000000000000
--- a/llvm/test/CodeGen/RISCV/stack-realignment-unsupported.ll
+++ /dev/null
@@ -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
-}
diff --git a/llvm/test/CodeGen/RISCV/stack-realignment-with-variable-sized-objects.ll b/llvm/test/CodeGen/RISCV/stack-realignment-with-variable-sized-objects.ll
new file mode 100644
index 000000000000..293eab03b74b
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/stack-realignment-with-variable-sized-objects.ll
@@ -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
+}
More information about the llvm-commits
mailing list