diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -21,6 +21,8 @@ #include "llvm/IR/DiagnosticInfo.h" #include "llvm/MC/MCDwarf.h" +#include + using namespace llvm; // For now we use x18, a.k.a s2, as pointer to shadow call stack. @@ -941,14 +943,33 @@ return std::make_pair(StackSize, RVVStackAlign); } -static bool hasRVVSpillWithFIs(MachineFunction &MF) { +static unsigned getScavSlotsNumForRVV(MachineFunction &MF) { + unsigned GlobalMostScavSlotsNum = 0; if (!MF.getSubtarget().hasVInstructions()) return false; for (const MachineBasicBlock &MBB : MF) - for (const MachineInstr &MI : MBB) - if (RISCV::isRVVSpill(MI, /*CheckFIs*/ true)) - return true; - return false; + for (const MachineInstr &MI : MBB) { + unsigned LocalMostScavSlotsNum = 0; + for (auto &MO : MI.operands()) { + if (!MO.isFI()) + continue; + bool isScalableVectorID = MF.getFrameInfo().getStackID(MO.getIndex()) == + TargetStackID::ScalableVector; + if (RISCV::isRVVSpill(MI)) { + // For RVV, scalable stack offsets require up to two scratch + // registers to compute the final offset. Non-scalable stack offsets + // require up to one scratch register. + LocalMostScavSlotsNum = isScalableVectorID ? 2 : 1; + } else if (MI.getOpcode() == RISCV::ADDI) { + // ADDI instruction's destination register can be used for computing + // offsets. Scalable stack offsets require up to one scratch register. + // Non-scalable stack offsets don't need scratch register. + LocalMostScavSlotsNum = isScalableVectorID ? 1 : 0; + } + } + GlobalMostScavSlotsNum = std::max(GlobalMostScavSlotsNum, LocalMostScavSlotsNum); + } + return GlobalMostScavSlotsNum; } void RISCVFrameLowering::processFunctionBeforeFrameFinalized( @@ -980,17 +1001,14 @@ // RVV loads & stores have no capacity to hold the immediate address offsets // so we must always reserve an emergency spill slot if the MachineFunction // contains any RVV spills. - if (!isInt<11>(MFI.estimateStackSize(MF)) || hasRVVSpillWithFIs(MF)) { - int RegScavFI = MFI.CreateStackObject(RegInfo->getSpillSize(*RC), - RegInfo->getSpillAlign(*RC), false); - RS->addScavengingFrameIndex(RegScavFI); - // For RVV, scalable stack offsets require up to two scratch registers to - // compute the final offset. Reserve an additional emergency spill slot. - if (RVVStackSize != 0) { - int RVVRegScavFI = MFI.CreateStackObject( - RegInfo->getSpillSize(*RC), RegInfo->getSpillAlign(*RC), false); - RS->addScavengingFrameIndex(RVVRegScavFI); - } + unsigned ScavSlotsNum = 0; + if (!isInt<11>(MFI.estimateStackSize(MF))) + ScavSlotsNum = 1; + + ScavSlotsNum = std::max(ScavSlotsNum, getScavSlotsNumForRVV(MF)); + for (unsigned i = 0; i < ScavSlotsNum; i++) { + RS->addScavengingFrameIndex(MFI.CreateStackObject( + RegInfo->getSpillSize(*RC), RegInfo->getSpillAlign(*RC), false)); } if (MFI.getCalleeSavedInfo().empty() || RVFI->useSaveRestoreLibCalls(MF)) { diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.h b/llvm/lib/Target/RISCV/RISCVInstrInfo.h --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.h +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.h @@ -184,9 +184,8 @@ namespace RISCV { // Returns true if the given MI is an RVV instruction opcode for which we may -// expect to see a FrameIndex operand. When CheckFIs is true, the instruction -// must contain at least one FrameIndex operand. -bool isRVVSpill(const MachineInstr &MI, bool CheckFIs); +// expect to see a FrameIndex operand. +bool isRVVSpill(const MachineInstr &MI); Optional> isRVVSpillForZvlsseg(unsigned Opcode); diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -1884,16 +1884,14 @@ } } -bool RISCV::isRVVSpill(const MachineInstr &MI, bool CheckFIs) { +bool RISCV::isRVVSpill(const MachineInstr &MI) { // RVV lacks any support for immediate addressing for stack addresses, so be // conservative. unsigned Opcode = MI.getOpcode(); if (!RISCVVPseudosTable::getPseudoInfo(Opcode) && !isRVVWholeLoadStore(Opcode) && !isRVVSpillForZvlsseg(Opcode)) return false; - return !CheckFIs || any_of(MI.operands(), [](const MachineOperand &MO) { - return MO.isFI(); - }); + return true; } Optional> diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -174,7 +174,7 @@ Register FrameReg; StackOffset Offset = getFrameLowering(MF)->getFrameIndexReference(MF, FrameIndex, FrameReg); - bool IsRVVSpill = RISCV::isRVVSpill(MI, /*CheckFIs*/ false); + bool IsRVVSpill = RISCV::isRVVSpill(MI); if (!IsRVVSpill) Offset += StackOffset::getFixed(MI.getOperand(FIOperandNum + 1).getImm()); diff --git a/llvm/test/CodeGen/RISCV/rvv/rvv-stack-align.mir b/llvm/test/CodeGen/RISCV/rvv/rvv-stack-align.mir --- a/llvm/test/CodeGen/RISCV/rvv/rvv-stack-align.mir +++ b/llvm/test/CodeGen/RISCV/rvv/rvv-stack-align.mir @@ -122,22 +122,22 @@ ; ; RV64-LABEL: rvv_stack_align32: ; RV64: # %bb.0: - ; RV64-NEXT: addi sp, sp, -48 - ; RV64-NEXT: sd ra, 40(sp) # 8-byte Folded Spill - ; RV64-NEXT: sd s0, 32(sp) # 8-byte Folded Spill - ; RV64-NEXT: addi s0, sp, 48 + ; RV64-NEXT: addi sp, sp, -80 + ; RV64-NEXT: sd ra, 72(sp) # 8-byte Folded Spill + ; RV64-NEXT: sd s0, 64(sp) # 8-byte Folded Spill + ; RV64-NEXT: addi s0, sp, 80 ; RV64-NEXT: csrr a0, vlenb ; RV64-NEXT: slli a0, a0, 2 ; RV64-NEXT: sub sp, sp, a0 ; RV64-NEXT: andi sp, sp, -32 - ; RV64-NEXT: addi a0, sp, 32 - ; RV64-NEXT: addi a1, sp, 8 - ; RV64-NEXT: mv a2, sp + ; RV64-NEXT: addi a0, sp, 64 + ; RV64-NEXT: addi a1, sp, 40 + ; RV64-NEXT: addi a2, sp, 32 ; RV64-NEXT: call extern@plt - ; RV64-NEXT: addi sp, s0, -48 - ; RV64-NEXT: ld ra, 40(sp) # 8-byte Folded Reload - ; RV64-NEXT: ld s0, 32(sp) # 8-byte Folded Reload - ; RV64-NEXT: addi sp, sp, 48 + ; RV64-NEXT: addi sp, s0, -80 + ; RV64-NEXT: ld ra, 72(sp) # 8-byte Folded Reload + ; RV64-NEXT: ld s0, 64(sp) # 8-byte Folded Reload + ; RV64-NEXT: addi sp, sp, 80 ; RV64-NEXT: ret %a = alloca , align 32 %b = alloca i64 diff --git a/llvm/test/CodeGen/RISCV/rvv/scalar-stack-align.ll b/llvm/test/CodeGen/RISCV/rvv/scalar-stack-align.ll --- a/llvm/test/CodeGen/RISCV/rvv/scalar-stack-align.ll +++ b/llvm/test/CodeGen/RISCV/rvv/scalar-stack-align.ll @@ -13,36 +13,36 @@ define i64* @scalar_stack_align16() nounwind { ; RV32-LABEL: scalar_stack_align16: ; RV32: # %bb.0: -; RV32-NEXT: addi sp, sp, -32 -; RV32-NEXT: sw ra, 28(sp) # 4-byte Folded Spill +; RV32-NEXT: addi sp, sp, -48 +; RV32-NEXT: sw ra, 44(sp) # 4-byte Folded Spill ; RV32-NEXT: csrr a0, vlenb ; RV32-NEXT: slli a0, a0, 1 ; RV32-NEXT: sub sp, sp, a0 -; RV32-NEXT: addi a0, sp, 16 +; RV32-NEXT: addi a0, sp, 32 ; RV32-NEXT: call extern@plt -; RV32-NEXT: mv a0, sp +; RV32-NEXT: addi a0, sp, 16 ; RV32-NEXT: csrr a1, vlenb ; RV32-NEXT: slli a1, a1, 1 ; RV32-NEXT: add sp, sp, a1 -; RV32-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32-NEXT: addi sp, sp, 32 +; RV32-NEXT: lw ra, 44(sp) # 4-byte Folded Reload +; RV32-NEXT: addi sp, sp, 48 ; RV32-NEXT: ret ; ; RV64-LABEL: scalar_stack_align16: ; RV64: # %bb.0: -; RV64-NEXT: addi sp, sp, -32 -; RV64-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-NEXT: addi sp, sp, -48 +; RV64-NEXT: sd ra, 40(sp) # 8-byte Folded Spill ; RV64-NEXT: csrr a0, vlenb ; RV64-NEXT: slli a0, a0, 1 ; RV64-NEXT: sub sp, sp, a0 -; RV64-NEXT: addi a0, sp, 16 +; RV64-NEXT: addi a0, sp, 32 ; RV64-NEXT: call extern@plt -; RV64-NEXT: mv a0, sp +; RV64-NEXT: addi a0, sp, 16 ; RV64-NEXT: csrr a1, vlenb ; RV64-NEXT: slli a1, a1, 1 ; RV64-NEXT: add sp, sp, a1 -; RV64-NEXT: ld ra, 24(sp) # 8-byte Folded Reload -; RV64-NEXT: addi sp, sp, 32 +; RV64-NEXT: ld ra, 40(sp) # 8-byte Folded Reload +; RV64-NEXT: addi sp, sp, 48 ; RV64-NEXT: ret %a = alloca %c = alloca i64, align 16