summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/RISCV/RISCVFrameLowering.cpp51
-rw-r--r--llvm/lib/Target/RISCV/RISCVFrameLowering.h5
-rw-r--r--llvm/test/CodeGen/RISCV/alloca.ll46
-rw-r--r--llvm/test/CodeGen/RISCV/calling-conv.ll14
4 files changed, 91 insertions, 25 deletions
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index 33703f5ec20..3dc1e3dbb27 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -43,21 +43,6 @@ void RISCVFrameLowering::determineFrameLayout(MachineFunction &MF) const {
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);
@@ -246,3 +231,39 @@ void RISCVFrameLowering::processFunctionBeforeFrameFinalized(
RS->addScavengingFrameIndex(RegScavFI);
}
}
+
+// Not preserve stack space within prologue for outgoing variables when the
+// function contains variable size objects and let eliminateCallFramePseudoInstr
+// preserve stack space for it.
+bool RISCVFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
+ return !MF.getFrameInfo().hasVarSizedObjects();
+}
+
+// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions.
+MachineBasicBlock::iterator RISCVFrameLowering::eliminateCallFramePseudoInstr(
+ MachineFunction &MF, MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI) const {
+ unsigned SPReg = RISCV::X2;
+ DebugLoc DL = MI->getDebugLoc();
+
+ if (!hasReservedCallFrame(MF)) {
+ // If space has not been reserved for a call frame, ADJCALLSTACKDOWN and
+ // ADJCALLSTACKUP must be converted to instructions manipulating the stack
+ // pointer. This is necessary when there is a variable length stack
+ // allocation (e.g. alloca), which means it's not possible to allocate
+ // space for outgoing arguments from within the function prologue.
+ int64_t Amount = MI->getOperand(0).getImm();
+
+ if (Amount != 0) {
+ // Ensure the stack remains aligned after adjustment.
+ Amount = alignSPAdjust(Amount);
+
+ if (MI->getOpcode() == RISCV::ADJCALLSTACKDOWN)
+ Amount = -Amount;
+
+ adjustReg(MBB, MI, DL, SPReg, SPReg, Amount, MachineInstr::NoFlags);
+ }
+ }
+
+ return MBB.erase(MI);
+}
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.h b/llvm/lib/Target/RISCV/RISCVFrameLowering.h
index ccf7e247b55..ca653c2b9f1 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.h
@@ -41,11 +41,10 @@ public:
bool hasFP(const MachineFunction &MF) const override;
+ bool hasReservedCallFrame(const MachineFunction &MF) const override;
MachineBasicBlock::iterator
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI) const override {
- return MBB.erase(MI);
- }
+ MachineBasicBlock::iterator MI) const override;
protected:
const RISCVSubtarget &STI;
diff --git a/llvm/test/CodeGen/RISCV/alloca.ll b/llvm/test/CodeGen/RISCV/alloca.ll
index 1472e8a302c..68efceaec20 100644
--- a/llvm/test/CodeGen/RISCV/alloca.ll
+++ b/llvm/test/CodeGen/RISCV/alloca.ll
@@ -63,3 +63,49 @@ define void @scoped_alloca(i32 %n) nounwind {
call void @llvm.stackrestore(i8* %sp)
ret void
}
+
+declare void @func(i8*, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32)
+
+; Check that outgoing arguments passed on the stack do not corrupt a
+; variable-sized stack object.
+define void @alloca_callframe(i32 %n) nounwind {
+; RV32I-LABEL: alloca_callframe:
+; 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: addi a0, a0, 15
+; RV32I-NEXT: andi a0, a0, -16
+; RV32I-NEXT: sub a0, sp, a0
+; RV32I-NEXT: mv sp, a0
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: addi a1, zero, 12
+; RV32I-NEXT: sw a1, 12(sp)
+; RV32I-NEXT: addi a1, zero, 11
+; RV32I-NEXT: sw a1, 8(sp)
+; RV32I-NEXT: addi a1, zero, 10
+; RV32I-NEXT: sw a1, 4(sp)
+; RV32I-NEXT: addi a1, zero, 9
+; RV32I-NEXT: sw a1, 0(sp)
+; RV32I-NEXT: lui a1, %hi(func)
+; RV32I-NEXT: addi t0, a1, %lo(func)
+; RV32I-NEXT: addi a1, zero, 2
+; RV32I-NEXT: addi a2, zero, 3
+; RV32I-NEXT: addi a3, zero, 4
+; RV32I-NEXT: addi a4, zero, 5
+; RV32I-NEXT: addi a5, zero, 6
+; RV32I-NEXT: addi a6, zero, 7
+; RV32I-NEXT: addi a7, zero, 8
+; RV32I-NEXT: jalr t0
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: addi sp, s0, -16
+; RV32I-NEXT: lw s0, 8(sp)
+; RV32I-NEXT: lw ra, 12(sp)
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+ %1 = alloca i8, i32 %n
+ call void @func(i8* %1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8,
+ i32 9, i32 10, i32 11, i32 12)
+ ret void
+}
diff --git a/llvm/test/CodeGen/RISCV/calling-conv.ll b/llvm/test/CodeGen/RISCV/calling-conv.ll
index 1d6f4c50731..8d752cbb6e7 100644
--- a/llvm/test/CodeGen/RISCV/calling-conv.ll
+++ b/llvm/test/CodeGen/RISCV/calling-conv.ll
@@ -504,10 +504,10 @@ define i32 @caller_many_scalars() nounwind {
;
; RV32I-WITHFP-LABEL: caller_many_scalars:
; RV32I-WITHFP: # %bb.0:
-; RV32I-WITHFP-NEXT: addi sp, sp, -32
-; RV32I-WITHFP-NEXT: sw ra, 28(sp)
-; RV32I-WITHFP-NEXT: sw s0, 24(sp)
-; RV32I-WITHFP-NEXT: addi s0, sp, 32
+; RV32I-WITHFP-NEXT: addi sp, sp, -16
+; RV32I-WITHFP-NEXT: sw ra, 12(sp)
+; RV32I-WITHFP-NEXT: sw s0, 8(sp)
+; RV32I-WITHFP-NEXT: addi s0, sp, 16
; RV32I-WITHFP-NEXT: addi a0, zero, 8
; RV32I-WITHFP-NEXT: sw a0, 4(sp)
; RV32I-WITHFP-NEXT: sw zero, 0(sp)
@@ -522,9 +522,9 @@ define i32 @caller_many_scalars() nounwind {
; RV32I-WITHFP-NEXT: addi a7, zero, 7
; RV32I-WITHFP-NEXT: mv a4, zero
; RV32I-WITHFP-NEXT: jalr t0
-; RV32I-WITHFP-NEXT: lw s0, 24(sp)
-; RV32I-WITHFP-NEXT: lw ra, 28(sp)
-; RV32I-WITHFP-NEXT: addi sp, sp, 32
+; RV32I-WITHFP-NEXT: lw s0, 8(sp)
+; RV32I-WITHFP-NEXT: lw ra, 12(sp)
+; RV32I-WITHFP-NEXT: addi sp, sp, 16
; RV32I-WITHFP-NEXT: ret
%1 = call i32 @callee_many_scalars(i8 1, i16 2, i32 3, i64 4, i32 5, i32 6, i64 7, i32 8)
ret i32 %1
OpenPOWER on IntegriCloud