@@ -280,7 +280,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
280
280
MVT::i1, Promote);
281
281
282
282
// TODO: add all necessary setOperationAction calls.
283
- setOperationAction(ISD::DYNAMIC_STACKALLOC, XLenVT, Expand );
283
+ setOperationAction(ISD::DYNAMIC_STACKALLOC, XLenVT, Custom );
284
284
285
285
setOperationAction(ISD::BR_JT, MVT::Other, Expand);
286
286
setOperationAction(ISD::BR_CC, XLenVT, Expand);
@@ -7727,6 +7727,8 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
7727
7727
return emitFlushICache(DAG, Op.getOperand(0), Op.getOperand(1),
7728
7728
Op.getOperand(2), Flags, DL);
7729
7729
}
7730
+ case ISD::DYNAMIC_STACKALLOC:
7731
+ return lowerDYNAMIC_STACKALLOC(Op, DAG);
7730
7732
case ISD::INIT_TRAMPOLINE:
7731
7733
return lowerINIT_TRAMPOLINE(Op, DAG);
7732
7734
case ISD::ADJUST_TRAMPOLINE:
@@ -19705,6 +19707,8 @@ RISCVTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
19705
19707
case RISCV::PseudoFROUND_D_INX:
19706
19708
case RISCV::PseudoFROUND_D_IN32X:
19707
19709
return emitFROUND(MI, BB, Subtarget);
19710
+ case RISCV::PROBED_STACKALLOC_DYN:
19711
+ return emitDynamicProbedAlloc(MI, BB);
19708
19712
case TargetOpcode::STATEPOINT:
19709
19713
// STATEPOINT is a pseudo instruction which has no implicit defs/uses
19710
19714
// while jal call instruction (where statepoint will be lowered at the end)
@@ -20937,6 +20941,7 @@ const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
20937
20941
NODE_NAME_CASE(SF_VC_V_IVW_SE)
20938
20942
NODE_NAME_CASE(SF_VC_V_VVW_SE)
20939
20943
NODE_NAME_CASE(SF_VC_V_FVW_SE)
20944
+ NODE_NAME_CASE(PROBED_ALLOCA)
20940
20945
}
20941
20946
// clang-format on
20942
20947
return nullptr;
@@ -22666,3 +22671,95 @@ unsigned RISCVTargetLowering::getStackProbeSize(const MachineFunction &MF,
22666
22671
StackProbeSize = alignDown(StackProbeSize, StackAlign.value());
22667
22672
return StackProbeSize ? StackProbeSize : StackAlign.value();
22668
22673
}
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