Index: lib/Target/RISCV/RISCVFrameLowering.h =================================================================== --- lib/Target/RISCV/RISCVFrameLowering.h +++ lib/Target/RISCV/RISCVFrameLowering.h @@ -41,11 +41,10 @@ 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; Index: lib/Target/RISCV/RISCVFrameLowering.cpp =================================================================== --- lib/Target/RISCV/RISCVFrameLowering.cpp +++ lib/Target/RISCV/RISCVFrameLowering.cpp @@ -43,21 +43,6 @@ 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,44 @@ RS->addScavengingFrameIndex(RegScavFI); } } + +/// 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. This eliminates the need for +/// add/sub sp brackets around call sites. Returns true if the call frame is +/// included as part of the stack frame. +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 we have alloca, convert as follows: + // ADJCALLSTACKDOWN -> sub, sp, sp, amount + // ADJCALLSTACKUP -> add, sp, sp, amount + // + // To avoid alloca area poison by outgoing arguments. + int64_t Amount = MI->getOperand(0).getImm(); + + if (Amount != 0) { + // We need to keep the stack aligned properly. To do this, we round the + // amount of space needed for the outgoing arguments up to the next + // alignment boundary. + Amount = alignSPAdjust(Amount); + + if (MI->getOpcode() == RISCV::ADJCALLSTACKDOWN) + Amount = -Amount; + + adjustReg(MBB, MI, DL, SPReg, SPReg, Amount, MachineInstr::NoFlags); + } + } + + return MBB.erase(MI); +} Index: test/CodeGen/RISCV/alloca.ll =================================================================== --- test/CodeGen/RISCV/alloca.ll +++ test/CodeGen/RISCV/alloca.ll @@ -63,3 +63,48 @@ 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, -32 +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s0, 24(sp) +; RV32I-NEXT: addi s0, sp, 32 +; 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, -32 +; RV32I-NEXT: lw s0, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: addi sp, sp, 32 +; 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 +} Index: test/CodeGen/RISCV/calling-conv.ll =================================================================== --- test/CodeGen/RISCV/calling-conv.ll +++ test/CodeGen/RISCV/calling-conv.ll @@ -504,10 +504,10 @@ ; ; 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 @@ ; 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