445 case Builtin::BI__builtin_hlsl_adduint64: {
451 "AddUint64 operand types must match");
453 "AddUint64 operands must have an integer representation");
454 assert((NumElements == 2 || NumElements == 4) &&
455 "AddUint64 operands must have 2 or 4 elements");
463 if (NumElements == 2) {
464 LowA =
Builder.CreateExtractElement(OpA, (uint64_t)0,
"LowA");
465 HighA =
Builder.CreateExtractElement(OpA, (uint64_t)1,
"HighA");
466 LowB =
Builder.CreateExtractElement(OpB, (uint64_t)0,
"LowB");
467 HighB =
Builder.CreateExtractElement(OpB, (uint64_t)1,
"HighB");
469 LowA =
Builder.CreateShuffleVector(OpA, {0, 2},
"LowA");
470 HighA =
Builder.CreateShuffleVector(OpA, {1, 3},
"HighA");
471 LowB =
Builder.CreateShuffleVector(OpB, {0, 2},
"LowB");
472 HighB =
Builder.CreateShuffleVector(OpB, {1, 3},
"HighB");
479 *
this, Intrinsic::uadd_with_overflow, LowA, LowB, Carry);
480 llvm::Value *ZExtCarry =
481 Builder.CreateZExt(Carry, HighA->getType(),
"CarryZExt");
484 llvm::Value *HighSum =
Builder.CreateAdd(HighA, HighB,
"HighSum");
485 llvm::Value *HighSumPlusCarry =
486 Builder.CreateAdd(HighSum, ZExtCarry,
"HighSumPlusCarry");
488 if (NumElements == 4) {
489 return Builder.CreateShuffleVector(LowSum, HighSumPlusCarry, {0, 2, 1, 3},
495 "hlsl.AddUint64.upto0");
500 case Builtin::BI__builtin_hlsl_resource_getpointer: {
505 return Builder.CreateIntrinsic(
506 RetTy,
CGM.getHLSLRuntime().getCreateResourceGetPointerIntrinsic(),
509 case Builtin::BI__builtin_hlsl_resource_sample: {
515 Args.push_back(HandleOp);
516 Args.push_back(SamplerOp);
517 Args.push_back(CoordOp);
524 llvm::Type *CoordTy = CoordOp->
getType();
526 llvm::Type *OffsetTy =
Int32Ty;
527 if (
auto *VT = dyn_cast<llvm::FixedVectorType>(CoordTy))
528 OffsetTy = llvm::FixedVectorType::get(
Int32Ty, VT->getNumElements());
529 Args.push_back(llvm::Constant::getNullValue(OffsetTy));
534 return Builder.CreateIntrinsic(
535 RetTy,
CGM.getHLSLRuntime().getSampleIntrinsic(), Args);
542 if (Clamp->getType() !=
Builder.getFloatTy())
544 Args.push_back(Clamp);
545 return Builder.CreateIntrinsic(
546 RetTy,
CGM.getHLSLRuntime().getSampleClampIntrinsic(), Args);
548 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
557 const HLSLAttributedResourceType *RT =
558 HandleTy->
getAs<HLSLAttributedResourceType>();
559 assert(
CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil &&
560 "Only DXIL currently implements load with status");
562 Intrinsic::ID IntrID = RT->getAttrs().RawBuffer
563 ? llvm::Intrinsic::dx_resource_load_rawbuffer
564 : llvm::Intrinsic::dx_resource_load_typedbuffer;
567 llvm::Type *RetTy = llvm::StructType::get(
Builder.getContext(),
568 {DataTy, Builder.getInt1Ty()});
571 Args.push_back(HandleOp);
572 Args.push_back(IndexOp);
574 if (RT->getAttrs().RawBuffer) {
576 Args.push_back(Offset);
582 Builder.CreateIntrinsic(RetTy, IntrID, Args, {},
"ld.struct");
583 Value *LoadedValue =
Builder.CreateExtractValue(ResRet, {0},
"ld.value");
584 Value *StatusBit =
Builder.CreateExtractValue(ResRet, {1},
"ld.status");
585 Value *ExtendedStatus =
586 Builder.CreateZExt(StatusBit,
Builder.getInt32Ty(),
"ld.status.ext");
587 Builder.CreateStore(ExtendedStatus, StatusAddr);
591 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
592 llvm::Type *HandleTy =
CGM.getTypes().ConvertType(E->
getType());
593 return llvm::PoisonValue::get(HandleTy);
595 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
596 llvm::Type *HandleTy =
CGM.getTypes().ConvertType(E->
getType());
602 llvm::Intrinsic::ID IntrinsicID =
603 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
605 return Builder.CreateIntrinsic(HandleTy, IntrinsicID, Args);
607 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
608 llvm::Type *HandleTy =
CGM.getTypes().ConvertType(E->
getType());
614 llvm::Intrinsic::ID IntrinsicID =
615 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
617 return Builder.CreateIntrinsic(HandleTy, IntrinsicID, Args);
619 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
621 if (!
CGM.getTriple().isSPIRV())
624 llvm::Type *HandleTy =
CGM.getTypes().ConvertType(E->
getType());
627 llvm::Intrinsic::ID IntrinsicID =
628 llvm::Intrinsic::spv_resource_counterhandlefromimplicitbinding;
630 return Builder.CreateIntrinsic(HandleTy, IntrinsicID, Args);
632 case Builtin::BI__builtin_hlsl_resource_nonuniformindex: {
635 return Builder.CreateIntrinsic(
636 RetTy,
CGM.getHLSLRuntime().getNonUniformResourceIndexIntrinsic(),
639 case Builtin::BI__builtin_hlsl_resource_getdimensions_x: {
644 RetTy,
CGM.getHLSLRuntime().getGetDimensionsXIntrinsic(),
646 return Builder.CreateStore(DimValue,
Dim.getAddress());
648 case Builtin::BI__builtin_hlsl_resource_getstride: {
652 case Builtin::BI__builtin_hlsl_all: {
654 return Builder.CreateIntrinsic(
659 case Builtin::BI__builtin_hlsl_and: {
662 return Builder.CreateAnd(Op0, Op1,
"hlsl.and");
664 case Builtin::BI__builtin_hlsl_or: {
667 return Builder.CreateOr(Op0, Op1,
"hlsl.or");
669 case Builtin::BI__builtin_hlsl_any: {
671 return Builder.CreateIntrinsic(
676 case Builtin::BI__builtin_hlsl_asdouble:
678 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
685 Ty = VecTy->getElementType();
689 Intr =
CGM.getHLSLRuntime().getNClampIntrinsic();
691 Intr =
CGM.getHLSLRuntime().getUClampIntrinsic();
694 Intr =
CGM.getHLSLRuntime().getSClampIntrinsic();
696 return Builder.CreateIntrinsic(
700 case Builtin::BI__builtin_hlsl_crossf16:
701 case Builtin::BI__builtin_hlsl_crossf32: {
706 "cross operands must have a float representation");
711 "input vectors must have 3 elements each");
712 return Builder.CreateIntrinsic(
713 Op0->
getType(),
CGM.getHLSLRuntime().getCrossIntrinsic(),
716 case Builtin::BI__builtin_hlsl_dot: {
719 llvm::Type *T0 = Op0->
getType();
720 llvm::Type *T1 = Op1->
getType();
723 if (!T0->isVectorTy() && !T1->isVectorTy()) {
724 if (T0->isFloatingPointTy())
725 return Builder.CreateFMul(Op0, Op1,
"hlsl.dot");
727 if (T0->isIntegerTy())
728 return Builder.CreateMul(Op0, Op1,
"hlsl.dot");
731 "Scalar dot product is only supported on ints and floats.");
736 "Dot product operands must have the same type.");
739 assert(VecTy0 &&
"Dot product argument must be a vector.");
741 return Builder.CreateIntrinsic(
746 case Builtin::BI__builtin_hlsl_dot4add_i8packed: {
751 Intrinsic::ID ID =
CGM.getHLSLRuntime().getDot4AddI8PackedIntrinsic();
754 return Builder.CreateIntrinsic(
756 nullptr,
"hlsl.dot4add.i8packed");
758 case Builtin::BI__builtin_hlsl_dot4add_u8packed: {
763 Intrinsic::ID ID =
CGM.getHLSLRuntime().getDot4AddU8PackedIntrinsic();
766 return Builder.CreateIntrinsic(
768 nullptr,
"hlsl.dot4add.u8packed");
770 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: {
773 return Builder.CreateIntrinsic(
778 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
781 return Builder.CreateIntrinsic(
784 nullptr,
"hlsl.firstbitlow");
786 case Builtin::BI__builtin_hlsl_lerp: {
791 llvm_unreachable(
"lerp operand must have a float representation");
792 return Builder.CreateIntrinsic(
793 X->getType(),
CGM.getHLSLRuntime().getLerpIntrinsic(),
796 case Builtin::BI__builtin_hlsl_normalize: {
800 "normalize operand must have a float representation");
802 return Builder.CreateIntrinsic(
805 nullptr,
"hlsl.normalize");
807 case Builtin::BI__builtin_hlsl_elementwise_degrees: {
811 "degree operand must have a float representation");
813 return Builder.CreateIntrinsic(
814 X->getType(),
CGM.getHLSLRuntime().getDegreesIntrinsic(),
817 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
820 case Builtin::BI__builtin_hlsl_elementwise_f32tof16: {
823 case Builtin::BI__builtin_hlsl_elementwise_frac: {
826 llvm_unreachable(
"frac operand must have a float representation");
827 return Builder.CreateIntrinsic(
828 Op0->
getType(),
CGM.getHLSLRuntime().getFracIntrinsic(),
831 case Builtin::BI__builtin_hlsl_elementwise_isinf: {
833 llvm::Type *Xty = Op0->
getType();
834 llvm::Type *retType = llvm::Type::getInt1Ty(this->
getLLVMContext());
835 if (Xty->isVectorTy()) {
837 retType = llvm::VectorType::get(
838 retType, ElementCount::getFixed(XVecTy->getNumElements()));
841 llvm_unreachable(
"isinf operand must have a float representation");
842 return Builder.CreateIntrinsic(
843 retType,
CGM.getHLSLRuntime().getIsInfIntrinsic(),
846 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
848 llvm::Type *Xty = Op0->
getType();
849 llvm::Type *retType = llvm::Type::getInt1Ty(this->
getLLVMContext());
850 if (Xty->isVectorTy()) {
852 retType = llvm::VectorType::get(
853 retType, ElementCount::getFixed(XVecTy->getNumElements()));
856 llvm_unreachable(
"isnan operand must have a float representation");
857 return Builder.CreateIntrinsic(
858 retType,
CGM.getHLSLRuntime().getIsNaNIntrinsic(),
861 case Builtin::BI__builtin_hlsl_mad: {
866 return Builder.CreateIntrinsic(
867 M->
getType(), Intrinsic::fmuladd,
871 if (
CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil)
872 return Builder.CreateIntrinsic(
873 M->
getType(), Intrinsic::dx_imad,
877 return Builder.CreateNSWAdd(Mul, B);
880 if (
CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil)
881 return Builder.CreateIntrinsic(
882 M->
getType(), Intrinsic::dx_umad,
886 return Builder.CreateNUWAdd(Mul, B);
888 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
891 llvm_unreachable(
"rcp operand must have a float representation");
892 llvm::Type *Ty = Op0->
getType();
893 llvm::Type *EltTy = Ty->getScalarType();
894 Constant *One = Ty->isVectorTy()
895 ? ConstantVector::getSplat(
896 ElementCount::getFixed(
898 ConstantFP::get(EltTy, 1.0))
899 : ConstantFP::get(EltTy, 1.0);
900 return Builder.CreateFDiv(One, Op0,
"hlsl.rcp");
902 case Builtin::BI__builtin_hlsl_elementwise_rsqrt: {
905 llvm_unreachable(
"rsqrt operand must have a float representation");
906 return Builder.CreateIntrinsic(
907 Op0->
getType(),
CGM.getHLSLRuntime().getRsqrtIntrinsic(),
910 case Builtin::BI__builtin_hlsl_elementwise_saturate: {
913 "saturate operand must have a float representation");
914 return Builder.CreateIntrinsic(
917 nullptr,
"hlsl.saturate");
919 case Builtin::BI__builtin_hlsl_wave_prefix_count_bits: {
921 assert(Op->
getType()->isIntegerTy(1) &&
922 "WavePrefixBitCount operand must be a boolean type");
928 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), IID),
ArrayRef{Op},
929 "hlsl.wave.prefix.bit.count");
931 case Builtin::BI__builtin_hlsl_select: {
944 if (!OpTrue->
getType()->isVectorTy())
946 Builder.CreateVectorSplat(VTy->getNumElements(), OpTrue,
"splat");
947 if (!OpFalse->
getType()->isVectorTy())
949 Builder.CreateVectorSplat(VTy->getNumElements(), OpFalse,
"splat");
953 Builder.CreateSelect(OpCond, OpTrue, OpFalse,
"hlsl.select");
960 case Builtin::BI__builtin_hlsl_step: {
965 "step operands must have a float representation");
966 return Builder.CreateIntrinsic(
967 Op0->
getType(),
CGM.getHLSLRuntime().getStepIntrinsic(),
970 case Builtin::BI__builtin_hlsl_wave_active_all_true: {
972 assert(Op->
getType()->isIntegerTy(1) &&
973 "Intrinsic WaveActiveAllTrue operand must be a bool");
975 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveActiveAllTrueIntrinsic();
977 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID), {Op});
979 case Builtin::BI__builtin_hlsl_wave_active_any_true: {
981 assert(Op->
getType()->isIntegerTy(1) &&
982 "Intrinsic WaveActiveAnyTrue operand must be a bool");
984 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic();
986 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID), {Op});
988 case Builtin::BI__builtin_hlsl_wave_active_ballot: {
990 assert(Op->
getType()->isIntegerTy(1) &&
991 "Intrinsic WaveActiveBallot operand must be a bool");
995 case Builtin::BI__builtin_hlsl_wave_active_count_bits: {
997 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveActiveCountBitsIntrinsic();
999 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID),
1002 case Builtin::BI__builtin_hlsl_wave_active_sum: {
1006 getTarget().getTriple().getArch(),
CGM.getHLSLRuntime(),
1010 &
CGM.getModule(), IID, {OpExpr->getType()}),
1011 ArrayRef{OpExpr},
"hlsl.wave.active.sum");
1013 case Builtin::BI__builtin_hlsl_wave_active_max: {
1017 getTarget().getTriple().getArch(),
CGM.getHLSLRuntime(),
1021 &
CGM.getModule(), IID, {OpExpr->getType()}),
1022 ArrayRef{OpExpr},
"hlsl.wave.active.max");
1024 case Builtin::BI__builtin_hlsl_wave_active_min: {
1028 getTarget().getTriple().getArch(),
CGM.getHLSLRuntime(),
1032 &
CGM.getModule(), IID, {OpExpr->getType()}),
1033 ArrayRef{OpExpr},
"hlsl.wave.active.min");
1035 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
1039 switch (
CGM.getTarget().getTriple().getArch()) {
1040 case llvm::Triple::dxil:
1042 &
CGM.getModule(), Intrinsic::dx_wave_getlaneindex));
1043 case llvm::Triple::spirv:
1045 llvm::FunctionType::get(
IntTy, {},
false),
1046 "__hlsl_wave_get_lane_index", {},
false,
true));
1049 "Intrinsic WaveGetLaneIndex not supported by target architecture");
1052 case Builtin::BI__builtin_hlsl_wave_is_first_lane: {
1053 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveIsFirstLaneIntrinsic();
1055 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID));
1057 case Builtin::BI__builtin_hlsl_wave_get_lane_count: {
1058 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveGetLaneCountIntrinsic();
1060 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID));
1062 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
1068 Intrinsic::getOrInsertDeclaration(
1069 &
CGM.getModule(),
CGM.getHLSLRuntime().getWaveReadLaneAtIntrinsic(),
1070 {OpExpr->getType()}),
1071 ArrayRef{OpExpr, OpIndex},
"hlsl.wave.readlane");
1073 case Builtin::BI__builtin_hlsl_elementwise_sign: {
1074 auto *Arg0 = E->
getArg(0);
1076 llvm::Type *Xty = Op0->
getType();
1077 llvm::Type *retType = llvm::Type::getInt32Ty(this->
getLLVMContext());
1078 if (Xty->isVectorTy()) {
1079 auto *XVecTy = Arg0->getType()->castAs<
VectorType>();
1080 retType = llvm::VectorType::get(
1081 retType, ElementCount::getFixed(XVecTy->getNumElements()));
1083 assert((Arg0->getType()->hasFloatingRepresentation() ||
1084 Arg0->getType()->hasIntegerRepresentation()) &&
1085 "sign operand must have a float or int representation");
1087 if (Arg0->getType()->hasUnsignedIntegerRepresentation()) {
1088 Value *Cmp =
Builder.CreateICmpEQ(Op0, ConstantInt::get(Xty, 0));
1089 return Builder.CreateSelect(Cmp, ConstantInt::get(retType, 0),
1090 ConstantInt::get(retType, 1),
"hlsl.sign");
1093 return Builder.CreateIntrinsic(
1094 retType,
CGM.getHLSLRuntime().getSignIntrinsic(),
1097 case Builtin::BI__builtin_hlsl_elementwise_radians: {
1100 "radians operand must have a float representation");
1101 return Builder.CreateIntrinsic(
1104 nullptr,
"hlsl.radians");
1106 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
1110 return Builder.CreateIntrinsic(
1112 CGM.getHLSLRuntime().getBufferUpdateCounterIntrinsic(),
1115 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
1120 "asuint operands types mismatch");
1123 case Builtin::BI__builtin_hlsl_elementwise_clip:
1125 "clip operands types mismatch");
1127 case Builtin::BI__builtin_hlsl_group_memory_barrier_with_group_sync: {
1129 CGM.getHLSLRuntime().getGroupMemoryBarrierWithGroupSyncIntrinsic();
1131 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID));
1133 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse: {
1136 llvm_unreachable(
"ddx_coarse operand must have a float representation");
1137 Intrinsic::ID ID =
CGM.getHLSLRuntime().getDdxCoarseIntrinsic();
1142 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse: {
1145 llvm_unreachable(
"ddy_coarse operand must have a float representation");
1146 Intrinsic::ID ID =
CGM.getHLSLRuntime().getDdyCoarseIntrinsic();
1151 case Builtin::BI__builtin_hlsl_elementwise_ddx_fine: {
1154 llvm_unreachable(
"ddx_fine operand must have a float representation");
1155 Intrinsic::ID ID =
CGM.getHLSLRuntime().getDdxFineIntrinsic();
1160 case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
1163 llvm_unreachable(
"ddy_fine operand must have a float representation");
1164 Intrinsic::ID ID =
CGM.getHLSLRuntime().getDdyFineIntrinsic();
1169 case Builtin::BI__builtin_get_spirv_spec_constant_bool:
1170 case Builtin::BI__builtin_get_spirv_spec_constant_short:
1171 case Builtin::BI__builtin_get_spirv_spec_constant_ushort:
1172 case Builtin::BI__builtin_get_spirv_spec_constant_int:
1173 case Builtin::BI__builtin_get_spirv_spec_constant_uint:
1174 case Builtin::BI__builtin_get_spirv_spec_constant_longlong:
1175 case Builtin::BI__builtin_get_spirv_spec_constant_ulonglong:
1176 case Builtin::BI__builtin_get_spirv_spec_constant_half:
1177 case Builtin::BI__builtin_get_spirv_spec_constant_float:
1178 case Builtin::BI__builtin_get_spirv_spec_constant_double: {
1182 llvm::Value *Args[] = {SpecId, DefaultVal};
1183 return Builder.CreateCall(SpecConstantFn, Args);