-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[RISCV] Add stack clash vector support #119458
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -499,6 +499,54 @@ getPushOrLibCallsSavedInfo(const MachineFunction &MF, | |
| return PushOrLibCallsCSI; | ||
| } | ||
|
|
||
| void RISCVFrameLowering::allocateAndProbeStackForRVV( | ||
| MachineFunction &MF, MachineBasicBlock &MBB, | ||
| MachineBasicBlock::iterator MBBI, const DebugLoc &DL, int64_t Amount, | ||
| MachineInstr::MIFlag Flag, bool EmitCFI) const { | ||
| assert(Amount != 0 && "Did not need to adjust stack pointer for RVV."); | ||
|
|
||
| // Emit a variable-length allocation probing loop. | ||
|
|
||
| // Get VLEN in TargetReg | ||
| const RISCVInstrInfo *TII = STI.getInstrInfo(); | ||
| Register TargetReg = RISCV::X6; | ||
| uint32_t NumOfVReg = Amount / (RISCV::RVVBitsPerBlock / 8); | ||
| BuildMI(MBB, MBBI, DL, TII->get(RISCV::PseudoReadVLENB), TargetReg) | ||
| .setMIFlag(Flag); | ||
| TII->mulImm(MF, MBB, MBBI, DL, TargetReg, NumOfVReg, Flag); | ||
|
|
||
| if (EmitCFI) { | ||
| // Set the CFA register to TargetReg. | ||
| unsigned Reg = STI.getRegisterInfo()->getDwarfRegNum(TargetReg, true); | ||
| unsigned CFIIndex = | ||
| MF.addFrameInst(MCCFIInstruction::cfiDefCfa(nullptr, Reg, -Amount)); | ||
| BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) | ||
| .addCFIIndex(CFIIndex) | ||
| .setMIFlags(MachineInstr::FrameSetup); | ||
| } | ||
|
|
||
| // It will be expanded to a probe loop in `inlineStackProbe`. | ||
| BuildMI(MBB, MBBI, DL, TII->get(RISCV::PROBED_STACKALLOC_RVV)) | ||
| .addReg(SPReg) | ||
| .addReg(TargetReg); | ||
|
|
||
| if (EmitCFI) { | ||
| // Set the CFA register back to SP. | ||
| unsigned Reg = STI.getRegisterInfo()->getDwarfRegNum(SPReg, true); | ||
| unsigned CFIIndex = | ||
| MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(nullptr, Reg)); | ||
| BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) | ||
| .addCFIIndex(CFIIndex) | ||
| .setMIFlags(MachineInstr::FrameSetup); | ||
| } | ||
|
|
||
| // SUB SP, SP, T1 | ||
| BuildMI(MBB, MBBI, DL, TII->get(RISCV::SUB), SPReg) | ||
| .addReg(SPReg) | ||
| .addReg(TargetReg) | ||
| .setMIFlag(Flag); | ||
| } | ||
|
|
||
| static void appendScalableVectorExpression(const TargetRegisterInfo &TRI, | ||
| SmallVectorImpl<char> &Expr, | ||
| int FixedOffset, int ScalableOffset, | ||
|
|
@@ -857,10 +905,10 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF, | |
| .setMIFlag(MachineInstr::FrameSetup); | ||
| } | ||
|
|
||
| uint64_t SecondSPAdjustAmount = 0; | ||
| // Emit the second SP adjustment after saving callee saved registers. | ||
| if (FirstSPAdjustAmount) { | ||
| uint64_t SecondSPAdjustAmount = | ||
| getStackSizeWithRVVPadding(MF) - FirstSPAdjustAmount; | ||
| SecondSPAdjustAmount = getStackSizeWithRVVPadding(MF) - FirstSPAdjustAmount; | ||
| assert(SecondSPAdjustAmount > 0 && | ||
| "SecondSPAdjustAmount should be greater than zero"); | ||
|
|
||
|
|
@@ -870,11 +918,15 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF, | |
| } | ||
|
|
||
| if (RVVStackSize) { | ||
| // We must keep the stack pointer aligned through any intermediate | ||
| // updates. | ||
| RI->adjustReg(MBB, MBBI, DL, SPReg, SPReg, | ||
| StackOffset::getScalable(-RVVStackSize), | ||
| MachineInstr::FrameSetup, getStackAlign()); | ||
| if (NeedProbe) | ||
| allocateAndProbeStackForRVV(MF, MBB, MBBI, DL, RVVStackSize, | ||
| MachineInstr::FrameSetup, !hasFP(MF)); | ||
| else | ||
| // We must keep the stack pointer aligned through any intermediate | ||
| // updates. | ||
| RI->adjustReg(MBB, MBBI, DL, SPReg, SPReg, | ||
| StackOffset::getScalable(-RVVStackSize), | ||
| MachineInstr::FrameSetup, getStackAlign()); | ||
|
|
||
| if (!hasFP(MF)) { | ||
| // Emit .cfi_def_cfa_expression "sp + StackSize + RVVStackSize * vlenb". | ||
|
|
@@ -914,6 +966,19 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF, | |
| .addImm(ShiftAmount) | ||
| .setMIFlag(MachineInstr::FrameSetup); | ||
| } | ||
| if (NeedProbe && RVVStackSize == 0) { | ||
| // Do a probe if the align + size allocated just passed the probe size | ||
topperc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // and was not yet probed. | ||
| if (SecondSPAdjustAmount < ProbeSize && | ||
| SecondSPAdjustAmount + MaxAlignment.value() >= ProbeSize) { | ||
| bool IsRV64 = STI.is64Bit(); | ||
| BuildMI(MBB, MBBI, DL, TII->get(IsRV64 ? RISCV::SD : RISCV::SW)) | ||
| .addReg(RISCV::X0) | ||
| .addReg(SPReg) | ||
| .addImm(0) | ||
| .setMIFlags(MachineInstr::FrameSetup); | ||
| } | ||
| } | ||
| // FP will be used to restore the frame in the epilogue, so we need | ||
| // another base register BP to record SP after re-alignment. SP will | ||
| // track the current stack after allocating variable sized objects. | ||
|
|
@@ -2016,9 +2081,11 @@ TargetStackID::Value RISCVFrameLowering::getStackIDForScalableVectors() const { | |
| } | ||
|
|
||
| // Synthesize the probe loop. | ||
| static void emitStackProbeInline(MachineFunction &MF, MachineBasicBlock &MBB, | ||
| MachineBasicBlock::iterator MBBI, | ||
| DebugLoc DL) { | ||
| MachineBasicBlock *RISCVFrameLowering::emitStackProbeInline( | ||
|
||
| MachineFunction &MF, MachineBasicBlock &MBB, | ||
| MachineBasicBlock::iterator MBBI, DebugLoc DL, Register TargetReg, | ||
| bool IsRVV) const { | ||
| assert(TargetReg != RISCV::X2 && "New top of stack cannot already be in SP"); | ||
|
|
||
| auto &Subtarget = MF.getSubtarget<RISCVSubtarget>(); | ||
| const RISCVInstrInfo *TII = Subtarget.getInstrInfo(); | ||
|
|
@@ -2034,7 +2101,6 @@ static void emitStackProbeInline(MachineFunction &MF, MachineBasicBlock &MBB, | |
| MachineBasicBlock *ExitMBB = MF.CreateMachineBasicBlock(MBB.getBasicBlock()); | ||
| MF.insert(MBBInsertPoint, ExitMBB); | ||
| MachineInstr::MIFlag Flags = MachineInstr::FrameSetup; | ||
| Register TargetReg = RISCV::X6; | ||
| Register ScratchReg = RISCV::X7; | ||
|
|
||
| // ScratchReg = ProbeSize | ||
|
|
@@ -2055,12 +2121,29 @@ static void emitStackProbeInline(MachineFunction &MF, MachineBasicBlock &MBB, | |
| .addImm(0) | ||
| .setMIFlags(Flags); | ||
|
|
||
| // BNE SP, TargetReg, LoopTest | ||
| BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(RISCV::BNE)) | ||
| .addReg(SPReg) | ||
| .addReg(TargetReg) | ||
| .addMBB(LoopTestMBB) | ||
| .setMIFlags(Flags); | ||
| if (IsRVV) { | ||
| // SUB TargetReg, TargetReg, ProbeSize | ||
| BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(RISCV::SUB), | ||
| TargetReg) | ||
| .addReg(TargetReg) | ||
| .addReg(ScratchReg) | ||
| .setMIFlags(Flags); | ||
|
|
||
| // BGE TargetReg, ProbeSize, LoopTest | ||
| BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(RISCV::BGE)) | ||
| .addReg(TargetReg) | ||
| .addReg(ScratchReg) | ||
| .addMBB(LoopTestMBB) | ||
| .setMIFlags(Flags); | ||
|
|
||
| } else { | ||
| // BNE SP, TargetReg, LoopTest | ||
| BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(RISCV::BNE)) | ||
| .addReg(SPReg) | ||
| .addReg(TargetReg) | ||
| .addMBB(LoopTestMBB) | ||
| .setMIFlags(Flags); | ||
| } | ||
|
|
||
| ExitMBB->splice(ExitMBB->end(), &MBB, std::next(MBBI), MBB.end()); | ||
|
|
||
|
|
@@ -2069,16 +2152,33 @@ static void emitStackProbeInline(MachineFunction &MF, MachineBasicBlock &MBB, | |
| MBB.addSuccessor(LoopTestMBB); | ||
| // Update liveins. | ||
| fullyRecomputeLiveIns({ExitMBB, LoopTestMBB}); | ||
|
|
||
| return ExitMBB; | ||
| } | ||
|
|
||
| void RISCVFrameLowering::inlineStackProbe(MachineFunction &MF, | ||
| MachineBasicBlock &MBB) const { | ||
| auto Where = llvm::find_if(MBB, [](MachineInstr &MI) { | ||
| return MI.getOpcode() == RISCV::PROBED_STACKALLOC; | ||
| }); | ||
| if (Where != MBB.end()) { | ||
| DebugLoc DL = MBB.findDebugLoc(Where); | ||
| emitStackProbeInline(MF, MBB, Where, DL); | ||
| Where->eraseFromParent(); | ||
| // Get the instructions that need to be replaced. We emit at most two of | ||
| // these. Remember them in order to avoid complications coming from the need | ||
| // to traverse the block while potentially creating more blocks. | ||
| SmallVector<MachineInstr *, 4> ToReplace; | ||
| for (MachineInstr &MI : MBB) { | ||
| int Opc = MI.getOpcode(); | ||
topperc marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| if (Opc == RISCV::PROBED_STACKALLOC || | ||
| Opc == RISCV::PROBED_STACKALLOC_RVV) { | ||
| ToReplace.push_back(&MI); | ||
| } | ||
| } | ||
|
|
||
| for (MachineInstr *MI : ToReplace) { | ||
| if (MI->getOpcode() == RISCV::PROBED_STACKALLOC || | ||
| MI->getOpcode() == RISCV::PROBED_STACKALLOC_RVV) { | ||
| MachineBasicBlock::iterator MBBI = MI->getIterator(); | ||
| DebugLoc DL = MBB.findDebugLoc(MBBI); | ||
| Register TargetReg = MI->getOperand(1).getReg(); | ||
| emitStackProbeInline(MF, MBB, MBBI, DL, TargetReg, | ||
| (MI->getOpcode() == RISCV::PROBED_STACKALLOC_RVV)); | ||
| MBBI->eraseFromParent(); | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add curly braces around this since the comment makes it multiple lines for the reader. See https://llvm.org/docs/CodingStandards.html#don-t-use-braces-on-simple-single-statement-bodies-of-if-else-loop-statements
You'll also need to add curly braces around if body for consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done