97 const auto *OutArg1 = dyn_cast<HLSLOutArgExpr>(E->
getArg(1));
98 const auto *OutArg2 = dyn_cast<HLSLOutArgExpr>(E->
getArg(2));
101 LValue Op1TmpLValue =
103 LValue Op2TmpLValue =
109 Value *LowBits =
nullptr;
110 Value *HighBits =
nullptr;
113 llvm::Type *RetElementTy = CGF->
Int32Ty;
115 RetElementTy = llvm::VectorType::get(
116 CGF->
Int32Ty, ElementCount::getFixed(Op0VecTy->getNumElements()));
117 auto *RetTy = llvm::StructType::get(RetElementTy, RetElementTy);
119 CallInst *CI = CGF->
Builder.CreateIntrinsic(
120 RetTy, Intrinsic::dx_splitdouble, {Op0},
nullptr,
"hlsl.splitdouble");
122 LowBits = CGF->
Builder.CreateExtractValue(CI, 0);
123 HighBits = CGF->
Builder.CreateExtractValue(CI, 1);
127 if (!Op0->
getType()->isVectorTy()) {
128 FixedVectorType *DestTy = FixedVectorType::get(CGF->
Int32Ty, 2);
129 Value *Bitcast = CGF->
Builder.CreateBitCast(Op0, DestTy);
131 LowBits = CGF->
Builder.CreateExtractElement(Bitcast, (uint64_t)0);
132 HighBits = CGF->
Builder.CreateExtractElement(Bitcast, 1);
135 if (
const auto *VecTy =
137 NumElements = VecTy->getNumElements();
139 FixedVectorType *Uint32VecTy =
140 FixedVectorType::get(CGF->
Int32Ty, NumElements * 2);
141 Value *Uint32Vec = CGF->
Builder.CreateBitCast(Op0, Uint32VecTy);
142 if (NumElements == 1) {
143 LowBits = CGF->
Builder.CreateExtractElement(Uint32Vec, (uint64_t)0);
144 HighBits = CGF->
Builder.CreateExtractElement(Uint32Vec, 1);
147 for (
int I = 0, E = NumElements; I != E; ++I) {
148 EvenMask.push_back(I * 2);
149 OddMask.push_back(I * 2 + 1);
151 LowBits = CGF->
Builder.CreateShuffleVector(Uint32Vec, EvenMask);
152 HighBits = CGF->
Builder.CreateShuffleVector(Uint32Vec, OddMask);
263 case Builtin::BI__builtin_hlsl_adduint64: {
269 "AddUint64 operand types must match");
271 "AddUint64 operands must have an integer representation");
272 assert((NumElements == 2 || NumElements == 4) &&
273 "AddUint64 operands must have 2 or 4 elements");
281 if (NumElements == 2) {
282 LowA =
Builder.CreateExtractElement(OpA, (uint64_t)0,
"LowA");
283 HighA =
Builder.CreateExtractElement(OpA, (uint64_t)1,
"HighA");
284 LowB =
Builder.CreateExtractElement(OpB, (uint64_t)0,
"LowB");
285 HighB =
Builder.CreateExtractElement(OpB, (uint64_t)1,
"HighB");
287 LowA =
Builder.CreateShuffleVector(OpA, {0, 2},
"LowA");
288 HighA =
Builder.CreateShuffleVector(OpA, {1, 3},
"HighA");
289 LowB =
Builder.CreateShuffleVector(OpB, {0, 2},
"LowB");
290 HighB =
Builder.CreateShuffleVector(OpB, {1, 3},
"HighB");
297 *
this, Intrinsic::uadd_with_overflow, LowA, LowB, Carry);
298 llvm::Value *ZExtCarry =
299 Builder.CreateZExt(Carry, HighA->getType(),
"CarryZExt");
302 llvm::Value *HighSum =
Builder.CreateAdd(HighA, HighB,
"HighSum");
303 llvm::Value *HighSumPlusCarry =
304 Builder.CreateAdd(HighSum, ZExtCarry,
"HighSumPlusCarry");
306 if (NumElements == 4) {
307 return Builder.CreateShuffleVector(LowSum, HighSumPlusCarry, {0, 2, 1, 3},
313 "hlsl.AddUint64.upto0");
318 case Builtin::BI__builtin_hlsl_resource_getpointer: {
323 return Builder.CreateIntrinsic(
324 RetTy,
CGM.getHLSLRuntime().getCreateResourceGetPointerIntrinsic(),
327 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
328 llvm::Type *HandleTy =
CGM.getTypes().ConvertType(E->
getType());
329 return llvm::PoisonValue::get(HandleTy);
331 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
332 llvm::Type *HandleTy =
CGM.getTypes().ConvertType(E->
getType());
338 llvm::Intrinsic::ID IntrinsicID =
339 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
341 return Builder.CreateIntrinsic(HandleTy, IntrinsicID, Args);
343 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
344 llvm::Type *HandleTy =
CGM.getTypes().ConvertType(E->
getType());
350 llvm::Intrinsic::ID IntrinsicID =
351 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
353 return Builder.CreateIntrinsic(HandleTy, IntrinsicID, Args);
355 case Builtin::BI__builtin_hlsl_all: {
357 return Builder.CreateIntrinsic(
362 case Builtin::BI__builtin_hlsl_and: {
365 return Builder.CreateAnd(Op0, Op1,
"hlsl.and");
367 case Builtin::BI__builtin_hlsl_or: {
370 return Builder.CreateOr(Op0, Op1,
"hlsl.or");
372 case Builtin::BI__builtin_hlsl_any: {
374 return Builder.CreateIntrinsic(
379 case Builtin::BI__builtin_hlsl_asdouble:
381 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
388 Ty = VecTy->getElementType();
392 Intr =
CGM.getHLSLRuntime().getNClampIntrinsic();
394 Intr =
CGM.getHLSLRuntime().getUClampIntrinsic();
397 Intr =
CGM.getHLSLRuntime().getSClampIntrinsic();
399 return Builder.CreateIntrinsic(
403 case Builtin::BI__builtin_hlsl_crossf16:
404 case Builtin::BI__builtin_hlsl_crossf32: {
409 "cross operands must have a float representation");
414 "input vectors must have 3 elements each");
415 return Builder.CreateIntrinsic(
416 Op0->
getType(),
CGM.getHLSLRuntime().getCrossIntrinsic(),
419 case Builtin::BI__builtin_hlsl_dot: {
422 llvm::Type *T0 = Op0->
getType();
423 llvm::Type *T1 = Op1->
getType();
426 if (!T0->isVectorTy() && !T1->isVectorTy()) {
427 if (T0->isFloatingPointTy())
428 return Builder.CreateFMul(Op0, Op1,
"hlsl.dot");
430 if (T0->isIntegerTy())
431 return Builder.CreateMul(Op0, Op1,
"hlsl.dot");
434 "Scalar dot product is only supported on ints and floats.");
439 "Dot product operands must have the same type.");
442 assert(VecTy0 &&
"Dot product argument must be a vector.");
444 return Builder.CreateIntrinsic(
449 case Builtin::BI__builtin_hlsl_dot4add_i8packed: {
454 Intrinsic::ID ID =
CGM.getHLSLRuntime().getDot4AddI8PackedIntrinsic();
457 return Builder.CreateIntrinsic(
459 nullptr,
"hlsl.dot4add.i8packed");
461 case Builtin::BI__builtin_hlsl_dot4add_u8packed: {
466 Intrinsic::ID ID =
CGM.getHLSLRuntime().getDot4AddU8PackedIntrinsic();
469 return Builder.CreateIntrinsic(
471 nullptr,
"hlsl.dot4add.u8packed");
473 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: {
476 return Builder.CreateIntrinsic(
481 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
484 return Builder.CreateIntrinsic(
487 nullptr,
"hlsl.firstbitlow");
489 case Builtin::BI__builtin_hlsl_lerp: {
494 llvm_unreachable(
"lerp operand must have a float representation");
495 return Builder.CreateIntrinsic(
496 X->getType(),
CGM.getHLSLRuntime().getLerpIntrinsic(),
499 case Builtin::BI__builtin_hlsl_normalize: {
503 "normalize operand must have a float representation");
505 return Builder.CreateIntrinsic(
508 nullptr,
"hlsl.normalize");
510 case Builtin::BI__builtin_hlsl_elementwise_degrees: {
514 "degree operand must have a float representation");
516 return Builder.CreateIntrinsic(
517 X->getType(),
CGM.getHLSLRuntime().getDegreesIntrinsic(),
520 case Builtin::BI__builtin_hlsl_elementwise_frac: {
523 llvm_unreachable(
"frac operand must have a float representation");
524 return Builder.CreateIntrinsic(
525 Op0->
getType(),
CGM.getHLSLRuntime().getFracIntrinsic(),
528 case Builtin::BI__builtin_hlsl_elementwise_isinf: {
530 llvm::Type *Xty = Op0->
getType();
531 llvm::Type *retType = llvm::Type::getInt1Ty(this->
getLLVMContext());
532 if (Xty->isVectorTy()) {
534 retType = llvm::VectorType::get(
535 retType, ElementCount::getFixed(XVecTy->getNumElements()));
538 llvm_unreachable(
"isinf operand must have a float representation");
539 return Builder.CreateIntrinsic(
540 retType,
CGM.getHLSLRuntime().getIsInfIntrinsic(),
543 case Builtin::BI__builtin_hlsl_mad: {
548 return Builder.CreateIntrinsic(
549 M->
getType(), Intrinsic::fmuladd,
553 if (
CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil)
554 return Builder.CreateIntrinsic(
555 M->
getType(), Intrinsic::dx_imad,
559 return Builder.CreateNSWAdd(Mul, B);
562 if (
CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil)
563 return Builder.CreateIntrinsic(
564 M->
getType(), Intrinsic::dx_umad,
568 return Builder.CreateNUWAdd(Mul, B);
570 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
573 llvm_unreachable(
"rcp operand must have a float representation");
574 llvm::Type *Ty = Op0->
getType();
575 llvm::Type *EltTy = Ty->getScalarType();
576 Constant *One = Ty->isVectorTy()
577 ? ConstantVector::getSplat(
578 ElementCount::getFixed(
580 ConstantFP::get(EltTy, 1.0))
581 : ConstantFP::get(EltTy, 1.0);
582 return Builder.CreateFDiv(One, Op0,
"hlsl.rcp");
584 case Builtin::BI__builtin_hlsl_elementwise_rsqrt: {
587 llvm_unreachable(
"rsqrt operand must have a float representation");
588 return Builder.CreateIntrinsic(
589 Op0->
getType(),
CGM.getHLSLRuntime().getRsqrtIntrinsic(),
592 case Builtin::BI__builtin_hlsl_elementwise_saturate: {
595 "saturate operand must have a float representation");
596 return Builder.CreateIntrinsic(
599 nullptr,
"hlsl.saturate");
601 case Builtin::BI__builtin_hlsl_select: {
614 if (!OpTrue->
getType()->isVectorTy())
616 Builder.CreateVectorSplat(VTy->getNumElements(), OpTrue,
"splat");
617 if (!OpFalse->
getType()->isVectorTy())
619 Builder.CreateVectorSplat(VTy->getNumElements(), OpFalse,
"splat");
623 Builder.CreateSelect(OpCond, OpTrue, OpFalse,
"hlsl.select");
630 case Builtin::BI__builtin_hlsl_step: {
635 "step operands must have a float representation");
636 return Builder.CreateIntrinsic(
637 Op0->
getType(),
CGM.getHLSLRuntime().getStepIntrinsic(),
640 case Builtin::BI__builtin_hlsl_wave_active_all_true: {
642 assert(Op->
getType()->isIntegerTy(1) &&
643 "Intrinsic WaveActiveAllTrue operand must be a bool");
645 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveActiveAllTrueIntrinsic();
647 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID), {Op});
649 case Builtin::BI__builtin_hlsl_wave_active_any_true: {
651 assert(Op->
getType()->isIntegerTy(1) &&
652 "Intrinsic WaveActiveAnyTrue operand must be a bool");
654 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic();
656 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID), {Op});
658 case Builtin::BI__builtin_hlsl_wave_active_count_bits: {
660 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveActiveCountBitsIntrinsic();
662 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID),
665 case Builtin::BI__builtin_hlsl_wave_active_sum: {
669 getTarget().getTriple().getArch(),
CGM.getHLSLRuntime(),
673 &
CGM.getModule(), IID, {OpExpr->getType()}),
674 ArrayRef{OpExpr},
"hlsl.wave.active.sum");
676 case Builtin::BI__builtin_hlsl_wave_active_max: {
680 getTarget().getTriple().getArch(),
CGM.getHLSLRuntime(),
684 &
CGM.getModule(), IID, {OpExpr->getType()}),
685 ArrayRef{OpExpr},
"hlsl.wave.active.max");
687 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
691 switch (
CGM.getTarget().getTriple().getArch()) {
692 case llvm::Triple::dxil:
694 &
CGM.getModule(), Intrinsic::dx_wave_getlaneindex));
695 case llvm::Triple::spirv:
697 llvm::FunctionType::get(
IntTy, {},
false),
698 "__hlsl_wave_get_lane_index", {},
false,
true));
701 "Intrinsic WaveGetLaneIndex not supported by target architecture");
704 case Builtin::BI__builtin_hlsl_wave_is_first_lane: {
705 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveIsFirstLaneIntrinsic();
707 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID));
709 case Builtin::BI__builtin_hlsl_wave_get_lane_count: {
710 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveGetLaneCountIntrinsic();
712 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID));
714 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
720 Intrinsic::getOrInsertDeclaration(
721 &
CGM.getModule(),
CGM.getHLSLRuntime().getWaveReadLaneAtIntrinsic(),
722 {OpExpr->getType()}),
723 ArrayRef{OpExpr, OpIndex},
"hlsl.wave.readlane");
725 case Builtin::BI__builtin_hlsl_elementwise_sign: {
726 auto *Arg0 = E->
getArg(0);
728 llvm::Type *Xty = Op0->
getType();
729 llvm::Type *retType = llvm::Type::getInt32Ty(this->
getLLVMContext());
730 if (Xty->isVectorTy()) {
731 auto *XVecTy = Arg0->getType()->castAs<
VectorType>();
732 retType = llvm::VectorType::get(
733 retType, ElementCount::getFixed(XVecTy->getNumElements()));
735 assert((Arg0->getType()->hasFloatingRepresentation() ||
736 Arg0->getType()->hasIntegerRepresentation()) &&
737 "sign operand must have a float or int representation");
739 if (Arg0->getType()->hasUnsignedIntegerRepresentation()) {
740 Value *Cmp =
Builder.CreateICmpEQ(Op0, ConstantInt::get(Xty, 0));
741 return Builder.CreateSelect(Cmp, ConstantInt::get(retType, 0),
742 ConstantInt::get(retType, 1),
"hlsl.sign");
745 return Builder.CreateIntrinsic(
746 retType,
CGM.getHLSLRuntime().getSignIntrinsic(),
749 case Builtin::BI__builtin_hlsl_elementwise_radians: {
752 "radians operand must have a float representation");
753 return Builder.CreateIntrinsic(
756 nullptr,
"hlsl.radians");
758 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
762 return Builder.CreateIntrinsic(
764 CGM.getHLSLRuntime().getBufferUpdateCounterIntrinsic(),
767 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
772 "asuint operands types mismatch");
775 case Builtin::BI__builtin_hlsl_elementwise_clip:
777 "clip operands types mismatch");
779 case Builtin::BI__builtin_hlsl_group_memory_barrier_with_group_sync: {
781 CGM.getHLSLRuntime().getGroupMemoryBarrierWithGroupSyncIntrinsic();
783 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID));
785 case Builtin::BI__builtin_get_spirv_spec_constant_bool:
786 case Builtin::BI__builtin_get_spirv_spec_constant_short:
787 case Builtin::BI__builtin_get_spirv_spec_constant_ushort:
788 case Builtin::BI__builtin_get_spirv_spec_constant_int:
789 case Builtin::BI__builtin_get_spirv_spec_constant_uint:
790 case Builtin::BI__builtin_get_spirv_spec_constant_longlong:
791 case Builtin::BI__builtin_get_spirv_spec_constant_ulonglong:
792 case Builtin::BI__builtin_get_spirv_spec_constant_half:
793 case Builtin::BI__builtin_get_spirv_spec_constant_float:
794 case Builtin::BI__builtin_get_spirv_spec_constant_double: {
798 llvm::Value *Args[] = {SpecId, DefaultVal};
799 return Builder.CreateCall(SpecConstantFn, Args);