@@ -280,7 +280,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
280280 MVT::i1, Promote);
281281
282282 // TODO: add all necessary setOperationAction calls.
283- setOperationAction(ISD::DYNAMIC_STACKALLOC, XLenVT, Expand );
283+ setOperationAction(ISD::DYNAMIC_STACKALLOC, XLenVT, Custom );
284284
285285 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
286286 setOperationAction(ISD::BR_CC, XLenVT, Expand);
@@ -7727,6 +7727,8 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
77277727 return emitFlushICache(DAG, Op.getOperand(0), Op.getOperand(1),
77287728 Op.getOperand(2), Flags, DL);
77297729 }
7730+ case ISD::DYNAMIC_STACKALLOC:
7731+ return lowerDYNAMIC_STACKALLOC(Op, DAG);
77307732 case ISD::INIT_TRAMPOLINE:
77317733 return lowerINIT_TRAMPOLINE(Op, DAG);
77327734 case ISD::ADJUST_TRAMPOLINE:
@@ -19705,6 +19707,8 @@ RISCVTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
1970519707 case RISCV::PseudoFROUND_D_INX:
1970619708 case RISCV::PseudoFROUND_D_IN32X:
1970719709 return emitFROUND(MI, BB, Subtarget);
19710+ case RISCV::PROBED_STACKALLOC_DYN:
19711+ return emitDynamicProbedAlloc(MI, BB);
1970819712 case TargetOpcode::STATEPOINT:
1970919713 // STATEPOINT is a pseudo instruction which has no implicit defs/uses
1971019714 // while jal call instruction (where statepoint will be lowered at the end)
@@ -20937,6 +20941,7 @@ const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
2093720941 NODE_NAME_CASE(SF_VC_V_IVW_SE)
2093820942 NODE_NAME_CASE(SF_VC_V_VVW_SE)
2093920943 NODE_NAME_CASE(SF_VC_V_FVW_SE)
20944+ NODE_NAME_CASE(PROBED_ALLOCA)
2094020945 }
2094120946 // clang-format on
2094220947 return nullptr;
@@ -22666,3 +22671,95 @@ unsigned RISCVTargetLowering::getStackProbeSize(const MachineFunction &MF,
2266622671 StackProbeSize = alignDown(StackProbeSize, StackAlign.value());
2266722672 return StackProbeSize ? StackProbeSize : StackAlign.value();
2266822673}
22674+
22675+ SDValue RISCVTargetLowering::lowerDYNAMIC_STACKALLOC(SDValue Op,
22676+ SelectionDAG &DAG) const {
22677+ MachineFunction &MF = DAG.getMachineFunction();
22678+ if (!hasInlineStackProbe(MF))
22679+ return SDValue();
22680+
22681+ MVT XLenVT = Subtarget.getXLenVT();
22682+ // Get the inputs.
22683+ SDValue Chain = Op.getOperand(0);
22684+ SDValue Size = Op.getOperand(1);
22685+
22686+ MaybeAlign Align =
22687+ cast<ConstantSDNode>(Op.getOperand(2))->getMaybeAlignValue();
22688+ SDLoc dl(Op);
22689+ EVT VT = Op.getValueType();
22690+
22691+ // Construct the new SP value in a GPR.
22692+ SDValue SP = DAG.getCopyFromReg(Chain, dl, RISCV::X2, XLenVT);
22693+ Chain = SP.getValue(1);
22694+ SP = DAG.getNode(ISD::SUB, dl, XLenVT, SP, Size);
22695+ if (Align)
22696+ SP = DAG.getNode(ISD::AND, dl, VT, SP.getValue(0),
22697+ DAG.getSignedConstant(-(uint64_t)Align->value(), dl, VT));
22698+
22699+ // Set the real SP to the new value with a probing loop.
22700+ Chain = DAG.getNode(RISCVISD::PROBED_ALLOCA, dl, MVT::Other, Chain, SP);
22701+ return DAG.getMergeValues({SP, Chain}, dl);
22702+ }
22703+
22704+ MachineBasicBlock *
22705+ RISCVTargetLowering::emitDynamicProbedAlloc(MachineInstr &MI,
22706+ MachineBasicBlock *MBB) const {
22707+ MachineFunction &MF = *MBB->getParent();
22708+ MachineBasicBlock::iterator MBBI = MI.getIterator();
22709+ DebugLoc DL = MBB->findDebugLoc(MBBI);
22710+ Register TargetReg = MI.getOperand(1).getReg();
22711+
22712+ const RISCVInstrInfo *TII = Subtarget.getInstrInfo();
22713+ bool IsRV64 = Subtarget.is64Bit();
22714+ Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
22715+ const RISCVTargetLowering *TLI = Subtarget.getTargetLowering();
22716+ uint64_t ProbeSize = TLI->getStackProbeSize(MF, StackAlign);
22717+
22718+ MachineFunction::iterator MBBInsertPoint = std::next(MBB->getIterator());
22719+ MachineBasicBlock *LoopTestMBB =
22720+ MF.CreateMachineBasicBlock(MBB->getBasicBlock());
22721+ MF.insert(MBBInsertPoint, LoopTestMBB);
22722+ MachineBasicBlock *ExitMBB = MF.CreateMachineBasicBlock(MBB->getBasicBlock());
22723+ MF.insert(MBBInsertPoint, ExitMBB);
22724+ Register SPReg = RISCV::X2;
22725+ Register ScratchReg =
22726+ MF.getRegInfo().createVirtualRegister(&RISCV::GPRRegClass);
22727+
22728+ // ScratchReg = ProbeSize
22729+ TII->movImm(*MBB, MBBI, DL, ScratchReg, ProbeSize, MachineInstr::NoFlags);
22730+
22731+ // LoopTest:
22732+ // SUB SP, SP, ProbeSize
22733+ BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(RISCV::SUB), SPReg)
22734+ .addReg(SPReg)
22735+ .addReg(ScratchReg);
22736+
22737+ // s[d|w] zero, 0(sp)
22738+ BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL,
22739+ TII->get(IsRV64 ? RISCV::SD : RISCV::SW))
22740+ .addReg(RISCV::X0)
22741+ .addReg(SPReg)
22742+ .addImm(0);
22743+
22744+ // BLT TargetReg, SP, LoopTest
22745+ BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(RISCV::BLT))
22746+ .addReg(TargetReg)
22747+ .addReg(SPReg)
22748+ .addMBB(LoopTestMBB);
22749+
22750+ // Adjust with: MV SP, TargetReg.
22751+ BuildMI(*ExitMBB, ExitMBB->end(), DL, TII->get(RISCV::ADDI), SPReg)
22752+ .addReg(TargetReg)
22753+ .addImm(0);
22754+
22755+ ExitMBB->splice(ExitMBB->end(), MBB, std::next(MBBI), MBB->end());
22756+ ExitMBB->transferSuccessorsAndUpdatePHIs(MBB);
22757+
22758+ LoopTestMBB->addSuccessor(ExitMBB);
22759+ LoopTestMBB->addSuccessor(LoopTestMBB);
22760+ MBB->addSuccessor(LoopTestMBB);
22761+
22762+ MI.eraseFromParent();
22763+ MF.getInfo<RISCVMachineFunctionInfo>()->setDynamicAllocation();
22764+ return ExitMBB->begin()->getParent();
22765+ }
0 commit comments