From b51b26e1bb582e1bc43dca795070fd6c17479c60 Mon Sep 17 00:00:00 2001 From: Daniil Avdeev Date: Tue, 1 Oct 2024 17:15:03 +0300 Subject: [PATCH] [RISCV] fix SP recovery in the function epilogue This patch fixes SP register recovery in the function epilogue. --- llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 105 ++++++++++++------- llvm/lib/Target/RISCV/RISCVFrameLowering.h | 4 + 2 files changed, 72 insertions(+), 37 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp index b0c525ea8c2996..31ce92a04934b5 100644 --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -755,6 +755,19 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF, } } +void RISCVFrameLowering::deallocateStack(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + const DebugLoc &DL, uint64_t StackSize, + int64_t CFAOffset) const { + const RISCVRegisterInfo *RI = STI.getRegisterInfo(); + + Register SPReg = getSPReg(STI); + + RI->adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackOffset::getFixed(StackSize), + MachineInstr::FrameDestroy, getStackAlign()); +} + void RISCVFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { const RISCVRegisterInfo *RI = STI.getRegisterInfo(); @@ -786,20 +799,51 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF, --MBBI; } - const auto &CSI = getUnmanagedCSI(MF, MFI.getCalleeSavedInfo()); + const auto &CSI = MFI.getCalleeSavedInfo(); // Skip to before the restores of scalar callee-saved registers // FIXME: assumes exactly one instruction is used to restore each // callee-saved register. - auto LastFrameDestroy = MBBI; - if (!CSI.empty()) - LastFrameDestroy = std::prev(MBBI, CSI.size()); + auto LastFrameDestroy = std::prev(MBBI, getUnmanagedCSI(MF, CSI).size()); - uint64_t RealStackSize = getStackSizeWithRVVPadding(MF); - uint64_t StackSize = RealStackSize - RVFI->getReservedSpillsSize(); - uint64_t FPOffset = RealStackSize - RVFI->getVarArgsSaveSize(); + uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF); + uint64_t RealStackSize = FirstSPAdjustAmount ? FirstSPAdjustAmount + : getStackSizeWithRVVPadding(MF); + uint64_t StackSize = FirstSPAdjustAmount ? FirstSPAdjustAmount + : getStackSizeWithRVVPadding(MF) - + RVFI->getReservedSpillsSize(); + uint64_t FPOffset = FirstSPAdjustAmount ? FirstSPAdjustAmount + : getStackSizeWithRVVPadding(MF) - + RVFI->getVarArgsSaveSize(); uint64_t RVVStackSize = RVFI->getRVVStackSize(); + bool RestoreFP = RI->hasStackRealignment(MF) || MFI.hasVarSizedObjects() || + !hasReservedCallFrame(MF); + + if (RVVStackSize) { + // If restoreFP the stack pointer will be restored using the frame pointer + // value. + if (!RestoreFP) { + adjustStackForRVV(MF, MBB, LastFrameDestroy, DL, RVVStackSize, + MachineInstr::FrameDestroy); + } + } + + if (FirstSPAdjustAmount) { + uint64_t SecondSPAdjustAmount = + getStackSizeWithRVVPadding(MF) - FirstSPAdjustAmount; + assert(SecondSPAdjustAmount > 0 && + "SecondSPAdjustAmount should be greater than zero"); + + // If restoreFP the stack pointer will be restored using the frame pointer + // value. + if (!RestoreFP) { + RI->adjustReg(MBB, LastFrameDestroy, DL, SPReg, SPReg, + StackOffset::getFixed(SecondSPAdjustAmount), + MachineInstr::FrameDestroy, getStackAlign()); + } + } + // 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. @@ -810,35 +854,17 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF, // 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)) { + if (RestoreFP) { assert(hasFP(MF) && "frame pointer should not have been eliminated"); - RI->adjustReg(MBB, LastFrameDestroy, DL, SPReg, FPReg, - StackOffset::getFixed(-FPOffset), - MachineInstr::FrameDestroy, getStackAlign()); - } else { - if (RVVStackSize) - adjustStackForRVV(MF, MBB, LastFrameDestroy, DL, RVVStackSize, - MachineInstr::FrameDestroy); - } - - uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF); - if (FirstSPAdjustAmount) { - uint64_t SecondSPAdjustAmount = - getStackSizeWithRVVPadding(MF) - FirstSPAdjustAmount; - assert(SecondSPAdjustAmount > 0 && - "SecondSPAdjustAmount should be greater than zero"); - RI->adjustReg(MBB, LastFrameDestroy, DL, SPReg, SPReg, - StackOffset::getFixed(SecondSPAdjustAmount), - MachineInstr::FrameDestroy, getStackAlign()); + RI->adjustReg(MBB, LastFrameDestroy, DL, SPReg, FPReg, + StackOffset::getFixed(-FPOffset), MachineInstr::FrameDestroy, + getStackAlign()); } - if (FirstSPAdjustAmount) - StackSize = FirstSPAdjustAmount; - - if (RVFI->isPushable(MF) && MBBI != MBB.end() && - MBBI->getOpcode() == RISCV::CM_POP) { + bool ApplyPop = RVFI->isPushable(MF) && MBBI != MBB.end() && + MBBI->getOpcode() == RISCV::CM_POP; + if (ApplyPop) { // Use available stack adjustment in pop instruction to deallocate stack // space. Align the stack size down to a multiple of 16. This is needed for // RVE. @@ -846,14 +872,19 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF, uint64_t Spimm = std::min(alignDown(StackSize, 16), (uint64_t)48); MBBI->getOperand(1).setImm(Spimm); StackSize -= Spimm; - } - // Deallocate stack - if (StackSize != 0) { - RI->adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackOffset::getFixed(StackSize), - MachineInstr::FrameDestroy, getStackAlign()); + if (StackSize != 0) + deallocateStack(MF, MBB, MBBI, DL, StackSize, + /*stack_adj of cm.pop instr*/ RealStackSize - StackSize); + + ++MBBI; } + // Deallocate stack if StackSize isn't a zero and if we didn't already do it + // during cm.pop handling. + if (StackSize != 0 && !ApplyPop) + deallocateStack(MF, MBB, MBBI, DL, StackSize, 0); + // Emit epilogue for shadow call stack. emitSCSEpilogue(MF, MBB, MBBI, DL); } diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.h b/llvm/lib/Target/RISCV/RISCVFrameLowering.h index 28ab4aff3b9d51..d660f3ad67c968 100644 --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.h +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.h @@ -91,6 +91,10 @@ class RISCVFrameLowering : public TargetFrameLowering { void emitCalleeSavedRVVPrologCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, bool HasFP) const; + void deallocateStack(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, const DebugLoc &DL, + uint64_t StackSize, int64_t CFAOffset) const; + std::pair assignRVVStackObjectOffsets(MachineFunction &MF) const; };