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_resource_counterhandlefromimplicitbinding: {
357 if (!
CGM.getTriple().isSPIRV())
360 llvm::Type *HandleTy =
CGM.getTypes().ConvertType(E->
getType());
363 llvm::Intrinsic::ID IntrinsicID =
364 llvm::Intrinsic::spv_resource_counterhandlefromimplicitbinding;
366 return Builder.CreateIntrinsic(HandleTy, IntrinsicID, Args);
368 case Builtin::BI__builtin_hlsl_resource_nonuniformindex: {
371 return Builder.CreateIntrinsic(
372 RetTy,
CGM.getHLSLRuntime().getNonUniformResourceIndexIntrinsic(),
375 case Builtin::BI__builtin_hlsl_all: {
377 return Builder.CreateIntrinsic(
382 case Builtin::BI__builtin_hlsl_and: {
385 return Builder.CreateAnd(Op0, Op1,
"hlsl.and");
387 case Builtin::BI__builtin_hlsl_or: {
390 return Builder.CreateOr(Op0, Op1,
"hlsl.or");
392 case Builtin::BI__builtin_hlsl_any: {
394 return Builder.CreateIntrinsic(
399 case Builtin::BI__builtin_hlsl_asdouble:
401 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
408 Ty = VecTy->getElementType();
412 Intr =
CGM.getHLSLRuntime().getNClampIntrinsic();
414 Intr =
CGM.getHLSLRuntime().getUClampIntrinsic();
417 Intr =
CGM.getHLSLRuntime().getSClampIntrinsic();
419 return Builder.CreateIntrinsic(
423 case Builtin::BI__builtin_hlsl_crossf16:
424 case Builtin::BI__builtin_hlsl_crossf32: {
429 "cross operands must have a float representation");
434 "input vectors must have 3 elements each");
435 return Builder.CreateIntrinsic(
436 Op0->
getType(),
CGM.getHLSLRuntime().getCrossIntrinsic(),
439 case Builtin::BI__builtin_hlsl_dot: {
442 llvm::Type *T0 = Op0->
getType();
443 llvm::Type *T1 = Op1->
getType();
446 if (!T0->isVectorTy() && !T1->isVectorTy()) {
447 if (T0->isFloatingPointTy())
448 return Builder.CreateFMul(Op0, Op1,
"hlsl.dot");
450 if (T0->isIntegerTy())
451 return Builder.CreateMul(Op0, Op1,
"hlsl.dot");
454 "Scalar dot product is only supported on ints and floats.");
459 "Dot product operands must have the same type.");
462 assert(VecTy0 &&
"Dot product argument must be a vector.");
464 return Builder.CreateIntrinsic(
469 case Builtin::BI__builtin_hlsl_dot4add_i8packed: {
474 Intrinsic::ID ID =
CGM.getHLSLRuntime().getDot4AddI8PackedIntrinsic();
477 return Builder.CreateIntrinsic(
479 nullptr,
"hlsl.dot4add.i8packed");
481 case Builtin::BI__builtin_hlsl_dot4add_u8packed: {
486 Intrinsic::ID ID =
CGM.getHLSLRuntime().getDot4AddU8PackedIntrinsic();
489 return Builder.CreateIntrinsic(
491 nullptr,
"hlsl.dot4add.u8packed");
493 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: {
496 return Builder.CreateIntrinsic(
501 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
504 return Builder.CreateIntrinsic(
507 nullptr,
"hlsl.firstbitlow");
509 case Builtin::BI__builtin_hlsl_lerp: {
514 llvm_unreachable(
"lerp operand must have a float representation");
515 return Builder.CreateIntrinsic(
516 X->getType(),
CGM.getHLSLRuntime().getLerpIntrinsic(),
519 case Builtin::BI__builtin_hlsl_normalize: {
523 "normalize operand must have a float representation");
525 return Builder.CreateIntrinsic(
528 nullptr,
"hlsl.normalize");
530 case Builtin::BI__builtin_hlsl_elementwise_degrees: {
534 "degree operand must have a float representation");
536 return Builder.CreateIntrinsic(
537 X->getType(),
CGM.getHLSLRuntime().getDegreesIntrinsic(),
540 case Builtin::BI__builtin_hlsl_elementwise_frac: {
543 llvm_unreachable(
"frac operand must have a float representation");
544 return Builder.CreateIntrinsic(
545 Op0->
getType(),
CGM.getHLSLRuntime().getFracIntrinsic(),
548 case Builtin::BI__builtin_hlsl_elementwise_isinf: {
550 llvm::Type *Xty = Op0->
getType();
551 llvm::Type *retType = llvm::Type::getInt1Ty(this->
getLLVMContext());
552 if (Xty->isVectorTy()) {
554 retType = llvm::VectorType::get(
555 retType, ElementCount::getFixed(XVecTy->getNumElements()));
558 llvm_unreachable(
"isinf operand must have a float representation");
559 return Builder.CreateIntrinsic(
560 retType,
CGM.getHLSLRuntime().getIsInfIntrinsic(),
563 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
565 llvm::Type *Xty = Op0->
getType();
566 llvm::Type *retType = llvm::Type::getInt1Ty(this->
getLLVMContext());
567 if (Xty->isVectorTy()) {
569 retType = llvm::VectorType::get(
570 retType, ElementCount::getFixed(XVecTy->getNumElements()));
573 llvm_unreachable(
"isnan operand must have a float representation");
574 return Builder.CreateIntrinsic(
575 retType,
CGM.getHLSLRuntime().getIsNaNIntrinsic(),
578 case Builtin::BI__builtin_hlsl_mad: {
583 return Builder.CreateIntrinsic(
584 M->
getType(), Intrinsic::fmuladd,
588 if (
CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil)
589 return Builder.CreateIntrinsic(
590 M->
getType(), Intrinsic::dx_imad,
594 return Builder.CreateNSWAdd(Mul, B);
597 if (
CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil)
598 return Builder.CreateIntrinsic(
599 M->
getType(), Intrinsic::dx_umad,
603 return Builder.CreateNUWAdd(Mul, B);
605 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
608 llvm_unreachable(
"rcp operand must have a float representation");
609 llvm::Type *Ty = Op0->
getType();
610 llvm::Type *EltTy = Ty->getScalarType();
611 Constant *One = Ty->isVectorTy()
612 ? ConstantVector::getSplat(
613 ElementCount::getFixed(
615 ConstantFP::get(EltTy, 1.0))
616 : ConstantFP::get(EltTy, 1.0);
617 return Builder.CreateFDiv(One, Op0,
"hlsl.rcp");
619 case Builtin::BI__builtin_hlsl_elementwise_rsqrt: {
622 llvm_unreachable(
"rsqrt operand must have a float representation");
623 return Builder.CreateIntrinsic(
624 Op0->
getType(),
CGM.getHLSLRuntime().getRsqrtIntrinsic(),
627 case Builtin::BI__builtin_hlsl_elementwise_saturate: {
630 "saturate operand must have a float representation");
631 return Builder.CreateIntrinsic(
634 nullptr,
"hlsl.saturate");
636 case Builtin::BI__builtin_hlsl_select: {
649 if (!OpTrue->
getType()->isVectorTy())
651 Builder.CreateVectorSplat(VTy->getNumElements(), OpTrue,
"splat");
652 if (!OpFalse->
getType()->isVectorTy())
654 Builder.CreateVectorSplat(VTy->getNumElements(), OpFalse,
"splat");
658 Builder.CreateSelect(OpCond, OpTrue, OpFalse,
"hlsl.select");
665 case Builtin::BI__builtin_hlsl_step: {
670 "step operands must have a float representation");
671 return Builder.CreateIntrinsic(
672 Op0->
getType(),
CGM.getHLSLRuntime().getStepIntrinsic(),
675 case Builtin::BI__builtin_hlsl_wave_active_all_true: {
677 assert(Op->
getType()->isIntegerTy(1) &&
678 "Intrinsic WaveActiveAllTrue operand must be a bool");
680 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveActiveAllTrueIntrinsic();
682 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID), {Op});
684 case Builtin::BI__builtin_hlsl_wave_active_any_true: {
686 assert(Op->
getType()->isIntegerTy(1) &&
687 "Intrinsic WaveActiveAnyTrue operand must be a bool");
689 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic();
691 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID), {Op});
693 case Builtin::BI__builtin_hlsl_wave_active_count_bits: {
695 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveActiveCountBitsIntrinsic();
697 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID),
700 case Builtin::BI__builtin_hlsl_wave_active_sum: {
704 getTarget().getTriple().getArch(),
CGM.getHLSLRuntime(),
708 &
CGM.getModule(), IID, {OpExpr->getType()}),
709 ArrayRef{OpExpr},
"hlsl.wave.active.sum");
711 case Builtin::BI__builtin_hlsl_wave_active_max: {
715 getTarget().getTriple().getArch(),
CGM.getHLSLRuntime(),
719 &
CGM.getModule(), IID, {OpExpr->getType()}),
720 ArrayRef{OpExpr},
"hlsl.wave.active.max");
722 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
726 switch (
CGM.getTarget().getTriple().getArch()) {
727 case llvm::Triple::dxil:
729 &
CGM.getModule(), Intrinsic::dx_wave_getlaneindex));
730 case llvm::Triple::spirv:
732 llvm::FunctionType::get(
IntTy, {},
false),
733 "__hlsl_wave_get_lane_index", {},
false,
true));
736 "Intrinsic WaveGetLaneIndex not supported by target architecture");
739 case Builtin::BI__builtin_hlsl_wave_is_first_lane: {
740 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveIsFirstLaneIntrinsic();
742 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID));
744 case Builtin::BI__builtin_hlsl_wave_get_lane_count: {
745 Intrinsic::ID ID =
CGM.getHLSLRuntime().getWaveGetLaneCountIntrinsic();
747 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID));
749 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
755 Intrinsic::getOrInsertDeclaration(
756 &
CGM.getModule(),
CGM.getHLSLRuntime().getWaveReadLaneAtIntrinsic(),
757 {OpExpr->getType()}),
758 ArrayRef{OpExpr, OpIndex},
"hlsl.wave.readlane");
760 case Builtin::BI__builtin_hlsl_elementwise_sign: {
761 auto *Arg0 = E->
getArg(0);
763 llvm::Type *Xty = Op0->
getType();
764 llvm::Type *retType = llvm::Type::getInt32Ty(this->
getLLVMContext());
765 if (Xty->isVectorTy()) {
766 auto *XVecTy = Arg0->getType()->castAs<
VectorType>();
767 retType = llvm::VectorType::get(
768 retType, ElementCount::getFixed(XVecTy->getNumElements()));
770 assert((Arg0->getType()->hasFloatingRepresentation() ||
771 Arg0->getType()->hasIntegerRepresentation()) &&
772 "sign operand must have a float or int representation");
774 if (Arg0->getType()->hasUnsignedIntegerRepresentation()) {
775 Value *Cmp =
Builder.CreateICmpEQ(Op0, ConstantInt::get(Xty, 0));
776 return Builder.CreateSelect(Cmp, ConstantInt::get(retType, 0),
777 ConstantInt::get(retType, 1),
"hlsl.sign");
780 return Builder.CreateIntrinsic(
781 retType,
CGM.getHLSLRuntime().getSignIntrinsic(),
784 case Builtin::BI__builtin_hlsl_elementwise_radians: {
787 "radians operand must have a float representation");
788 return Builder.CreateIntrinsic(
791 nullptr,
"hlsl.radians");
793 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
797 return Builder.CreateIntrinsic(
799 CGM.getHLSLRuntime().getBufferUpdateCounterIntrinsic(),
802 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
807 "asuint operands types mismatch");
810 case Builtin::BI__builtin_hlsl_elementwise_clip:
812 "clip operands types mismatch");
814 case Builtin::BI__builtin_hlsl_group_memory_barrier_with_group_sync: {
816 CGM.getHLSLRuntime().getGroupMemoryBarrierWithGroupSyncIntrinsic();
818 Intrinsic::getOrInsertDeclaration(&
CGM.getModule(), ID));
820 case Builtin::BI__builtin_get_spirv_spec_constant_bool:
821 case Builtin::BI__builtin_get_spirv_spec_constant_short:
822 case Builtin::BI__builtin_get_spirv_spec_constant_ushort:
823 case Builtin::BI__builtin_get_spirv_spec_constant_int:
824 case Builtin::BI__builtin_get_spirv_spec_constant_uint:
825 case Builtin::BI__builtin_get_spirv_spec_constant_longlong:
826 case Builtin::BI__builtin_get_spirv_spec_constant_ulonglong:
827 case Builtin::BI__builtin_get_spirv_spec_constant_half:
828 case Builtin::BI__builtin_get_spirv_spec_constant_float:
829 case Builtin::BI__builtin_get_spirv_spec_constant_double: {
833 llvm::Value *Args[] = {SpecId, DefaultVal};
834 return Builder.CreateCall(SpecConstantFn, Args);