432 case Builtin::BI__builtin_hlsl_adduint64: {
438 "AddUint64 operand types must match");
440 "AddUint64 operands must have an integer representation");
441 assert((NumElements == 2 || NumElements == 4) &&
442 "AddUint64 operands must have 2 or 4 elements");
450 if (NumElements == 2) {
451 LowA =
Builder.CreateExtractElement(OpA, (uint64_t)0,
"LowA");
452 HighA =
Builder.CreateExtractElement(OpA, (uint64_t)1,
"HighA");
453 LowB =
Builder.CreateExtractElement(OpB, (uint64_t)0,
"LowB");
454 HighB =
Builder.CreateExtractElement(OpB, (uint64_t)1,
"HighB");
456 LowA =
Builder.CreateShuffleVector(OpA, {0, 2},
"LowA");
457 HighA =
Builder.CreateShuffleVector(OpA, {1, 3},
"HighA");
458 LowB =
Builder.CreateShuffleVector(OpB, {0, 2},
"LowB");
459 HighB =
Builder.CreateShuffleVector(OpB, {1, 3},
"HighB");
466 *
this, Intrinsic::uadd_with_overflow, LowA, LowB, Carry);
467 llvm::Value *ZExtCarry =
468 Builder.CreateZExt(Carry, HighA->getType(),
"CarryZExt");
471 llvm::Value *HighSum =
Builder.CreateAdd(HighA, HighB,
"HighSum");
472 llvm::Value *HighSumPlusCarry =
473 Builder.CreateAdd(HighSum, ZExtCarry,
"HighSumPlusCarry");
475 if (NumElements == 4) {
476 return Builder.CreateShuffleVector(LowSum, HighSumPlusCarry, {0, 2, 1, 3},
482 "hlsl.AddUint64.upto0");
487 case Builtin::BI__builtin_hlsl_resource_getpointer: {
492 return Builder.CreateIntrinsic(
493 RetTy,
CGM.getHLSLRuntime().getCreateResourceGetPointerIntrinsic(),
496 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
505 const HLSLAttributedResourceType *RT =
506 HandleTy->
getAs<HLSLAttributedResourceType>();
507 assert(
CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil &&
508 "Only DXIL currently implements load with status");
510 Intrinsic::ID IntrID = RT->getAttrs().RawBuffer
511 ? llvm::Intrinsic::dx_resource_load_rawbuffer
512 : llvm::Intrinsic::dx_resource_load_typedbuffer;
515 llvm::Type *RetTy = llvm::StructType::get(
Builder.getContext(),
516 {DataTy, Builder.getInt1Ty()});
519 Args.push_back(HandleOp);
520 Args.push_back(IndexOp);
522 if (RT->getAttrs().RawBuffer) {
524 Args.push_back(Offset);
530 Builder.CreateIntrinsic(RetTy, IntrID, Args, {},
"ld.struct");
531 Value *LoadedValue =
Builder.CreateExtractValue(ResRet, {0},
"ld.value");
532 Value *StatusBit =
Builder.CreateExtractValue(ResRet, {1},
"ld.status");
533 Value *ExtendedStatus =
534 Builder.CreateZExt(StatusBit,
Builder.getInt32Ty(),
"ld.status.ext");
535 Builder.CreateStore(ExtendedStatus, StatusAddr);
539 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
540 llvm::Type *HandleTy =
CGM.getTypes().ConvertType(E->
getType());
541 return llvm::PoisonValue::get(HandleTy);
543 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
544 llvm::Type *HandleTy =
CGM.getTypes().ConvertType(E->
getType());
550 llvm::Intrinsic::ID IntrinsicID =
551 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
553 return Builder.CreateIntrinsic(HandleTy, IntrinsicID, Args);
555 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
556 llvm::Type *HandleTy =
CGM.getTypes().ConvertType(E->
getType());
562 llvm::Intrinsic::ID IntrinsicID =
563 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
565 return Builder.CreateIntrinsic(HandleTy, IntrinsicID, Args);
567 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
569 if (!
CGM.getTriple().isSPIRV())
572 llvm::Type *HandleTy =
CGM.getTypes().ConvertType(E->
getType());
575 llvm::Intrinsic::ID IntrinsicID =
576 llvm::Intrinsic::spv_resource_counterhandlefromimplicitbinding;
578 return Builder.CreateIntrinsic(HandleTy, IntrinsicID, Args);
580 case Builtin::BI__builtin_hlsl_resource_nonuniformindex: {
583 return Builder.CreateIntrinsic(
584 RetTy,
CGM.getHLSLRuntime().getNonUniformResourceIndexIntrinsic(),
587 case Builtin::BI__builtin_hlsl_resource_getdimensions_x: {
592 RetTy,
CGM.getHLSLRuntime().getGetDimensionsXIntrinsic(),
594 return Builder.CreateStore(DimValue,
Dim.getAddress());
596 case Builtin::BI__builtin_hlsl_resource_getstride: {
600 case Builtin::BI__builtin_hlsl_all: {
602 return Builder.CreateIntrinsic(
607 case Builtin::BI__builtin_hlsl_and: {
610 return Builder.CreateAnd(Op0, Op1,
"hlsl.and");
612 case Builtin::BI__builtin_hlsl_or: {
615 return Builder.CreateOr(Op0, Op1,
"hlsl.or");
617 case Builtin::BI__builtin_hlsl_any: {
619 return Builder.CreateIntrinsic(
624 case Builtin::BI__builtin_hlsl_asdouble:
626 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
633 Ty = VecTy->getElementType();
637 Intr =
CGM.getHLSLRuntime().getNClampIntrinsic();
639 Intr =
CGM.getHLSLRuntime().getUClampIntrinsic();
642 Intr =
CGM.getHLSLRuntime().getSClampIntrinsic();
644 return Builder.CreateIntrinsic(
648 case Builtin::BI__builtin_hlsl_crossf16:
649 case Builtin::BI__builtin_hlsl_crossf32: {
654 "cross operands must have a float representation");
659 "input vectors must have 3 elements each");
660 return Builder.CreateIntrinsic(
661 Op0->
getType(),
CGM.getHLSLRuntime().getCrossIntrinsic(),
664 case Builtin::BI__builtin_hlsl_dot: {
667 llvm::Type *T0 = Op0->
getType();
668 llvm::Type *T1 = Op1->
getType();
671 if (!T0->isVectorTy() && !T1->isVectorTy()) {
672 if (T0->isFloatingPointTy())
673 return Builder.CreateFMul(Op0, Op1,
"hlsl.dot");
675 if (T0->isIntegerTy())
676 return Builder.CreateMul(Op0, Op1,
"hlsl.dot");
679 "Scalar dot product is only supported on ints and floats.");
684 "Dot product operands must have the same type.");
687 assert(VecTy0 &&
"Dot product argument must be a vector.");
689 return Builder.CreateIntrinsic(
694 case Builtin::BI__builtin_hlsl_dot4add_i8packed: {
699 Intrinsic::ID ID =
CGM.getHLSLRuntime().getDot4AddI8PackedIntrinsic();
702 return Builder.CreateIntrinsic(
704 nullptr,
"hlsl.dot4add.i8packed");
706 case Builtin::BI__builtin_hlsl_dot4add_u8packed: {
711 Intrinsic::ID ID =
CGM.getHLSLRuntime().getDot4AddU8PackedIntrinsic();
714 return Builder.CreateIntrinsic(
716 nullptr,
"hlsl.dot4add.u8packed");
718 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: {
721 return Builder.CreateIntrinsic(
726 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
729 return Builder.CreateIntrinsic(
732 nullptr,
"hlsl.firstbitlow");
734 case Builtin::BI__builtin_hlsl_lerp: {
739 llvm_unreachable(
"lerp operand must have a float representation");
740 return Builder.CreateIntrinsic(
741 X->getType(),
CGM.getHLSLRuntime().getLerpIntrinsic(),
744 case Builtin::BI__builtin_hlsl_normalize: {
748 "normalize operand must have a float representation");
750 return Builder.CreateIntrinsic(
753 nullptr,
"hlsl.normalize");
755 case Builtin::BI__builtin_hlsl_elementwise_degrees: {
759 "degree operand must have a float representation");
761 return Builder.CreateIntrinsic(
762 X->getType(),
CGM.getHLSLRuntime().getDegreesIntrinsic(),
765 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
768 case Builtin::BI__builtin_hlsl_elementwise_f32tof16: {
771 case Builtin::BI__builtin_hlsl_elementwise_frac: {
774 llvm_unreachable(
"frac operand must have a float representation");
775 return Builder.CreateIntrinsic(
776 Op0->
getType(),
CGM.getHLSLRuntime().getFracIntrinsic(),
779 case Builtin::BI__builtin_hlsl_elementwise_isinf: {
781 llvm::Type *Xty = Op0->
getType();
782 llvm::Type *retType = llvm::Type::getInt1Ty(this->
getLLVMContext());
783 if (Xty->isVectorTy()) {
785 retType = llvm::VectorType::get(
786 retType, ElementCount::getFixed(XVecTy->getNumElements()));
789 llvm_unreachable(
"isinf operand must have a float representation");
790 return Builder.CreateIntrinsic(
791 retType,
CGM.getHLSLRuntime().getIsInfIntrinsic(),
794 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
796 llvm::Type *Xty = Op0->
getType();
797 llvm::Type *retType = llvm::Type::getInt1Ty(this->
getLLVMContext());
798 if (Xty->isVectorTy()) {
800 retType = llvm::VectorType::get(
801 retType, ElementCount::getFixed(XVecTy->getNumElements()));
804 llvm_unreachable(
"isnan operand must have a float representation");
805 return Builder.CreateIntrinsic(
806 retType,
CGM.getHLSLRuntime().getIsNaNIntrinsic(),
809 case Builtin::BI__builtin_hlsl_mad: {
814 return Builder.CreateIntrinsic(
815 M->
getType(), Intrinsic::fmuladd,
819 if (
CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil)
820 return Builder.CreateIntrinsic(
821 M->
getType(), Intrinsic::dx_imad,
825 return Builder.CreateNSWAdd(Mul, B);
828 if (
CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil)
829 return Builder.CreateIntrinsic(
830 M->
getType(), Intrinsic::dx_umad,
834 return Builder.CreateNUWAdd(Mul, B);
836 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
839 llvm_unreachable(
"rcp operand must have a float representation");
840 llvm::Type *Ty = Op0->
getType();
841 llvm::Type *EltTy = Ty->getScalarType();
842 Constant *One = Ty->isVectorTy()
843 ? ConstantVector::getSplat(
844 ElementCount::getFixed(
846 ConstantFP::get(EltTy, 1.0))
847 : ConstantFP::get(EltTy, 1.0);
848 return Builder.CreateFDiv(One, Op0,
"hlsl.rcp");
850 case Builtin::BI__builtin_hlsl_elementwise_rsqrt: {
853 llvm_unreachable(
"rsqrt operand must have a float representation");
854 return Builder.CreateIntrinsic(
855 Op0->
getType(),
CGM.getHLSLRuntime().getRsqrtIntrinsic(),
858 case Builtin::BI__builtin_hlsl_elementwise_saturate: {
861 "saturate operand must have a float representation");
862 return Builder.CreateIntrinsic(
865 nullptr,
"hlsl.saturate");
867 case Builtin::BI__builtin_hlsl_select: {
880 if (!OpTrue->
getType()->isVectorTy())
882 Builder.CreateVectorSplat(VTy->getNumElements(), OpTrue,
"splat");
883 if (!OpFalse->
getType()->isVectorTy())
885 Builder.CreateVectorSplat(VTy->getNumElements(), OpFalse,
"splat");
889 Builder.CreateSelect(OpCond, OpTrue, OpFalse,
"hlsl.select");
896 case Builtin::BI__builtin_hlsl_step: {
901 "step operands must have a float representation");
902 return Builder.CreateIntrinsic(
903 Op0->
getType(),
CGM.getHLSLRuntime().getStepIntrinsic(),
906 case Builtin::BI__builtin_hlsl_wave_active_all_true: {
908 assert(Op->
getType()->isIntegerTy(1) &&
909 "Intrinsic WaveActiveAllTrue operand must be a bool");
911 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveActiveAllTrueIntrinsic();
913 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID), {Op});
915 case Builtin::BI__builtin_hlsl_wave_active_any_true: {
917 assert(Op->
getType()->isIntegerTy(1) &&
918 "Intrinsic WaveActiveAnyTrue operand must be a bool");
920 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic();
922 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID), {Op});
924 case Builtin::BI__builtin_hlsl_wave_active_ballot: {
926 assert(Op->
getType()->isIntegerTy(1) &&
927 "Intrinsic WaveActiveBallot operand must be a bool");
931 case Builtin::BI__builtin_hlsl_wave_active_count_bits: {
933 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveActiveCountBitsIntrinsic();
935 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID),
938 case Builtin::BI__builtin_hlsl_wave_active_sum: {
942 getTarget().getTriple().getArch(),
CGM.getHLSLRuntime(),
946 &
CGM.getModule(), IID, {OpExpr->getType()}),
947 ArrayRef{OpExpr},
"hlsl.wave.active.sum");
949 case Builtin::BI__builtin_hlsl_wave_active_max: {
953 getTarget().getTriple().getArch(),
CGM.getHLSLRuntime(),
957 &
CGM.getModule(), IID, {OpExpr->getType()}),
958 ArrayRef{OpExpr},
"hlsl.wave.active.max");
960 case Builtin::BI__builtin_hlsl_wave_active_min: {
964 getTarget().getTriple().getArch(),
CGM.getHLSLRuntime(),
968 &
CGM.getModule(), IID, {OpExpr->getType()}),
969 ArrayRef{OpExpr},
"hlsl.wave.active.min");
971 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
975 switch (
CGM.getTarget().getTriple().getArch()) {
976 case llvm::Triple::dxil:
978 &
CGM.getModule(), Intrinsic::dx_wave_getlaneindex));
979 case llvm::Triple::spirv:
981 llvm::FunctionType::get(
IntTy, {},
false),
982 "__hlsl_wave_get_lane_index", {},
false,
true));
985 "Intrinsic WaveGetLaneIndex not supported by target architecture");
988 case Builtin::BI__builtin_hlsl_wave_is_first_lane: {
989 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveIsFirstLaneIntrinsic();
991 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID));
993 case Builtin::BI__builtin_hlsl_wave_get_lane_count: {
994 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveGetLaneCountIntrinsic();
996 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID));
998 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
1004 Intrinsic::getOrInsertDeclaration(
1005 &
CGM.getModule(),
CGM.getHLSLRuntime().getWaveReadLaneAtIntrinsic(),
1006 {OpExpr->getType()}),
1007 ArrayRef{OpExpr, OpIndex},
"hlsl.wave.readlane");
1009 case Builtin::BI__builtin_hlsl_elementwise_sign: {
1010 auto *Arg0 = E->
getArg(0);
1012 llvm::Type *Xty = Op0->
getType();
1013 llvm::Type *retType = llvm::Type::getInt32Ty(this->
getLLVMContext());
1014 if (Xty->isVectorTy()) {
1015 auto *XVecTy = Arg0->getType()->castAs<
VectorType>();
1016 retType = llvm::VectorType::get(
1017 retType, ElementCount::getFixed(XVecTy->getNumElements()));
1019 assert((Arg0->getType()->hasFloatingRepresentation() ||
1020 Arg0->getType()->hasIntegerRepresentation()) &&
1021 "sign operand must have a float or int representation");
1023 if (Arg0->getType()->hasUnsignedIntegerRepresentation()) {
1024 Value *Cmp =
Builder.CreateICmpEQ(Op0, ConstantInt::get(Xty, 0));
1025 return Builder.CreateSelect(Cmp, ConstantInt::get(retType, 0),
1026 ConstantInt::get(retType, 1),
"hlsl.sign");
1029 return Builder.CreateIntrinsic(
1030 retType,
CGM.getHLSLRuntime().getSignIntrinsic(),
1033 case Builtin::BI__builtin_hlsl_elementwise_radians: {
1036 "radians operand must have a float representation");
1037 return Builder.CreateIntrinsic(
1040 nullptr,
"hlsl.radians");
1042 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
1046 return Builder.CreateIntrinsic(
1048 CGM.getHLSLRuntime().getBufferUpdateCounterIntrinsic(),
1051 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
1056 "asuint operands types mismatch");
1059 case Builtin::BI__builtin_hlsl_elementwise_clip:
1061 "clip operands types mismatch");
1063 case Builtin::BI__builtin_hlsl_group_memory_barrier_with_group_sync: {
1065 CGM.getHLSLRuntime().getGroupMemoryBarrierWithGroupSyncIntrinsic();
1067 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID));
1069 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse: {
1072 llvm_unreachable(
"ddx_coarse operand must have a float representation");
1073 Intrinsic::ID ID =
CGM.getHLSLRuntime().getDdxCoarseIntrinsic();
1078 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse: {
1081 llvm_unreachable(
"ddy_coarse operand must have a float representation");
1082 Intrinsic::ID ID =
CGM.getHLSLRuntime().getDdyCoarseIntrinsic();
1087 case Builtin::BI__builtin_hlsl_elementwise_ddx_fine: {
1090 llvm_unreachable(
"ddx_fine operand must have a float representation");
1091 Intrinsic::ID ID =
CGM.getHLSLRuntime().getDdxFineIntrinsic();
1096 case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
1099 llvm_unreachable(
"ddy_fine operand must have a float representation");
1100 Intrinsic::ID ID =
CGM.getHLSLRuntime().getDdyFineIntrinsic();
1105 case Builtin::BI__builtin_get_spirv_spec_constant_bool:
1106 case Builtin::BI__builtin_get_spirv_spec_constant_short:
1107 case Builtin::BI__builtin_get_spirv_spec_constant_ushort:
1108 case Builtin::BI__builtin_get_spirv_spec_constant_int:
1109 case Builtin::BI__builtin_get_spirv_spec_constant_uint:
1110 case Builtin::BI__builtin_get_spirv_spec_constant_longlong:
1111 case Builtin::BI__builtin_get_spirv_spec_constant_ulonglong:
1112 case Builtin::BI__builtin_get_spirv_spec_constant_half:
1113 case Builtin::BI__builtin_get_spirv_spec_constant_float:
1114 case Builtin::BI__builtin_get_spirv_spec_constant_double: {
1118 llvm::Value *Args[] = {SpecId, DefaultVal};
1119 return Builder.CreateCall(SpecConstantFn, Args);