@@ -3526,8 +3526,7 @@ void SelectionDAGBuilder::visitCallBr(const CallBrInst &I) {
35263526
35273527 // Update successor info.
35283528 addSuccessorWithProb(CallBrMBB, Return, BranchProbability::getOne());
3529- for (unsigned i = 0, e = I.getNumIndirectDests(); i < e; ++i) {
3530- BasicBlock *Dest = I.getIndirectDest(i);
3529+ for (BasicBlock *Dest : I.getIndirectDests()) {
35313530 MachineBasicBlock *Target = FuncInfo.getMBB(Dest);
35323531 Target->setIsInlineAsmBrIndirectTarget();
35333532 // If we introduce a type of asm goto statement that is permitted to use an
@@ -5313,18 +5312,26 @@ void SelectionDAGBuilder::visitAtomicStore(const StoreInst &I) {
53135312 DAG.setRoot(OutChain);
53145313}
53155314
5316- /// visitTargetIntrinsic - Lower a call of a target intrinsic to an INTRINSIC
5317- /// node .
5318- void SelectionDAGBuilder::visitTargetIntrinsic(const CallInst &I,
5319- unsigned Intrinsic) {
5320- // Ignore the callsite's attributes. A specific call site may be marked with
5321- // readnone, but the lowering code will expect the chain based on the
5322- // definition.
5315+ /// Check if this intrinsic call depends on the chain (1st return value)
5316+ /// and if it only *loads* memory .
5317+ /// Ignore the callsite's attributes. A specific call site may be marked with
5318+ /// readnone, but the lowering code will expect the chain based on the
5319+ /// definition.
5320+ std::pair<bool, bool>
5321+ SelectionDAGBuilder::getTargetIntrinsicCallProperties(const CallBase &I) {
53235322 const Function *F = I.getCalledFunction();
53245323 bool HasChain = !F->doesNotAccessMemory();
53255324 bool OnlyLoad =
53265325 HasChain && F->onlyReadsMemory() && F->willReturn() && F->doesNotThrow();
53275326
5327+ return {HasChain, OnlyLoad};
5328+ }
5329+
5330+ SmallVector<SDValue, 8> SelectionDAGBuilder::getTargetIntrinsicOperands(
5331+ const CallBase &I, bool HasChain, bool OnlyLoad,
5332+ TargetLowering::IntrinsicInfo *TgtMemIntrinsicInfo) {
5333+ const TargetLowering &TLI = DAG.getTargetLoweringInfo();
5334+
53285335 // Build the operand list.
53295336 SmallVector<SDValue, 8> Ops;
53305337 if (HasChain) { // If this intrinsic has side-effects, chainify it.
@@ -5336,17 +5343,10 @@ void SelectionDAGBuilder::visitTargetIntrinsic(const CallInst &I,
53365343 }
53375344 }
53385345
5339- // Info is set by getTgtMemIntrinsic
5340- TargetLowering::IntrinsicInfo Info;
5341- const TargetLowering &TLI = DAG.getTargetLoweringInfo();
5342- bool IsTgtIntrinsic = TLI.getTgtMemIntrinsic(Info, I,
5343- DAG.getMachineFunction(),
5344- Intrinsic);
5345-
53465346 // Add the intrinsic ID as an integer operand if it's not a target intrinsic.
5347- if (!IsTgtIntrinsic || Info. opc == ISD::INTRINSIC_VOID ||
5348- Info. opc == ISD::INTRINSIC_W_CHAIN)
5349- Ops.push_back(DAG.getTargetConstant(Intrinsic , getCurSDLoc(),
5347+ if (!TgtMemIntrinsicInfo || TgtMemIntrinsicInfo-> opc == ISD::INTRINSIC_VOID ||
5348+ TgtMemIntrinsicInfo-> opc == ISD::INTRINSIC_W_CHAIN)
5349+ Ops.push_back(DAG.getTargetConstant(I.getIntrinsicID() , getCurSDLoc(),
53505350 TLI.getPointerTy(DAG.getDataLayout())));
53515351
53525352 // Add all operands of the call to the operand list.
@@ -5369,13 +5369,85 @@ void SelectionDAGBuilder::visitTargetIntrinsic(const CallInst &I,
53695369 }
53705370 }
53715371
5372+ if (std::optional<OperandBundleUse> Bundle =
5373+ I.getOperandBundle(LLVMContext::OB_convergencectrl)) {
5374+ Value *Token = Bundle->Inputs[0].get();
5375+ SDValue ConvControlToken = getValue(Token);
5376+ assert(Ops.back().getValueType() != MVT::Glue &&
5377+ "Did not expect another glue node here.");
5378+ ConvControlToken =
5379+ DAG.getNode(ISD::CONVERGENCECTRL_GLUE, {}, MVT::Glue, ConvControlToken);
5380+ Ops.push_back(ConvControlToken);
5381+ }
5382+
5383+ return Ops;
5384+ }
5385+
5386+ SDVTList SelectionDAGBuilder::getTargetIntrinsicVTList(const CallBase &I,
5387+ bool HasChain) {
5388+ const TargetLowering &TLI = DAG.getTargetLoweringInfo();
5389+
53725390 SmallVector<EVT, 4> ValueVTs;
53735391 ComputeValueVTs(TLI, DAG.getDataLayout(), I.getType(), ValueVTs);
53745392
53755393 if (HasChain)
53765394 ValueVTs.push_back(MVT::Other);
53775395
5378- SDVTList VTs = DAG.getVTList(ValueVTs);
5396+ return DAG.getVTList(ValueVTs);
5397+ }
5398+
5399+ /// Get an INTRINSIC node for a target intrinsic which does not touch memory.
5400+ SDValue SelectionDAGBuilder::getTargetNonMemIntrinsicNode(
5401+ const Type &IntrinsicVT, bool HasChain, ArrayRef<SDValue> Ops,
5402+ const SDVTList &VTs) {
5403+ if (!HasChain)
5404+ return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, getCurSDLoc(), VTs, Ops);
5405+ if (!IntrinsicVT.isVoidTy())
5406+ return DAG.getNode(ISD::INTRINSIC_W_CHAIN, getCurSDLoc(), VTs, Ops);
5407+ return DAG.getNode(ISD::INTRINSIC_VOID, getCurSDLoc(), VTs, Ops);
5408+ }
5409+
5410+ /// Set root, convert return type if necessary and check alignment.
5411+ SDValue SelectionDAGBuilder::handleTargetIntrinsicRet(const CallBase &I,
5412+ bool HasChain,
5413+ bool OnlyLoad,
5414+ SDValue Result) {
5415+ if (HasChain) {
5416+ SDValue Chain = Result.getValue(Result.getNode()->getNumValues() - 1);
5417+ if (OnlyLoad)
5418+ PendingLoads.push_back(Chain);
5419+ else
5420+ DAG.setRoot(Chain);
5421+ }
5422+
5423+ if (I.getType()->isVoidTy())
5424+ return Result;
5425+
5426+ if (MaybeAlign Alignment = I.getRetAlign(); InsertAssertAlign && Alignment) {
5427+ // Insert `assertalign` node if there's an alignment.
5428+ Result = DAG.getAssertAlign(getCurSDLoc(), Result, Alignment.valueOrOne());
5429+ } else if (!isa<VectorType>(I.getType())) {
5430+ Result = lowerRangeToAssertZExt(DAG, I, Result);
5431+ }
5432+
5433+ return Result;
5434+ }
5435+
5436+ /// visitTargetIntrinsic - Lower a call of a target intrinsic to an INTRINSIC
5437+ /// node.
5438+ void SelectionDAGBuilder::visitTargetIntrinsic(const CallInst &I,
5439+ unsigned Intrinsic) {
5440+ auto [HasChain, OnlyLoad] = getTargetIntrinsicCallProperties(I);
5441+
5442+ // Info is set by getTgtMemIntrinsic
5443+ TargetLowering::IntrinsicInfo Info;
5444+ const TargetLowering &TLI = DAG.getTargetLoweringInfo();
5445+ bool IsTgtMemIntrinsic =
5446+ TLI.getTgtMemIntrinsic(Info, I, DAG.getMachineFunction(), Intrinsic);
5447+
5448+ SmallVector<SDValue, 8> Ops = getTargetIntrinsicOperands(
5449+ I, HasChain, OnlyLoad, IsTgtMemIntrinsic ? &Info : nullptr);
5450+ SDVTList VTs = getTargetIntrinsicVTList(I, HasChain);
53795451
53805452 // Propagate fast-math-flags from IR to node(s).
53815453 SDNodeFlags Flags;
@@ -5386,19 +5458,9 @@ void SelectionDAGBuilder::visitTargetIntrinsic(const CallInst &I,
53865458 // Create the node.
53875459 SDValue Result;
53885460
5389- if (auto Bundle = I.getOperandBundle(LLVMContext::OB_convergencectrl)) {
5390- auto *Token = Bundle->Inputs[0].get();
5391- SDValue ConvControlToken = getValue(Token);
5392- assert(Ops.back().getValueType() != MVT::Glue &&
5393- "Did not expected another glue node here.");
5394- ConvControlToken =
5395- DAG.getNode(ISD::CONVERGENCECTRL_GLUE, {}, MVT::Glue, ConvControlToken);
5396- Ops.push_back(ConvControlToken);
5397- }
5398-
53995461 // In some cases, custom collection of operands from CallInst I may be needed.
54005462 TLI.CollectTargetIntrinsicOperands(I, Ops, DAG);
5401- if (IsTgtIntrinsic ) {
5463+ if (IsTgtMemIntrinsic ) {
54025464 // This is target intrinsic that touches memory
54035465 //
54045466 // TODO: We currently just fallback to address space 0 if getTgtMemIntrinsic
@@ -5418,34 +5480,11 @@ void SelectionDAGBuilder::visitTargetIntrinsic(const CallInst &I,
54185480 Info.ssid, Info.order, Info.failureOrder);
54195481 Result =
54205482 DAG.getMemIntrinsicNode(Info.opc, getCurSDLoc(), VTs, Ops, MemVT, MMO);
5421- } else if (!HasChain) {
5422- Result = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, getCurSDLoc(), VTs, Ops);
5423- } else if (!I.getType()->isVoidTy()) {
5424- Result = DAG.getNode(ISD::INTRINSIC_W_CHAIN, getCurSDLoc(), VTs, Ops);
54255483 } else {
5426- Result = DAG.getNode(ISD::INTRINSIC_VOID, getCurSDLoc( ), VTs , Ops);
5484+ Result = getTargetNonMemIntrinsicNode(*I.getType( ), HasChain , Ops, VTs );
54275485 }
54285486
5429- if (HasChain) {
5430- SDValue Chain = Result.getValue(Result.getNode()->getNumValues()-1);
5431- if (OnlyLoad)
5432- PendingLoads.push_back(Chain);
5433- else
5434- DAG.setRoot(Chain);
5435- }
5436-
5437- if (!I.getType()->isVoidTy()) {
5438- if (!isa<VectorType>(I.getType()))
5439- Result = lowerRangeToAssertZExt(DAG, I, Result);
5440-
5441- MaybeAlign Alignment = I.getRetAlign();
5442-
5443- // Insert `assertalign` node if there's an alignment.
5444- if (InsertAssertAlign && Alignment) {
5445- Result =
5446- DAG.getAssertAlign(getCurSDLoc(), Result, Alignment.valueOrOne());
5447- }
5448- }
5487+ Result = handleTargetIntrinsicRet(I, HasChain, OnlyLoad, Result);
54495488
54505489 setValue(&I, Result);
54515490}
0 commit comments