LLVM: lib/Target/DirectX/DXILIntrinsicExpansion.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
24#include "llvm/IR/IntrinsicsDirectX.h"
32
33#define DEBUG_TYPE "dxil-intrinsic-expansion"
34
35using namespace llvm;
36
38
39public:
42
44};
45
47 bool IsRaw) {
48 if (IsRaw && M->getTargetTriple().getDXILVersion() > VersionTuple(1, 2))
49 return false;
50
53}
54
57 if (M->getTargetTriple().getDXILVersion() >= VersionTuple(1, 9))
58 return nullptr;
59
62 if (!ValTy->getScalarType()->isHalfTy())
63 return nullptr;
64
68 ValTy->isVectorTy()
72 ConstantInt::get(IType, 0x7c00))
73 : ConstantInt::get(IType, 0x7c00);
74
76 ValTy->isVectorTy()
80 ConstantInt::get(IType, 0xfc00))
81 : ConstantInt::get(IType, 0xfc00);
82
83 Value *IVal = Builder.CreateBitCast(Val, PosInf->getType());
84 Value *B1 = Builder.CreateICmpEQ(IVal, PosInf);
85 Value *B2 = Builder.CreateICmpEQ(IVal, NegInf);
86 Value *B3 = Builder.CreateOr(B1, B2);
87 return B3;
88}
89
92 if (M->getTargetTriple().getDXILVersion() >= VersionTuple(1, 9))
93 return nullptr;
94
97 if (!ValTy->getScalarType()->isHalfTy())
98 return nullptr;
99
102
104 ValTy->isVectorTy()
108 ConstantInt::get(IType, 0x7c00))
109 : ConstantInt::get(IType, 0x7c00);
111 ValTy->isVectorTy()
115 ConstantInt::get(IType, 0x3ff))
116 : ConstantInt::get(IType, 0x3ff);
117
119 ValTy->isVectorTy()
123 ConstantInt::get(IType, 0))
124 : ConstantInt::get(IType, 0);
125
126 Value *IVal = Builder.CreateBitCast(Val, ExpBitMask->getType());
127 Value *Exp = Builder.CreateAnd(IVal, ExpBitMask);
128 Value *B1 = Builder.CreateICmpEQ(Exp, ExpBitMask);
129
130 Value *Sig = Builder.CreateAnd(IVal, SigBitMask);
131 Value *B2 = Builder.CreateICmpNE(Sig, Zero);
132 Value *B3 = Builder.CreateAnd(B1, B2);
133 return B3;
134}
135
138 if (M->getTargetTriple().getDXILVersion() >= VersionTuple(1, 9))
139 return nullptr;
140
143 if (!ValTy->getScalarType()->isHalfTy())
144 return nullptr;
145
148
150 ValTy->isVectorTy()
154 ConstantInt::get(IType, 0x7c00))
155 : ConstantInt::get(IType, 0x7c00);
156
157 Value *IVal = Builder.CreateBitCast(Val, ExpBitMask->getType());
158 Value *Exp = Builder.CreateAnd(IVal, ExpBitMask);
159 Value *B1 = Builder.CreateICmpNE(Exp, ExpBitMask);
160 return B1;
161}
162
165 if (M->getTargetTriple().getDXILVersion() >= VersionTuple(1, 9))
166 return nullptr;
167
170 if (!ValTy->getScalarType()->isHalfTy())
171 return nullptr;
172
175
177 ValTy->isVectorTy()
181 ConstantInt::get(IType, 0x7c00))
182 : ConstantInt::get(IType, 0x7c00);
184 ValTy->isVectorTy()
188 ConstantInt::get(IType, 0))
189 : ConstantInt::get(IType, 0);
190
191 Value *IVal = Builder.CreateBitCast(Val, ExpBitMask->getType());
192 Value *Exp = Builder.CreateAnd(IVal, ExpBitMask);
193 Value *NotAllZeroes = Builder.CreateICmpNE(Exp, Zero);
194 Value *NotAllOnes = Builder.CreateICmpNE(Exp, ExpBitMask);
195 Value *B1 = Builder.CreateAnd(NotAllZeroes, NotAllOnes);
196 return B1;
197}
198
200 switch (F.getIntrinsicID()) {
201 case Intrinsic::assume:
202 case Intrinsic::abs:
203 case Intrinsic::atan2:
204 case Intrinsic::fshl:
205 case Intrinsic::fshr:
206 case Intrinsic::exp:
207 case Intrinsic::is_fpclass:
208 case Intrinsic:🪵
209 case Intrinsic::log10:
210 case Intrinsic::pow:
211 case Intrinsic::powi:
212 case Intrinsic::dx_all:
213 case Intrinsic::dx_any:
214 case Intrinsic::dx_cross:
215 case Intrinsic::dx_uclamp:
216 case Intrinsic::dx_sclamp:
217 case Intrinsic::dx_nclamp:
218 case Intrinsic::dx_degrees:
219 case Intrinsic::dx_isinf:
220 case Intrinsic::dx_isnan:
221 case Intrinsic::dx_lerp:
222 case Intrinsic::dx_normalize:
223 case Intrinsic::dx_fdot:
224 case Intrinsic::dx_sdot:
225 case Intrinsic::dx_udot:
226 case Intrinsic::dx_sign:
227 case Intrinsic::dx_step:
228 case Intrinsic::dx_radians:
229 case Intrinsic::usub_sat:
230 case Intrinsic::vector_reduce_add:
231 case Intrinsic::vector_reduce_fadd:
232 return true;
233 case Intrinsic::dx_resource_load_rawbuffer:
235 F.getParent(), F.getReturnType()->getStructElementType(0),
236 true);
237 case Intrinsic::dx_resource_load_typedbuffer:
239 F.getParent(), F.getReturnType()->getStructElementType(0),
240 false);
241 case Intrinsic::dx_resource_store_rawbuffer:
243 F.getParent(), F.getFunctionType()->getParamType(3), true);
244 case Intrinsic::dx_resource_store_typedbuffer:
246 F.getParent(), F.getFunctionType()->getParamType(2), false);
247 }
248 return false;
249}
250
255
257
258 Value *Cmp = Builder.CreateICmpULT(A, B, "usub.cmp");
259 Value *Sub = Builder.CreateSub(A, B, "usub.sub");
260 Value *Zero = ConstantInt::get(Ty, 0);
261 return Builder.CreateSelect(Cmp, Zero, Sub, "usub.sat");
262}
263
265 assert(IntrinsicId == Intrinsic::vector_reduce_add ||
266 IntrinsicId == Intrinsic::vector_reduce_fadd);
267
269 bool IsFAdd = (IntrinsicId == Intrinsic::vector_reduce_fadd);
270
274 unsigned XVecSize = XVec->getNumElements();
275 Value *Sum = Builder.CreateExtractElement(X, static_cast<uint64_t>(0));
276
277
278 if (IsFAdd) {
280 if (StartValue && !StartValue->isZeroValue())
281 Sum = Builder.CreateFAdd(Sum, StartValue);
282 }
283
284
285 for (unsigned I = 1; I < XVecSize; I++) {
286 Value *Elt = Builder.CreateExtractElement(X, I);
287 if (IsFAdd)
288 Sum = Builder.CreateFAdd(Sum, Elt);
289 else
290 Sum = Builder.CreateAdd(Sum, Elt);
291 }
292
293 return Sum;
294}
295
301 Constant *Zero = Ty->isVectorTy()
305 ConstantInt::get(EltTy, 0))
306 : ConstantInt::get(EltTy, 0);
307 auto *V = Builder.CreateSub(Zero, X);
308 return Builder.CreateIntrinsic(Ty, Intrinsic::smax, {X, V}, nullptr,
309 "dx.max");
310}
311
313
317
321
322 Value *op0_x = Builder.CreateExtractElement(op0, (uint64_t)0, "x0");
323 Value *op0_y = Builder.CreateExtractElement(op0, 1, "x1");
324 Value *op0_z = Builder.CreateExtractElement(op0, 2, "x2");
325
326 Value *op1_x = Builder.CreateExtractElement(op1, (uint64_t)0, "y0");
327 Value *op1_y = Builder.CreateExtractElement(op1, 1, "y1");
328 Value *op1_z = Builder.CreateExtractElement(op1, 2, "y2");
329
331 Value *xy = Builder.CreateFMul(x0, y1);
332 Value *yx = Builder.CreateFMul(y0, x1);
333 return Builder.CreateFSub(xy, yx, Orig->getName());
334 };
335
336 Value *yz_zy = MulSub(op0_y, op0_z, op1_y, op1_z);
337 Value *zx_xz = MulSub(op0_z, op0_x, op1_z, op1_x);
338 Value *xy_yx = MulSub(op0_x, op0_y, op1_x, op1_y);
339
341 cross = Builder.CreateInsertElement(cross, yz_zy, (uint64_t)0);
342 cross = Builder.CreateInsertElement(cross, zx_xz, 1);
343 cross = Builder.CreateInsertElement(cross, xy_yx, 2);
344 return cross;
345}
346
347
348
349
352 [[maybe_unused]] Type *BTy = B->getType();
354
356
358
360
362 int NumElts = AVec->getNumElements();
363 switch (NumElts) {
364 case 2:
365 DotIntrinsic = Intrinsic::dx_dot2;
366 break;
367 case 3:
368 DotIntrinsic = Intrinsic::dx_dot3;
369 break;
370 case 4:
371 DotIntrinsic = Intrinsic::dx_dot4;
372 break;
373 default:
375 "Invalid dot product input vector: length is outside 2-4");
376 return nullptr;
377 }
378
380 for (int I = 0; I < NumElts; ++I)
381 Args.push_back(Builder.CreateExtractElement(A, Builder.getInt32(I)));
382 for (int I = 0; I < NumElts; ++I)
383 Args.push_back(Builder.CreateExtractElement(B, Builder.getInt32(I)));
384 return Builder.CreateIntrinsic(ATy->getScalarType(), DotIntrinsic, Args,
385 nullptr, "dot");
386}
387
388
389
390
395
396
399 assert(DotIntrinsic == Intrinsic::dx_sdot ||
400 DotIntrinsic == Intrinsic::dx_udot);
404 [[maybe_unused]] Type *BTy = B->getType();
406
408
410
412
414 Intrinsic::ID MadIntrinsic = DotIntrinsic == Intrinsic::dx_sdot
415 ? Intrinsic::dx_imad
416 : Intrinsic::dx_umad;
417 Value *Elt0 = Builder.CreateExtractElement(A, (uint64_t)0);
418 Value *Elt1 = Builder.CreateExtractElement(B, (uint64_t)0);
419 Result = Builder.CreateMul(Elt0, Elt1);
420 for (unsigned I = 1; I < AVec->getNumElements(); I++) {
421 Elt0 = Builder.CreateExtractElement(A, I);
422 Elt1 = Builder.CreateExtractElement(B, I);
423 Result = Builder.CreateIntrinsic(Result->getType(), MadIntrinsic,
425 nullptr, "dx.mad");
426 }
427 return Result;
428}
429
441 Value *NewX = Builder.CreateFMul(Log2eConst, X);
442 auto *Exp2Call =
443 Builder.CreateIntrinsic(Ty, Intrinsic::exp2, {NewX}, nullptr, "dx.exp2");
444 Exp2Call->setTailCall(Orig->isTailCall());
446 return Exp2Call;
447}
448
452
453
454
455 switch (TCI->getZExtValue()) {
464 }
465
467
470 unsigned FNumElem = 0;
471
472 unsigned BitWidth;
473 Type *BitCastTy;
474
476 Type *ElemTy = FVecTy->getElementType();
477 FNumElem = FVecTy->getNumElements();
478 BitWidth = ElemTy->getPrimitiveSizeInBits();
480 } else {
483 }
484
485 Value *FBitCast = Builder.CreateBitCast(F, BitCastTy);
486 switch (TCI->getZExtValue()) {
489 ConstantInt::get(Builder.getIntNTy(BitWidth), 1 << (BitWidth - 1));
491 if (FNumElem) {
492 Value *NegZeroSplat = Builder.CreateVectorSplat(FNumElem, NegZero);
493 RetVal =
494 Builder.CreateICmpEQ(FBitCast, NegZeroSplat, "is.fpclass.negzero");
495 } else
496 RetVal = Builder.CreateICmpEQ(FBitCast, NegZero, "is.fpclass.negzero");
497 return RetVal;
498 }
499 default:
501 }
502}
503
510
513 if (IntrinsicId == Intrinsic::dx_any)
514 return Builder.CreateOr(Result, Elt);
515 assert(IntrinsicId == Intrinsic::dx_all);
516 return Builder.CreateAnd(Result, Elt);
517 };
518
519 Value *Result = nullptr;
520 if (!Ty->isVectorTy()) {
522 ? Builder.CreateFCmpUNE(X, ConstantFP::get(EltTy, 0))
523 : Builder.CreateICmpNE(X, ConstantInt::get(EltTy, 0));
524 } else {
528 ? Builder.CreateFCmpUNE(
531 ConstantFP::get(EltTy, 0)))
532 : Builder.CreateICmpNE(
535 ConstantInt::get(EltTy, 0)));
536 Result = Builder.CreateExtractElement(Cond, (uint64_t)0);
537 for (unsigned I = 1; I < XVec->getNumElements(); I++) {
538 Value *Elt = Builder.CreateExtractElement(Cond, I);
539 Result = ApplyOp(IntrinsicId, Result, Elt);
540 }
541 }
542 return Result;
543}
544
550 auto *V = Builder.CreateFSub(Y, X);
551 V = Builder.CreateFMul(S, V);
552 return Builder.CreateFAdd(X, V, "dx.lerp");
553}
554
565 ConstantFP::get(EltTy, LogConstVal))
566 : ConstantFP::get(EltTy, LogConstVal);
567 auto *Log2Call =
568 Builder.CreateIntrinsic(Ty, Intrinsic::log2, {X}, nullptr, "elt.log2");
569 Log2Call->setTailCall(Orig->isTailCall());
571 return Builder.CreateFMul(Ln2Const, Log2Call);
572}
576
577
578
584
586 if (!XVec) {
588 const APFloat &fpVal = constantFP->getValueAPF();
591 }
592 return Builder.CreateFDiv(X, X);
593 }
594
596
597
598
600 const APFloat &fpVal = constantFP->getValueAPF();
603 }
604
605 Value *Multiplicand = Builder.CreateIntrinsic(EltTy, Intrinsic::dx_rsqrt,
607 nullptr, "dx.rsqrt");
608
609 Value *MultiplicandVec =
610 Builder.CreateVectorSplat(XVec->getNumElements(), Multiplicand);
611 return Builder.CreateFMul(X, MultiplicandVec);
612}
613
620
621 Value *Tan = Builder.CreateFDiv(Y, X);
622
624 Builder.CreateIntrinsic(Ty, Intrinsic::atan, {Tan}, nullptr, "Elt.Atan");
627
628
632 Constant *Zero = ConstantFP::get(Ty, 0);
633 Value *AtanAddPi = Builder.CreateFAdd(Atan, Pi);
634 Value *AtanSubPi = Builder.CreateFSub(Atan, Pi);
635
636
637 Value *Result = Atan;
638 Value *XLt0 = Builder.CreateFCmpOLT(X, Zero);
639 Value *XEq0 = Builder.CreateFCmpOEQ(X, Zero);
640 Value *YGe0 = Builder.CreateFCmpOGE(Y, Zero);
641 Value *YLt0 = Builder.CreateFCmpOLT(Y, Zero);
642
643
644 Value *XLt0AndYGe0 = Builder.CreateAnd(XLt0, YGe0);
645 Result = Builder.CreateSelect(XLt0AndYGe0, AtanAddPi, Result);
646
647
648 Value *XLt0AndYLt0 = Builder.CreateAnd(XLt0, YLt0);
649 Result = Builder.CreateSelect(XLt0AndYLt0, AtanSubPi, Result);
650
651
652 Value *XEq0AndYLt0 = Builder.CreateAnd(XEq0, YLt0);
653 Result = Builder.CreateSelect(XEq0AndYLt0, NegHalfPi, Result);
654
655
656 Value *XEq0AndYGe0 = Builder.CreateAnd(XEq0, YGe0);
657 Result = Builder.CreateSelect(XEq0AndYGe0, HalfPi, Result);
658
659 return Result;
660}
661
662template
668
670
671 unsigned BitWidth = Ty->getScalarSizeInBits();
673 "Can't use Mask to compute modulo and inverse");
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688 Constant *Mask = ConstantInt::get(Ty, Ty->getScalarSizeInBits() - 1);
689
690
691
692
693 Value *MaskedShift = Builder.CreateAnd(Shift, Mask);
694
695
696
697
698 Value *NotShift = Builder.CreateNot(Shift);
699 Value *InverseShift = Builder.CreateAnd(NotShift, Mask);
700
701 Constant *One = ConstantInt::get(Ty, 1);
704
705 if (LeftFunnel) {
706 ShiftedA = Builder.CreateShl(A, MaskedShift);
707 Value *ShiftB1 = Builder.CreateLShr(B, One);
708 ShiftedB = Builder.CreateLShr(ShiftB1, InverseShift);
709 } else {
710 Value *ShiftA1 = Builder.CreateShl(A, One);
711 ShiftedA = Builder.CreateShl(ShiftA1, InverseShift);
712 ShiftedB = Builder.CreateLShr(B, MaskedShift);
713 }
714
715 Value *Result = Builder.CreateOr(ShiftedA, ShiftedB);
716 return Result;
717}
718
720
725
726 if (IntrinsicId == Intrinsic::powi)
727 Y = Builder.CreateSIToFP(Y, Ty);
728
729 auto *Log2Call =
730 Builder.CreateIntrinsic(Ty, Intrinsic::log2, {X}, nullptr, "elt.log2");
731 auto *Mul = Builder.CreateFMul(Log2Call, Y);
732 auto *Exp2Call =
733 Builder.CreateIntrinsic(Ty, Intrinsic::exp2, {Mul}, nullptr, "elt.exp2");
734 Exp2Call->setTailCall(Orig->isTailCall());
736 return Exp2Call;
737}
738
740
745
746 Constant *One = ConstantFP::get(Ty->getScalarType(), 1.0);
747 Constant *Zero = ConstantFP::get(Ty->getScalarType(), 0.0);
748 Value *Cond = Builder.CreateFCmpOLT(Y, X);
749
750 if (Ty != Ty->getScalarType()) {
756 }
757
758 return Builder.CreateSelect(Cond, Zero, One);
759}
760
766 return Builder.CreateFMul(X, PiOver180);
767}
768
771
774 bool IsDouble = ScalarTy->isDoubleTy();
776 "Only expand double or int64 scalars or vectors");
777 bool IsVector = false;
778 unsigned ExtractNum = 2;
780 ExtractNum = 2 * VT->getNumElements();
781 IsVector = true;
782 assert(IsRaw || ExtractNum == 4 && "TypedBufferLoad vector must be size 2");
783 }
784
787 unsigned Base = 0;
788
789
790
791 while (ExtractNum > 0) {
792 unsigned LoadNum = std::min(ExtractNum, 4u);
794
796 Intrinsic::ID LoadIntrinsic = Intrinsic::dx_resource_load_typedbuffer;
798 if (IsRaw) {
799 LoadIntrinsic = Intrinsic::dx_resource_load_rawbuffer;
800 Value *Tmp = Builder.getInt32(4 * Base * 2);
801 Args.push_back(Builder.CreateAdd(Orig->getOperand(2), Tmp));
802 }
803
804 CallInst *Load = Builder.CreateIntrinsic(LoadType, LoadIntrinsic, Args);
806
807
808 Value *Extract = Builder.CreateExtractValue(Load, {0});
809
811 for (unsigned I = 0; I < LoadNum; ++I)
813 Builder.CreateExtractElement(Extract, Builder.getInt32(I)));
814
815
816 for (unsigned I = 0; I < LoadNum; I += 2) {
817 Value *Combined = nullptr;
818 if (IsDouble)
819
820 Combined = Builder.CreateIntrinsic(
821 Builder.getDoubleTy(), Intrinsic::dx_asdouble,
822 {ExtractElements[I], ExtractElements[I + 1]});
823 else {
824
825
827 Builder.CreateZExt(ExtractElements[I], Builder.getInt64Ty());
829 Builder.CreateZExt(ExtractElements[I + 1], Builder.getInt64Ty());
830
831 Value *ShiftedHi = Builder.CreateShl(Hi, Builder.getInt64(32));
832
833 Combined = Builder.CreateOr(Lo, ShiftedHi);
834 }
835
836 if (IsVector)
837 Result = Builder.CreateInsertElement(Result, Combined,
838 Builder.getInt32((I / 2) + Base));
839 else
840 Result = Combined;
841 }
842
843 ExtractNum -= LoadNum;
844 Base += LoadNum / 2;
845 }
846
847 Value *CheckBit = nullptr;
849
850
852 if (!EVI)
854
857
858 if (Indices[0] == 0) {
859
860 EVI->replaceAllUsesWith(Result);
861 } else {
862
863 assert(Indices[0] == 1 && "Unexpected type for typedbufferload");
864
865
866 if (!CheckBit) {
868 for (Value *L : Loads)
869 CheckBits.push_back(Builder.CreateExtractValue(L, {1}));
870 CheckBit = Builder.CreateAnd(CheckBits);
871 }
872 EVI->replaceAllUsesWith(CheckBit);
873 }
874 EVI->eraseFromParent();
875 }
877 return true;
878}
879
882
883 unsigned ValIndex = IsRaw ? 3 : 2;
886 bool IsDouble = ScalarTy->isDoubleTy();
888 "Only expand double or int64 scalars or vectors");
889
890
891 bool IsVector = false;
892 unsigned ExtractNum = 2;
893 unsigned VecLen = 0;
895 VecLen = VT->getNumElements();
896 assert(IsRaw || VecLen == 2 && "TypedBufferStore vector must be size 2");
897 ExtractNum = VecLen * 2;
898 IsVector = true;
899 }
900
901
905
907 if (IsVector)
908 SplitElementTy = VectorType::get(SplitElementTy, VecLen, false);
909
910 Value *LowBits = nullptr;
911 Value *HighBits = nullptr;
912
913 if (IsDouble) {
915 Value *Split = Builder.CreateIntrinsic(SplitTy, Intrinsic::dx_splitdouble,
917 LowBits = Builder.CreateExtractValue(Split, 0);
918 HighBits = Builder.CreateExtractValue(Split, 1);
919 } else {
920
922 Constant *ShiftAmt = Builder.getInt64(32);
923 if (IsVector)
924 ShiftAmt =
926
927
928 LowBits = Builder.CreateTrunc(InputVal, SplitElementTy);
929 Value *ShiftedVal = Builder.CreateLShr(InputVal, ShiftAmt);
930 HighBits = Builder.CreateTrunc(ShiftedVal, SplitElementTy);
931 }
932
933 if (IsVector) {
935 for (unsigned I = 0; I < VecLen; ++I) {
936 Mask.push_back(I);
937 Mask.push_back(I + VecLen);
938 }
939 Val = Builder.CreateShuffleVector(LowBits, HighBits, Mask);
940 } else {
941 Val = Builder.CreateInsertElement(Val, LowBits, Builder.getInt32(0));
942 Val = Builder.CreateInsertElement(Val, HighBits, Builder.getInt32(1));
943 }
944
945
946
947
948 unsigned Base = 0;
949 while (ExtractNum > 0) {
950 unsigned StoreNum = std::min(ExtractNum, 4u);
951
952 Intrinsic::ID StoreIntrinsic = Intrinsic::dx_resource_store_typedbuffer;
954 if (IsRaw) {
955 StoreIntrinsic = Intrinsic::dx_resource_store_rawbuffer;
956 Value *Tmp = Builder.getInt32(4 * Base);
957 Args.push_back(Builder.CreateAdd(Orig->getOperand(2), Tmp));
958 }
959
961 for (unsigned I = 0; I < StoreNum; ++I) {
963 }
964
965 Value *SubVal = Val;
966 if (VecLen > 2)
967 SubVal = Builder.CreateShuffleVector(Val, Mask);
968
969 Args.push_back(SubVal);
970
971 Builder.CreateIntrinsic(Builder.getVoidTy(), StoreIntrinsic, Args);
972
973 ExtractNum -= StoreNum;
974 Base += StoreNum;
975 }
977 return true;
978}
979
981 if (ClampIntrinsic == Intrinsic::dx_uclamp)
982 return Intrinsic::umax;
983 if (ClampIntrinsic == Intrinsic::dx_sclamp)
984 return Intrinsic::smax;
985 assert(ClampIntrinsic == Intrinsic::dx_nclamp);
986 return Intrinsic::maxnum;
987}
988
990 if (ClampIntrinsic == Intrinsic::dx_uclamp)
991 return Intrinsic::umin;
992 if (ClampIntrinsic == Intrinsic::dx_sclamp)
993 return Intrinsic::smin;
994 assert(ClampIntrinsic == Intrinsic::dx_nclamp);
995 return Intrinsic::minnum;
996}
997
1005 auto *MaxCall = Builder.CreateIntrinsic(Ty, getMaxForClamp(ClampIntrinsic),
1006 {X, Min}, nullptr, "dx.max");
1007 return Builder.CreateIntrinsic(Ty, getMinForClamp(ClampIntrinsic),
1008 {MaxCall, Max}, nullptr, "dx.min");
1009}
1010
1016 return Builder.CreateFMul(X, DegreesRatio);
1017}
1018
1025
1027
1031 GT = Builder.CreateFCmpOLT(Zero, X);
1032 LT = Builder.CreateFCmpOLT(X, Zero);
1033 } else {
1035 GT = Builder.CreateICmpSLT(Zero, X);
1036 LT = Builder.CreateICmpSLT(X, Zero);
1037 }
1038
1039 Value *ZextGT = Builder.CreateZExt(GT, RetTy);
1040 Value *ZextLT = Builder.CreateZExt(LT, RetTy);
1041
1042 return Builder.CreateSub(ZextGT, ZextLT);
1043}
1044
1046 Value *Result = nullptr;
1048 switch (IntrinsicId) {
1049 case Intrinsic::abs:
1051 break;
1052 case Intrinsic::assume:
1054 return true;
1055 case Intrinsic::atan2:
1057 break;
1058 case Intrinsic::fshl:
1060 break;
1061 case Intrinsic::fshr:
1063 break;
1064 case Intrinsic::exp:
1066 break;
1067 case Intrinsic::is_fpclass:
1069 break;
1070 case Intrinsic:🪵
1072 break;
1073 case Intrinsic::log10:
1075 break;
1076 case Intrinsic::pow:
1077 case Intrinsic::powi:
1079 break;
1080 case Intrinsic::dx_all:
1081 case Intrinsic::dx_any:
1083 break;
1084 case Intrinsic::dx_cross:
1086 break;
1087 case Intrinsic::dx_uclamp:
1088 case Intrinsic::dx_sclamp:
1089 case Intrinsic::dx_nclamp:
1091 break;
1092 case Intrinsic::dx_degrees:
1094 break;
1095 case Intrinsic::dx_isinf:
1097 break;
1098 case Intrinsic::dx_isnan:
1100 break;
1101 case Intrinsic::dx_lerp:
1103 break;
1104 case Intrinsic::dx_normalize:
1106 break;
1107 case Intrinsic::dx_fdot:
1109 break;
1110 case Intrinsic::dx_sdot:
1111 case Intrinsic::dx_udot:
1113 break;
1114 case Intrinsic::dx_sign:
1116 break;
1117 case Intrinsic::dx_step:
1119 break;
1120 case Intrinsic::dx_radians:
1122 break;
1123 case Intrinsic::dx_resource_load_rawbuffer:
1125 return true;
1126 break;
1127 case Intrinsic::dx_resource_store_rawbuffer:
1129 return true;
1130 break;
1131 case Intrinsic::dx_resource_load_typedbuffer:
1133 return true;
1134 break;
1135 case Intrinsic::dx_resource_store_typedbuffer:
1137 return true;
1138 break;
1139 case Intrinsic::usub_sat:
1141 break;
1142 case Intrinsic::vector_reduce_add:
1143 case Intrinsic::vector_reduce_fadd:
1145 break;
1146 }
1147 if (Result) {
1150 return true;
1151 }
1152 return false;
1153}
1154
1158 continue;
1159 bool IntrinsicExpanded = false;
1162 if (!IntrinsicCall)
1163 continue;
1165 }
1166 if (F.user_empty() && IntrinsicExpanded)
1167 F.eraseFromParent();
1168 }
1169 return true;
1170}
1171
1178
1182
1184
1186 "DXIL Intrinsic Expansion", false, false)
1189
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static Value * expand16BitIsNormal(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:163
static Value * expandNormalizeIntrinsic(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:579
static bool expandIntrinsic(Function &F, CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:1045
static Value * expandClampIntrinsic(CallInst *Orig, Intrinsic::ID ClampIntrinsic)
Definition DXILIntrinsicExpansion.cpp:998
static Value * expand16BitIsInf(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:55
static bool expansionIntrinsics(Module &M)
Definition DXILIntrinsicExpansion.cpp:1155
static Value * expand16BitIsFinite(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:136
static Value * expandLerpIntrinsic(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:545
static Value * expandCrossIntrinsic(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:312
static Value * expandUsubSat(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:251
static Value * expandAnyOrAllIntrinsic(CallInst *Orig, Intrinsic::ID IntrinsicId)
Definition DXILIntrinsicExpansion.cpp:504
static Value * expandVecReduceAdd(CallInst *Orig, Intrinsic::ID IntrinsicId)
Definition DXILIntrinsicExpansion.cpp:264
static Value * expandAtan2Intrinsic(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:614
static Value * expandLog10Intrinsic(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:573
static Intrinsic::ID getMinForClamp(Intrinsic::ID ClampIntrinsic)
Definition DXILIntrinsicExpansion.cpp:989
static Value * expandStepIntrinsic(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:739
static Value * expandIntegerDotIntrinsic(CallInst *Orig, Intrinsic::ID DotIntrinsic)
Definition DXILIntrinsicExpansion.cpp:397
static bool expandBufferStoreIntrinsic(CallInst *Orig, bool IsRaw)
Definition DXILIntrinsicExpansion.cpp:880
static Value * expandLogIntrinsic(CallInst *Orig, float LogConstVal=numbers::ln2f)
Definition DXILIntrinsicExpansion.cpp:555
static Value * expandDegreesIntrinsic(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:1011
static Value * expandPowIntrinsic(CallInst *Orig, Intrinsic::ID IntrinsicId)
Definition DXILIntrinsicExpansion.cpp:719
static bool resourceAccessNeeds64BitExpansion(Module *M, Type *OverloadTy, bool IsRaw)
Definition DXILIntrinsicExpansion.cpp:46
static Value * expandExpIntrinsic(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:430
static Value * expand16BitIsNaN(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:90
static Value * expandSignIntrinsic(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:1019
static Intrinsic::ID getMaxForClamp(Intrinsic::ID ClampIntrinsic)
Definition DXILIntrinsicExpansion.cpp:980
static Value * expandAbs(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:296
static Value * expandFloatDotIntrinsic(CallInst *Orig, Value *A, Value *B)
Definition DXILIntrinsicExpansion.cpp:350
static Value * expandRadiansIntrinsic(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:761
static bool isIntrinsicExpansion(Function &F)
Definition DXILIntrinsicExpansion.cpp:199
static bool expandBufferLoadIntrinsic(CallInst *Orig, bool IsRaw)
Definition DXILIntrinsicExpansion.cpp:769
static Value * expandIsFPClass(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:449
static Value * expandFunnelShiftIntrinsic(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:663
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
const SmallVectorImpl< MachineOperand > & Cond
static unsigned getNumElements(Type *Ty)
This file defines the SmallVector class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static char ID
Definition DXILIntrinsicExpansion.cpp:43
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
Definition DXILIntrinsicExpansion.cpp:1179
DXILIntrinsicExpansionLegacy()
Definition DXILIntrinsicExpansion.cpp:41
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
void setAttributes(AttributeList A)
Set the attributes for this call.
Value * getArgOperand(unsigned i) const
FunctionType * getFunctionType() const
AttributeList getAttributes() const
Return the attributes for this call.
This class represents a function call, abstracting a target machine's calling convention.
void setTailCall(bool IsTc=true)
static LLVM_ABI Constant * getSplat(ElementCount EC, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
This is an important base class in LLVM.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
LLVM_ABI bool isZeroValue() const
Return true if the value is negative zero or null value.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
Definition DXILIntrinsicExpansion.cpp:1172
static constexpr ElementCount getFixed(ScalarTy MinVal)
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Type * getParamType(unsigned i) const
Parameter type accessors.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI FastMathFlags getFastMathFlags() const LLVM_READONLY
Convenience function for getting all the fast-math flags, which must be an operator which supports th...
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
A Module instance is used to store all the information related to an LLVM module.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI Type * getStructElementType(unsigned N) const
bool isVectorTy() const
True if this is an instance of VectorType.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
Represents a version number in the form major[.minor[.subminor[.build]]].
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
ModulePass * createDXILIntrinsicExpansionLegacyPass()
Pass to expand intrinsic operations that lack DXIL opCodes.
Definition DXILIntrinsicExpansion.cpp:1190
@ Sub
Subtraction of integers.
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.