343 case Builtin::BI__builtin_hlsl_adduint64: {
349 "AddUint64 operand types must match");
351 "AddUint64 operands must have an integer representation");
352 assert((NumElements == 2 || NumElements == 4) &&
353 "AddUint64 operands must have 2 or 4 elements");
361 if (NumElements == 2) {
362 LowA =
Builder.CreateExtractElement(OpA, (uint64_t)0,
"LowA");
363 HighA =
Builder.CreateExtractElement(OpA, (uint64_t)1,
"HighA");
364 LowB =
Builder.CreateExtractElement(OpB, (uint64_t)0,
"LowB");
365 HighB =
Builder.CreateExtractElement(OpB, (uint64_t)1,
"HighB");
367 LowA =
Builder.CreateShuffleVector(OpA, {0, 2},
"LowA");
368 HighA =
Builder.CreateShuffleVector(OpA, {1, 3},
"HighA");
369 LowB =
Builder.CreateShuffleVector(OpB, {0, 2},
"LowB");
370 HighB =
Builder.CreateShuffleVector(OpB, {1, 3},
"HighB");
377 *
this, Intrinsic::uadd_with_overflow, LowA, LowB, Carry);
378 llvm::Value *ZExtCarry =
379 Builder.CreateZExt(Carry, HighA->getType(),
"CarryZExt");
382 llvm::Value *HighSum =
Builder.CreateAdd(HighA, HighB,
"HighSum");
383 llvm::Value *HighSumPlusCarry =
384 Builder.CreateAdd(HighSum, ZExtCarry,
"HighSumPlusCarry");
386 if (NumElements == 4) {
387 return Builder.CreateShuffleVector(LowSum, HighSumPlusCarry, {0, 2, 1, 3},
393 "hlsl.AddUint64.upto0");
398 case Builtin::BI__builtin_hlsl_resource_getpointer: {
403 return Builder.CreateIntrinsic(
404 RetTy,
CGM.getHLSLRuntime().getCreateResourceGetPointerIntrinsic(),
407 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
416 const HLSLAttributedResourceType *RT =
417 HandleTy->
getAs<HLSLAttributedResourceType>();
418 assert(
CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil &&
419 "Only DXIL currently implements load with status");
421 Intrinsic::ID IntrID = RT->getAttrs().RawBuffer
422 ? llvm::Intrinsic::dx_resource_load_rawbuffer
423 : llvm::Intrinsic::dx_resource_load_typedbuffer;
426 llvm::Type *RetTy = llvm::StructType::get(
Builder.getContext(),
427 {DataTy, Builder.getInt1Ty()});
430 Args.push_back(HandleOp);
431 Args.push_back(IndexOp);
433 if (RT->getAttrs().RawBuffer) {
435 Args.push_back(Offset);
441 Builder.CreateIntrinsic(RetTy, IntrID, Args, {},
"ld.struct");
442 Value *LoadedValue =
Builder.CreateExtractValue(ResRet, {0},
"ld.value");
443 Value *StatusBit =
Builder.CreateExtractValue(ResRet, {1},
"ld.status");
444 Value *ExtendedStatus =
445 Builder.CreateZExt(StatusBit,
Builder.getInt32Ty(),
"ld.status.ext");
446 Builder.CreateStore(ExtendedStatus, StatusAddr);
450 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
451 llvm::Type *HandleTy =
CGM.getTypes().ConvertType(E->
getType());
452 return llvm::PoisonValue::get(HandleTy);
454 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
455 llvm::Type *HandleTy =
CGM.getTypes().ConvertType(E->
getType());
461 llvm::Intrinsic::ID IntrinsicID =
462 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
464 return Builder.CreateIntrinsic(HandleTy, IntrinsicID, Args);
466 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
467 llvm::Type *HandleTy =
CGM.getTypes().ConvertType(E->
getType());
473 llvm::Intrinsic::ID IntrinsicID =
474 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
476 return Builder.CreateIntrinsic(HandleTy, IntrinsicID, Args);
478 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
480 if (!
CGM.getTriple().isSPIRV())
483 llvm::Type *HandleTy =
CGM.getTypes().ConvertType(E->
getType());
486 llvm::Intrinsic::ID IntrinsicID =
487 llvm::Intrinsic::spv_resource_counterhandlefromimplicitbinding;
489 return Builder.CreateIntrinsic(HandleTy, IntrinsicID, Args);
491 case Builtin::BI__builtin_hlsl_resource_nonuniformindex: {
494 return Builder.CreateIntrinsic(
495 RetTy,
CGM.getHLSLRuntime().getNonUniformResourceIndexIntrinsic(),
498 case Builtin::BI__builtin_hlsl_resource_getdimensions_x: {
503 RetTy,
CGM.getHLSLRuntime().getGetDimensionsXIntrinsic(),
505 return Builder.CreateStore(DimValue,
Dim.getAddress());
507 case Builtin::BI__builtin_hlsl_resource_getstride: {
511 case Builtin::BI__builtin_hlsl_all: {
513 return Builder.CreateIntrinsic(
518 case Builtin::BI__builtin_hlsl_and: {
521 return Builder.CreateAnd(Op0, Op1,
"hlsl.and");
523 case Builtin::BI__builtin_hlsl_or: {
526 return Builder.CreateOr(Op0, Op1,
"hlsl.or");
528 case Builtin::BI__builtin_hlsl_any: {
530 return Builder.CreateIntrinsic(
535 case Builtin::BI__builtin_hlsl_asdouble:
537 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
544 Ty = VecTy->getElementType();
548 Intr =
CGM.getHLSLRuntime().getNClampIntrinsic();
550 Intr =
CGM.getHLSLRuntime().getUClampIntrinsic();
553 Intr =
CGM.getHLSLRuntime().getSClampIntrinsic();
555 return Builder.CreateIntrinsic(
559 case Builtin::BI__builtin_hlsl_crossf16:
560 case Builtin::BI__builtin_hlsl_crossf32: {
565 "cross operands must have a float representation");
570 "input vectors must have 3 elements each");
571 return Builder.CreateIntrinsic(
572 Op0->
getType(),
CGM.getHLSLRuntime().getCrossIntrinsic(),
575 case Builtin::BI__builtin_hlsl_dot: {
578 llvm::Type *T0 = Op0->
getType();
579 llvm::Type *T1 = Op1->
getType();
582 if (!T0->isVectorTy() && !T1->isVectorTy()) {
583 if (T0->isFloatingPointTy())
584 return Builder.CreateFMul(Op0, Op1,
"hlsl.dot");
586 if (T0->isIntegerTy())
587 return Builder.CreateMul(Op0, Op1,
"hlsl.dot");
590 "Scalar dot product is only supported on ints and floats.");
595 "Dot product operands must have the same type.");
598 assert(VecTy0 &&
"Dot product argument must be a vector.");
600 return Builder.CreateIntrinsic(
605 case Builtin::BI__builtin_hlsl_dot4add_i8packed: {
610 Intrinsic::ID ID =
CGM.getHLSLRuntime().getDot4AddI8PackedIntrinsic();
613 return Builder.CreateIntrinsic(
615 nullptr,
"hlsl.dot4add.i8packed");
617 case Builtin::BI__builtin_hlsl_dot4add_u8packed: {
622 Intrinsic::ID ID =
CGM.getHLSLRuntime().getDot4AddU8PackedIntrinsic();
625 return Builder.CreateIntrinsic(
627 nullptr,
"hlsl.dot4add.u8packed");
629 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: {
632 return Builder.CreateIntrinsic(
637 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
640 return Builder.CreateIntrinsic(
643 nullptr,
"hlsl.firstbitlow");
645 case Builtin::BI__builtin_hlsl_lerp: {
650 llvm_unreachable(
"lerp operand must have a float representation");
651 return Builder.CreateIntrinsic(
652 X->getType(),
CGM.getHLSLRuntime().getLerpIntrinsic(),
655 case Builtin::BI__builtin_hlsl_normalize: {
659 "normalize operand must have a float representation");
661 return Builder.CreateIntrinsic(
664 nullptr,
"hlsl.normalize");
666 case Builtin::BI__builtin_hlsl_elementwise_degrees: {
670 "degree operand must have a float representation");
672 return Builder.CreateIntrinsic(
673 X->getType(),
CGM.getHLSLRuntime().getDegreesIntrinsic(),
676 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
679 case Builtin::BI__builtin_hlsl_elementwise_frac: {
682 llvm_unreachable(
"frac operand must have a float representation");
683 return Builder.CreateIntrinsic(
684 Op0->
getType(),
CGM.getHLSLRuntime().getFracIntrinsic(),
687 case Builtin::BI__builtin_hlsl_elementwise_isinf: {
689 llvm::Type *Xty = Op0->
getType();
690 llvm::Type *retType = llvm::Type::getInt1Ty(this->
getLLVMContext());
691 if (Xty->isVectorTy()) {
693 retType = llvm::VectorType::get(
694 retType, ElementCount::getFixed(XVecTy->getNumElements()));
697 llvm_unreachable(
"isinf operand must have a float representation");
698 return Builder.CreateIntrinsic(
699 retType,
CGM.getHLSLRuntime().getIsInfIntrinsic(),
702 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
704 llvm::Type *Xty = Op0->
getType();
705 llvm::Type *retType = llvm::Type::getInt1Ty(this->
getLLVMContext());
706 if (Xty->isVectorTy()) {
708 retType = llvm::VectorType::get(
709 retType, ElementCount::getFixed(XVecTy->getNumElements()));
712 llvm_unreachable(
"isnan operand must have a float representation");
713 return Builder.CreateIntrinsic(
714 retType,
CGM.getHLSLRuntime().getIsNaNIntrinsic(),
717 case Builtin::BI__builtin_hlsl_mad: {
722 return Builder.CreateIntrinsic(
723 M->
getType(), Intrinsic::fmuladd,
727 if (
CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil)
728 return Builder.CreateIntrinsic(
729 M->
getType(), Intrinsic::dx_imad,
733 return Builder.CreateNSWAdd(Mul, B);
736 if (
CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil)
737 return Builder.CreateIntrinsic(
738 M->
getType(), Intrinsic::dx_umad,
742 return Builder.CreateNUWAdd(Mul, B);
744 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
747 llvm_unreachable(
"rcp operand must have a float representation");
748 llvm::Type *Ty = Op0->
getType();
749 llvm::Type *EltTy = Ty->getScalarType();
750 Constant *One = Ty->isVectorTy()
751 ? ConstantVector::getSplat(
752 ElementCount::getFixed(
754 ConstantFP::get(EltTy, 1.0))
755 : ConstantFP::get(EltTy, 1.0);
756 return Builder.CreateFDiv(One, Op0,
"hlsl.rcp");
758 case Builtin::BI__builtin_hlsl_elementwise_rsqrt: {
761 llvm_unreachable(
"rsqrt operand must have a float representation");
762 return Builder.CreateIntrinsic(
763 Op0->
getType(),
CGM.getHLSLRuntime().getRsqrtIntrinsic(),
766 case Builtin::BI__builtin_hlsl_elementwise_saturate: {
769 "saturate operand must have a float representation");
770 return Builder.CreateIntrinsic(
773 nullptr,
"hlsl.saturate");
775 case Builtin::BI__builtin_hlsl_select: {
788 if (!OpTrue->
getType()->isVectorTy())
790 Builder.CreateVectorSplat(VTy->getNumElements(), OpTrue,
"splat");
791 if (!OpFalse->
getType()->isVectorTy())
793 Builder.CreateVectorSplat(VTy->getNumElements(), OpFalse,
"splat");
797 Builder.CreateSelect(OpCond, OpTrue, OpFalse,
"hlsl.select");
804 case Builtin::BI__builtin_hlsl_step: {
809 "step operands must have a float representation");
810 return Builder.CreateIntrinsic(
811 Op0->
getType(),
CGM.getHLSLRuntime().getStepIntrinsic(),
814 case Builtin::BI__builtin_hlsl_wave_active_all_true: {
816 assert(Op->
getType()->isIntegerTy(1) &&
817 "Intrinsic WaveActiveAllTrue operand must be a bool");
819 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveActiveAllTrueIntrinsic();
821 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID), {Op});
823 case Builtin::BI__builtin_hlsl_wave_active_any_true: {
825 assert(Op->
getType()->isIntegerTy(1) &&
826 "Intrinsic WaveActiveAnyTrue operand must be a bool");
828 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic();
830 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID), {Op});
832 case Builtin::BI__builtin_hlsl_wave_active_count_bits: {
834 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveActiveCountBitsIntrinsic();
836 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID),
839 case Builtin::BI__builtin_hlsl_wave_active_sum: {
843 getTarget().getTriple().getArch(),
CGM.getHLSLRuntime(),
847 &
CGM.getModule(), IID, {OpExpr->getType()}),
848 ArrayRef{OpExpr},
"hlsl.wave.active.sum");
850 case Builtin::BI__builtin_hlsl_wave_active_max: {
854 getTarget().getTriple().getArch(),
CGM.getHLSLRuntime(),
858 &
CGM.getModule(), IID, {OpExpr->getType()}),
859 ArrayRef{OpExpr},
"hlsl.wave.active.max");
861 case Builtin::BI__builtin_hlsl_wave_active_min: {
865 getTarget().getTriple().getArch(),
CGM.getHLSLRuntime(),
869 &
CGM.getModule(), IID, {OpExpr->getType()}),
870 ArrayRef{OpExpr},
"hlsl.wave.active.min");
872 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
876 switch (
CGM.getTarget().getTriple().getArch()) {
877 case llvm::Triple::dxil:
879 &
CGM.getModule(), Intrinsic::dx_wave_getlaneindex));
880 case llvm::Triple::spirv:
882 llvm::FunctionType::get(
IntTy, {},
false),
883 "__hlsl_wave_get_lane_index", {},
false,
true));
886 "Intrinsic WaveGetLaneIndex not supported by target architecture");
889 case Builtin::BI__builtin_hlsl_wave_is_first_lane: {
890 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveIsFirstLaneIntrinsic();
892 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID));
894 case Builtin::BI__builtin_hlsl_wave_get_lane_count: {
895 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveGetLaneCountIntrinsic();
897 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID));
899 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
905 Intrinsic::getOrInsertDeclaration(
906 &
CGM.getModule(),
CGM.getHLSLRuntime().getWaveReadLaneAtIntrinsic(),
907 {OpExpr->getType()}),
908 ArrayRef{OpExpr, OpIndex},
"hlsl.wave.readlane");
910 case Builtin::BI__builtin_hlsl_elementwise_sign: {
911 auto *Arg0 = E->
getArg(0);
913 llvm::Type *Xty = Op0->
getType();
914 llvm::Type *retType = llvm::Type::getInt32Ty(this->
getLLVMContext());
915 if (Xty->isVectorTy()) {
916 auto *XVecTy = Arg0->getType()->castAs<
VectorType>();
917 retType = llvm::VectorType::get(
918 retType, ElementCount::getFixed(XVecTy->getNumElements()));
920 assert((Arg0->getType()->hasFloatingRepresentation() ||
921 Arg0->getType()->hasIntegerRepresentation()) &&
922 "sign operand must have a float or int representation");
924 if (Arg0->getType()->hasUnsignedIntegerRepresentation()) {
925 Value *Cmp =
Builder.CreateICmpEQ(Op0, ConstantInt::get(Xty, 0));
926 return Builder.CreateSelect(Cmp, ConstantInt::get(retType, 0),
927 ConstantInt::get(retType, 1),
"hlsl.sign");
930 return Builder.CreateIntrinsic(
931 retType,
CGM.getHLSLRuntime().getSignIntrinsic(),
934 case Builtin::BI__builtin_hlsl_elementwise_radians: {
937 "radians operand must have a float representation");
938 return Builder.CreateIntrinsic(
941 nullptr,
"hlsl.radians");
943 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
947 return Builder.CreateIntrinsic(
949 CGM.getHLSLRuntime().getBufferUpdateCounterIntrinsic(),
952 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
957 "asuint operands types mismatch");
960 case Builtin::BI__builtin_hlsl_elementwise_clip:
962 "clip operands types mismatch");
964 case Builtin::BI__builtin_hlsl_group_memory_barrier_with_group_sync: {
966 CGM.getHLSLRuntime().getGroupMemoryBarrierWithGroupSyncIntrinsic();
968 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID));
970 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse: {
973 llvm_unreachable(
"ddx_coarse operand must have a float representation");
974 Intrinsic::ID ID =
CGM.getHLSLRuntime().getDdxCoarseIntrinsic();
979 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse: {
982 llvm_unreachable(
"ddy_coarse operand must have a float representation");
983 Intrinsic::ID ID =
CGM.getHLSLRuntime().getDdyCoarseIntrinsic();
988 case Builtin::BI__builtin_get_spirv_spec_constant_bool:
989 case Builtin::BI__builtin_get_spirv_spec_constant_short:
990 case Builtin::BI__builtin_get_spirv_spec_constant_ushort:
991 case Builtin::BI__builtin_get_spirv_spec_constant_int:
992 case Builtin::BI__builtin_get_spirv_spec_constant_uint:
993 case Builtin::BI__builtin_get_spirv_spec_constant_longlong:
994 case Builtin::BI__builtin_get_spirv_spec_constant_ulonglong:
995 case Builtin::BI__builtin_get_spirv_spec_constant_half:
996 case Builtin::BI__builtin_get_spirv_spec_constant_float:
997 case Builtin::BI__builtin_get_spirv_spec_constant_double: {
1001 llvm::Value *Args[] = {SpecId, DefaultVal};
1002 return Builder.CreateCall(SpecConstantFn, Args);