diff options
Diffstat (limited to 'llvm/lib/Target/RISCV/RISCVFrameLowering.cpp')
-rw-r--r-- | llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 468 |
1 files changed, 285 insertions, 183 deletions
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp index ad003404d793..57d8ba6f0161 100644 --- 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 <algorithm> + using namespace llvm; // For now we use x18, a.k.a s2, as pointer to shadow call stack. @@ -250,6 +252,7 @@ bool RISCVFrameLowering::hasBP(const MachineFunction &MF) const { // Determines the size of the frame and maximum call frame size. void RISCVFrameLowering::determineFrameLayout(MachineFunction &MF) const { MachineFrameInfo &MFI = MF.getFrameInfo(); + auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>(); // Get the number of bytes to allocate from the FrameInfo. uint64_t FrameSize = MFI.getStackSize(); @@ -262,6 +265,28 @@ void RISCVFrameLowering::determineFrameLayout(MachineFunction &MF) const { // Update frame info. MFI.setStackSize(FrameSize); + + // When using SP or BP to access stack objects, we may require extra padding + // to ensure the bottom of the RVV stack is correctly aligned within the main + // stack. We calculate this as the amount required to align the scalar local + // variable section up to the RVV alignment. + const TargetRegisterInfo *TRI = STI.getRegisterInfo(); + if (RVFI->getRVVStackSize() && (!hasFP(MF) || TRI->hasStackRealignment(MF))) { + int ScalarLocalVarSize = FrameSize - RVFI->getCalleeSavedStackSize() - + RVFI->getVarArgsSaveSize(); + if (auto RVVPadding = + offsetToAlignment(ScalarLocalVarSize, RVFI->getRVVStackAlign())) + RVFI->setRVVPadding(RVVPadding); + } +} + +// Returns the stack size including RVV padding (when required), rounded back +// up to the required stack alignment. +uint64_t RISCVFrameLowering::getStackSizeWithRVVPadding( + const MachineFunction &MF) const { + const MachineFrameInfo &MFI = MF.getFrameInfo(); + auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>(); + return alignTo(MFI.getStackSize() + RVFI->getRVVPadding(), getStackAlign()); } void RISCVFrameLowering::adjustReg(MachineBasicBlock &MBB, @@ -280,21 +305,43 @@ void RISCVFrameLowering::adjustReg(MachineBasicBlock &MBB, .addReg(SrcReg) .addImm(Val) .setMIFlag(Flag); - } else { - unsigned Opc = RISCV::ADD; - bool isSub = Val < 0; - if (isSub) { - Val = -Val; - Opc = RISCV::SUB; - } + return; + } - Register ScratchReg = MRI.createVirtualRegister(&RISCV::GPRRegClass); - TII->movImm(MBB, MBBI, DL, ScratchReg, Val, Flag); - BuildMI(MBB, MBBI, DL, TII->get(Opc), DestReg) + // Try to split the offset across two ADDIs. We need to keep the stack pointer + // aligned after each ADDI. We need to determine the maximum value we can put + // in each ADDI. In the negative direction, we can use -2048 which is always + // sufficiently aligned. In the positive direction, we need to find the + // largest 12-bit immediate that is aligned. Exclude -4096 since it can be + // created with LUI. + assert(getStackAlign().value() < 2048 && "Stack alignment too large"); + int64_t MaxPosAdjStep = 2048 - getStackAlign().value(); + if (Val > -4096 && Val <= (2 * MaxPosAdjStep)) { + int64_t FirstAdj = Val < 0 ? -2048 : MaxPosAdjStep; + Val -= FirstAdj; + BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), DestReg) .addReg(SrcReg) - .addReg(ScratchReg, RegState::Kill) + .addImm(FirstAdj) + .setMIFlag(Flag); + BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), DestReg) + .addReg(DestReg, RegState::Kill) + .addImm(Val) .setMIFlag(Flag); + return; + } + + unsigned Opc = RISCV::ADD; + if (Val < 0) { + Val = -Val; + Opc = RISCV::SUB; } + + Register ScratchReg = MRI.createVirtualRegister(&RISCV::GPRRegClass); + TII->movImm(MBB, MBBI, DL, ScratchReg, Val, Flag); + BuildMI(MBB, MBBI, DL, TII->get(Opc), DestReg) + .addReg(SrcReg) + .addReg(ScratchReg, RegState::Kill) + .setMIFlag(Flag); } // Returns the register used to hold the frame pointer. @@ -401,7 +448,7 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF, // FIXME (note copied from Lanai): This appears to be overallocating. Needs // investigation. Get the number of bytes to allocate from the FrameInfo. - uint64_t StackSize = MFI.getStackSize() + RVFI->getRVVPadding(); + uint64_t StackSize = getStackSizeWithRVVPadding(MF); uint64_t RealStackSize = StackSize + RVFI->getLibCallStackSize(); uint64_t RVVStackSize = RVFI->getRVVStackSize(); @@ -482,7 +529,8 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF, // Emit the second SP adjustment after saving callee saved registers. if (FirstSPAdjustAmount) { - uint64_t SecondSPAdjustAmount = MFI.getStackSize() - FirstSPAdjustAmount; + uint64_t SecondSPAdjustAmount = + getStackSizeWithRVVPadding(MF) - FirstSPAdjustAmount; assert(SecondSPAdjustAmount > 0 && "SecondSPAdjustAmount should be greater than zero"); adjustReg(MBB, MBBI, DL, SPReg, SPReg, -SecondSPAdjustAmount, @@ -492,8 +540,8 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF, // don't emit an sp-based .cfi_def_cfa_offset if (!hasFP(MF)) { // Emit ".cfi_def_cfa_offset StackSize" - unsigned CFIIndex = MF.addFrameInst( - MCCFIInstruction::cfiDefCfaOffset(nullptr, MFI.getStackSize())); + unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset( + nullptr, getStackSizeWithRVVPadding(MF))); BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex) .setMIFlag(MachineInstr::FrameSetup); @@ -561,15 +609,11 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock::iterator MBBI = MBB.end(); DebugLoc DL; if (!MBB.empty()) { - MBBI = MBB.getFirstTerminator(); - if (MBBI == MBB.end()) - MBBI = MBB.getLastNonDebugInstr(); - DL = MBBI->getDebugLoc(); + MBBI = MBB.getLastNonDebugInstr(); + if (MBBI != MBB.end()) + DL = MBBI->getDebugLoc(); - // If this is not a terminator, the actual insert location should be after the - // last instruction. - if (!MBBI->isTerminator()) - MBBI = std::next(MBBI); + MBBI = MBB.getFirstTerminator(); // If callee-saved registers are saved via libcall, place stack adjustment // before this call. @@ -587,7 +631,7 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF, if (!CSI.empty()) LastFrameDestroy = std::prev(MBBI, CSI.size()); - uint64_t StackSize = MFI.getStackSize() + RVFI->getRVVPadding(); + uint64_t StackSize = getStackSizeWithRVVPadding(MF); uint64_t RealStackSize = StackSize + RVFI->getLibCallStackSize(); uint64_t FPOffset = RealStackSize - RVFI->getVarArgsSaveSize(); uint64_t RVVStackSize = RVFI->getRVVStackSize(); @@ -595,7 +639,15 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF, // Restore the stack pointer using the value of the frame pointer. Only // necessary if the stack pointer was modified, meaning the stack size is // unknown. - if (RI->hasStackRealignment(MF) || MFI.hasVarSizedObjects()) { + // + // In order to make sure the stack point is right through the EH region, + // we also need to restore stack pointer from the frame pointer if we + // don't preserve stack space within prologue/epilogue for outgoing variables, + // normally it's just checking the variable sized object is present or not + // is enough, but we also don't preserve that at prologue/epilogue when + // have vector objects in stack. + if (RI->hasStackRealignment(MF) || MFI.hasVarSizedObjects() || + !hasReservedCallFrame(MF)) { assert(hasFP(MF) && "frame pointer should not have been eliminated"); adjustReg(MBB, LastFrameDestroy, DL, SPReg, FPReg, -FPOffset, MachineInstr::FrameDestroy); @@ -607,7 +659,8 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF, uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF); if (FirstSPAdjustAmount) { - uint64_t SecondSPAdjustAmount = MFI.getStackSize() - FirstSPAdjustAmount; + uint64_t SecondSPAdjustAmount = + getStackSizeWithRVVPadding(MF) - FirstSPAdjustAmount; assert(SecondSPAdjustAmount > 0 && "SecondSPAdjustAmount should be greater than zero"); @@ -665,134 +718,138 @@ RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, if (FirstSPAdjustAmount) Offset += StackOffset::getFixed(FirstSPAdjustAmount); else - Offset += - StackOffset::getFixed(MFI.getStackSize() + RVFI->getRVVPadding()); - } else if (RI->hasStackRealignment(MF) && !MFI.isFixedObjectIndex(FI)) { + Offset += StackOffset::getFixed(getStackSizeWithRVVPadding(MF)); + return Offset; + } + + if (RI->hasStackRealignment(MF) && !MFI.isFixedObjectIndex(FI)) { // If the stack was realigned, the frame pointer is set in order to allow // SP to be restored, so we need another base register to record the stack // after realignment. + // |--------------------------| -- <-- FP + // | callee-allocated save | | <----| + // | area for register varargs| | | + // |--------------------------| | | + // | callee-saved registers | | | + // |--------------------------| -- | + // | realignment (the size of | | | + // | this area is not counted | | | + // | in MFI.getStackSize()) | | | + // |--------------------------| -- |-- MFI.getStackSize() + // | RVV alignment padding | | | + // | (not counted in | | | + // | MFI.getStackSize() but | | | + // | counted in | | | + // | RVFI.getRVVStackSize()) | | | + // |--------------------------| -- | + // | RVV objects | | | + // | (not counted in | | | + // | MFI.getStackSize()) | | | + // |--------------------------| -- | + // | padding before RVV | | | + // | (not counted in | | | + // | MFI.getStackSize() or in | | | + // | RVFI.getRVVStackSize()) | | | + // |--------------------------| -- | + // | scalar local variables | | <----' + // |--------------------------| -- <-- BP (if var sized objects present) + // | VarSize objects | | + // |--------------------------| -- <-- SP if (hasBP(MF)) { FrameReg = RISCVABI::getBPReg(); - // |--------------------------| -- <-- FP - // | callee-saved registers | | <----. - // |--------------------------| -- | - // | realignment (the size of | | | - // | this area is not counted | | | - // | in MFI.getStackSize()) | | | - // |--------------------------| -- | - // | Padding after RVV | | | - // | (not counted in | | | - // | MFI.getStackSize()) | | | - // |--------------------------| -- |-- MFI.getStackSize() - // | RVV objects | | | - // | (not counted in | | | - // | MFI.getStackSize()) | | | - // |--------------------------| -- | - // | Padding before RVV | | | - // | (not counted in | | | - // | MFI.getStackSize()) | | | - // |--------------------------| -- | - // | scalar local variables | | <----' - // |--------------------------| -- <-- BP - // | VarSize objects | | - // |--------------------------| -- <-- SP } else { + // VarSize objects must be empty in this case! + assert(!MFI.hasVarSizedObjects()); FrameReg = RISCV::X2; - // |--------------------------| -- <-- FP - // | callee-saved registers | | <----. - // |--------------------------| -- | - // | realignment (the size of | | | - // | this area is not counted | | | - // | in MFI.getStackSize()) | | | - // |--------------------------| -- | - // | Padding after RVV | | | - // | (not counted in | | | - // | MFI.getStackSize()) | | | - // |--------------------------| -- |-- MFI.getStackSize() - // | RVV objects | | | - // | (not counted in | | | - // | MFI.getStackSize()) | | | - // |--------------------------| -- | - // | Padding before RVV | | | - // | (not counted in | | | - // | MFI.getStackSize()) | | | - // |--------------------------| -- | - // | scalar local variables | | <----' - // |--------------------------| -- <-- SP - } - // The total amount of padding surrounding RVV objects is described by - // RVV->getRVVPadding() and it can be zero. It allows us to align the RVV - // objects to 8 bytes. - if (MFI.getStackID(FI) == TargetStackID::Default) { - Offset += StackOffset::getFixed(MFI.getStackSize()); - if (FI < 0) - Offset += StackOffset::getFixed(RVFI->getLibCallStackSize()); - } else if (MFI.getStackID(FI) == TargetStackID::ScalableVector) { - Offset += StackOffset::get( - alignTo(MFI.getStackSize() - RVFI->getCalleeSavedStackSize(), 8), - RVFI->getRVVStackSize()); } } else { FrameReg = RI->getFrameRegister(MF); - if (hasFP(MF)) { - Offset += StackOffset::getFixed(RVFI->getVarArgsSaveSize()); - if (FI >= 0) - Offset -= StackOffset::getFixed(RVFI->getLibCallStackSize()); - // When using FP to access scalable vector objects, we need to minus - // the frame size. - // - // |--------------------------| -- <-- FP - // | callee-saved registers | | - // |--------------------------| | MFI.getStackSize() - // | scalar local variables | | - // |--------------------------| -- (Offset of RVV objects is from here.) - // | RVV objects | - // |--------------------------| - // | VarSize objects | - // |--------------------------| <-- SP - if (MFI.getStackID(FI) == TargetStackID::ScalableVector) - Offset -= StackOffset::getFixed(MFI.getStackSize()); - } else { - // When using SP to access frame objects, we need to add RVV stack size. - // - // |--------------------------| -- <-- FP - // | callee-saved registers | | <----. - // |--------------------------| -- | - // | Padding after RVV | | | - // | (not counted in | | | - // | MFI.getStackSize()) | | | - // |--------------------------| -- | - // | RVV objects | | |-- MFI.getStackSize() - // | (not counted in | | | - // | MFI.getStackSize()) | | | - // |--------------------------| -- | - // | Padding before RVV | | | - // | (not counted in | | | - // | MFI.getStackSize()) | | | - // |--------------------------| -- | - // | scalar local variables | | <----' - // |--------------------------| -- <-- SP - // - // The total amount of padding surrounding RVV objects is described by - // RVV->getRVVPadding() and it can be zero. It allows us to align the RVV - // objects to 8 bytes. - if (MFI.getStackID(FI) == TargetStackID::Default) { - if (MFI.isFixedObjectIndex(FI)) { - Offset += - StackOffset::get(MFI.getStackSize() + RVFI->getRVVPadding() + - RVFI->getLibCallStackSize(), - RVFI->getRVVStackSize()); - } else { - Offset += StackOffset::getFixed(MFI.getStackSize()); - } - } else if (MFI.getStackID(FI) == TargetStackID::ScalableVector) { - Offset += StackOffset::get( - alignTo(MFI.getStackSize() - RVFI->getCalleeSavedStackSize(), 8), - RVFI->getRVVStackSize()); - } + } + + if (FrameReg == getFPReg(STI)) { + Offset += StackOffset::getFixed(RVFI->getVarArgsSaveSize()); + if (FI >= 0) + Offset -= StackOffset::getFixed(RVFI->getLibCallStackSize()); + // When using FP to access scalable vector objects, we need to minus + // the frame size. + // + // |--------------------------| -- <-- FP + // | callee-allocated save | | + // | area for register varargs| | + // |--------------------------| | + // | callee-saved registers | | + // |--------------------------| | MFI.getStackSize() + // | scalar local variables | | + // |--------------------------| -- (Offset of RVV objects is from here.) + // | RVV objects | + // |--------------------------| + // | VarSize objects | + // |--------------------------| <-- SP + if (MFI.getStackID(FI) == TargetStackID::ScalableVector) { + assert(!RI->hasStackRealignment(MF) && + "Can't index across variable sized realign"); + // We don't expect any extra RVV alignment padding, as the stack size + // and RVV object sections should be correct aligned in their own + // right. + assert(MFI.getStackSize() == getStackSizeWithRVVPadding(MF) && + "Inconsistent stack layout"); + Offset -= StackOffset::getFixed(MFI.getStackSize()); } + return Offset; } + // This case handles indexing off both SP and BP. + // If indexing off SP, there must not be any var sized objects + assert(FrameReg == RISCVABI::getBPReg() || !MFI.hasVarSizedObjects()); + + // When using SP to access frame objects, we need to add RVV stack size. + // + // |--------------------------| -- <-- FP + // | callee-allocated save | | <----| + // | area for register varargs| | | + // |--------------------------| | | + // | callee-saved registers | | | + // |--------------------------| -- | + // | RVV alignment padding | | | + // | (not counted in | | | + // | MFI.getStackSize() but | | | + // | counted in | | | + // | RVFI.getRVVStackSize()) | | | + // |--------------------------| -- | + // | RVV objects | | |-- MFI.getStackSize() + // | (not counted in | | | + // | MFI.getStackSize()) | | | + // |--------------------------| -- | + // | padding before RVV | | | + // | (not counted in | | | + // | MFI.getStackSize()) | | | + // |--------------------------| -- | + // | scalar local variables | | <----' + // |--------------------------| -- <-- BP (if var sized objects present) + // | VarSize objects | | + // |--------------------------| -- <-- SP + // + // The total amount of padding surrounding RVV objects is described by + // RVV->getRVVPadding() and it can be zero. It allows us to align the RVV + // objects to the required alignment. + if (MFI.getStackID(FI) == TargetStackID::Default) { + if (MFI.isFixedObjectIndex(FI)) { + assert(!RI->hasStackRealignment(MF) && + "Can't index across variable sized realign"); + Offset += StackOffset::get(getStackSizeWithRVVPadding(MF) + + RVFI->getLibCallStackSize(), + RVFI->getRVVStackSize()); + } else { + Offset += StackOffset::getFixed(MFI.getStackSize()); + } + } else if (MFI.getStackID(FI) == TargetStackID::ScalableVector) { + // Ensure the base of the RVV stack is correctly aligned: add on the + // alignment padding. + int ScalarLocalVarSize = + MFI.getStackSize() - RVFI->getCalleeSavedStackSize() - + RVFI->getVarArgsSaveSize() + RVFI->getRVVPadding(); + Offset += StackOffset::get(ScalarLocalVarSize, RVFI->getRVVStackSize()); + } return Offset; } @@ -841,9 +898,8 @@ void RISCVFrameLowering::determineCalleeSaves(MachineFunction &MF, } } -int64_t +std::pair<int64_t, Align> RISCVFrameLowering::assignRVVStackObjectOffsets(MachineFrameInfo &MFI) const { - int64_t Offset = 0; // Create a buffer of RVV objects to allocate. SmallVector<int, 8> ObjectsToAllocate; for (int I = 0, E = MFI.getObjectIndexEnd(); I != E; ++I) { @@ -857,29 +913,78 @@ RISCVFrameLowering::assignRVVStackObjectOffsets(MachineFrameInfo &MFI) const { } // Allocate all RVV locals and spills + int64_t Offset = 0; + // The minimum alignment is 16 bytes. + Align RVVStackAlign(16); for (int FI : ObjectsToAllocate) { // ObjectSize in bytes. int64_t ObjectSize = MFI.getObjectSize(FI); + auto ObjectAlign = std::max(Align(8), MFI.getObjectAlign(FI)); // If the data type is the fractional vector type, reserve one vector // register for it. if (ObjectSize < 8) ObjectSize = 8; - // Currently, all scalable vector types are aligned to 8 bytes. - Offset = alignTo(Offset + ObjectSize, 8); + Offset = alignTo(Offset + ObjectSize, ObjectAlign); MFI.setObjectOffset(FI, -Offset); + // Update the maximum alignment of the RVV stack section + RVVStackAlign = std::max(RVVStackAlign, ObjectAlign); } - return Offset; + // Ensure the alignment of the RVV stack. Since we want the most-aligned + // object right at the bottom (i.e., any padding at the top of the frame), + // readjust all RVV objects down by the alignment padding. + uint64_t StackSize = Offset; + if (auto AlignmentPadding = offsetToAlignment(StackSize, RVVStackAlign)) { + StackSize += AlignmentPadding; + for (int FI : ObjectsToAllocate) + MFI.setObjectOffset(FI, MFI.getObjectOffset(FI) - AlignmentPadding); + } + + return std::make_pair(StackSize, RVVStackAlign); } -static bool hasRVVSpillWithFIs(MachineFunction &MF, const RISCVInstrInfo &TII) { +static unsigned getScavSlotsNumForRVV(MachineFunction &MF) { + // For RVV spill, scalable stack offsets computing requires up to two scratch + // registers + static constexpr unsigned ScavSlotsNumRVVSpillScalableObject = 2; + + // For RVV spill, non-scalable stack offsets computing requires up to one + // scratch register. + static constexpr unsigned ScavSlotsNumRVVSpillNonScalableObject = 1; + + // ADDI instruction's destination register can be used for computing + // offsets. So Scalable stack offsets require up to one scratch register. + static constexpr unsigned ScavSlotsADDIScalableObject = 1; + + static constexpr unsigned MaxScavSlotsNumKnown = + std::max({ScavSlotsADDIScalableObject, ScavSlotsNumRVVSpillScalableObject, + ScavSlotsNumRVVSpillNonScalableObject}); + + unsigned MaxScavSlotsNum = 0; if (!MF.getSubtarget<RISCVSubtarget>().hasVInstructions()) return false; - return any_of(MF, [&TII](const MachineBasicBlock &MBB) { - return any_of(MBB, [&TII](const MachineInstr &MI) { - return TII.isRVVSpill(MI, /*CheckFIs*/ true); - }); - }); + for (const MachineBasicBlock &MBB : MF) + for (const MachineInstr &MI : MBB) { + bool IsRVVSpill = RISCV::isRVVSpill(MI); + for (auto &MO : MI.operands()) { + if (!MO.isFI()) + continue; + bool IsScalableVectorID = MF.getFrameInfo().getStackID(MO.getIndex()) == + TargetStackID::ScalableVector; + if (IsRVVSpill) { + MaxScavSlotsNum = std::max( + MaxScavSlotsNum, IsScalableVectorID + ? ScavSlotsNumRVVSpillScalableObject + : ScavSlotsNumRVVSpillNonScalableObject); + } else if (MI.getOpcode() == RISCV::ADDI && IsScalableVectorID) { + MaxScavSlotsNum = + std::max(MaxScavSlotsNum, ScavSlotsADDIScalableObject); + } + } + if (MaxScavSlotsNum == MaxScavSlotsNumKnown) + return MaxScavSlotsNumKnown; + } + return MaxScavSlotsNum; } void RISCVFrameLowering::processFunctionBeforeFrameFinalized( @@ -890,9 +995,17 @@ void RISCVFrameLowering::processFunctionBeforeFrameFinalized( const TargetRegisterClass *RC = &RISCV::GPRRegClass; auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>(); - int64_t RVVStackSize = assignRVVStackObjectOffsets(MFI); + int64_t RVVStackSize; + Align RVVStackAlign; + std::tie(RVVStackSize, RVVStackAlign) = assignRVVStackObjectOffsets(MFI); + RVFI->setRVVStackSize(RVVStackSize); - const RISCVInstrInfo &TII = *MF.getSubtarget<RISCVSubtarget>().getInstrInfo(); + RVFI->setRVVStackAlign(RVVStackAlign); + + // Ensure the entire stack is aligned to at least the RVV requirement: some + // scalable-vector object alignments are not considered by the + // target-independent code. + MFI.ensureMaxAlignment(RVVStackAlign); // estimateStackSize has been observed to under-estimate the final stack // size, so give ourselves wiggle-room by checking for stack size @@ -903,17 +1016,14 @@ void RISCVFrameLowering::processFunctionBeforeFrameFinalized( // 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, TII)) { - 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)) { @@ -930,14 +1040,6 @@ void RISCVFrameLowering::processFunctionBeforeFrameFinalized( Size += MFI.getObjectSize(FrameIdx); } RVFI->setCalleeSavedStackSize(Size); - - // Padding required to keep the RVV stack aligned to 8 bytes - // within the main stack. We only need this when not using FP. - if (RVVStackSize && !hasFP(MF) && Size % 8 != 0) { - // Because we add the padding to the size of the stack, adding - // getStackAlign() will keep it aligned. - RVFI->setRVVPadding(getStackAlign().value()); - } } static bool hasRVVFrameObject(const MachineFunction &MF) { @@ -1012,23 +1114,23 @@ RISCVFrameLowering::getFirstSPAdjustAmount(const MachineFunction &MF) const { const auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>(); const MachineFrameInfo &MFI = MF.getFrameInfo(); const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); - uint64_t StackSize = MFI.getStackSize(); + uint64_t StackSize = getStackSizeWithRVVPadding(MF); - // Disable SplitSPAdjust if save-restore libcall used. The callee saved + // Disable SplitSPAdjust if save-restore libcall is used. The callee-saved // registers will be pushed by the save-restore libcalls, so we don't have to // split the SP adjustment in this case. if (RVFI->getLibCallStackSize()) return 0; - // Return the FirstSPAdjustAmount if the StackSize can not fit in signed - // 12-bit and there exists a callee saved register need to be pushed. + // Return the FirstSPAdjustAmount if the StackSize can not fit in a signed + // 12-bit and there exists a callee-saved register needing to be pushed. if (!isInt<12>(StackSize) && (CSI.size() > 0)) { - // FirstSPAdjustAmount is choosed as (2048 - StackAlign) - // because 2048 will cause sp = sp + 2048 in epilogue split into - // multi-instructions. The offset smaller than 2048 can fit in signle - // load/store instruction and we have to stick with the stack alignment. - // 2048 is 16-byte alignment. The stack alignment for RV32 and RV64 is 16, - // for RV32E is 4. So (2048 - StackAlign) will satisfy the stack alignment. + // FirstSPAdjustAmount is chosen as (2048 - StackAlign) because 2048 will + // cause sp = sp + 2048 in the epilogue to be split into multiple + // instructions. Offsets smaller than 2048 can fit in a single load/store + // instruction, and we have to stick with the stack alignment. 2048 has + // 16-byte alignment. The stack alignment for RV32 and RV64 is 16 and for + // RV32E it is 4. So (2048 - StackAlign) will satisfy the stack alignment. return 2048 - getStackAlign().value(); } return 0; |