LLVM: lib/Target/DirectX/DXILIntrinsicExpansion.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
23#include "llvm/IR/IntrinsicsDirectX.h"
31
32#define DEBUG_TYPE "dxil-intrinsic-expansion"
33
34using namespace llvm;
35
37
38public:
41
43};
44
46 bool IsRaw) {
47 if (IsRaw && M->getTargetTriple().getDXILVersion() > VersionTuple(1, 2))
48 return false;
49
52}
53
56 if (M->getTargetTriple().getDXILVersion() >= VersionTuple(1, 9))
57 return nullptr;
58
61 if (!ValTy->getScalarType()->isHalfTy())
62 return nullptr;
63
67 ValTy->isVectorTy()
71 ConstantInt::get(IType, 0x7c00))
72 : ConstantInt::get(IType, 0x7c00);
73
75 ValTy->isVectorTy()
79 ConstantInt::get(IType, 0xfc00))
80 : ConstantInt::get(IType, 0xfc00);
81
82 Value *IVal = Builder.CreateBitCast(Val, PosInf->getType());
83 Value *B1 = Builder.CreateICmpEQ(IVal, PosInf);
84 Value *B2 = Builder.CreateICmpEQ(IVal, NegInf);
85 Value *B3 = Builder.CreateOr(B1, B2);
86 return B3;
87}
88
91 if (M->getTargetTriple().getDXILVersion() >= VersionTuple(1, 9))
92 return nullptr;
93
96 if (!ValTy->getScalarType()->isHalfTy())
97 return nullptr;
98
101
103 ValTy->isVectorTy()
107 ConstantInt::get(IType, 0x7c00))
108 : ConstantInt::get(IType, 0x7c00);
110 ValTy->isVectorTy()
114 ConstantInt::get(IType, 0x3ff))
115 : ConstantInt::get(IType, 0x3ff);
116
118 ValTy->isVectorTy()
122 ConstantInt::get(IType, 0))
123 : ConstantInt::get(IType, 0);
124
125 Value *IVal = Builder.CreateBitCast(Val, ExpBitMask->getType());
126 Value *Exp = Builder.CreateAnd(IVal, ExpBitMask);
127 Value *B1 = Builder.CreateICmpEQ(Exp, ExpBitMask);
128
129 Value *Sig = Builder.CreateAnd(IVal, SigBitMask);
130 Value *B2 = Builder.CreateICmpNE(Sig, Zero);
131 Value *B3 = Builder.CreateAnd(B1, B2);
132 return B3;
133}
134
137 if (M->getTargetTriple().getDXILVersion() >= VersionTuple(1, 9))
138 return nullptr;
139
142 if (!ValTy->getScalarType()->isHalfTy())
143 return nullptr;
144
147
149 ValTy->isVectorTy()
153 ConstantInt::get(IType, 0x7c00))
154 : ConstantInt::get(IType, 0x7c00);
155
156 Value *IVal = Builder.CreateBitCast(Val, ExpBitMask->getType());
157 Value *Exp = Builder.CreateAnd(IVal, ExpBitMask);
158 Value *B1 = Builder.CreateICmpNE(Exp, ExpBitMask);
159 return B1;
160}
161
164 if (M->getTargetTriple().getDXILVersion() >= VersionTuple(1, 9))
165 return nullptr;
166
169 if (!ValTy->getScalarType()->isHalfTy())
170 return nullptr;
171
174
176 ValTy->isVectorTy()
180 ConstantInt::get(IType, 0x7c00))
181 : ConstantInt::get(IType, 0x7c00);
183 ValTy->isVectorTy()
187 ConstantInt::get(IType, 0))
188 : ConstantInt::get(IType, 0);
189
190 Value *IVal = Builder.CreateBitCast(Val, ExpBitMask->getType());
191 Value *Exp = Builder.CreateAnd(IVal, ExpBitMask);
192 Value *NotAllZeroes = Builder.CreateICmpNE(Exp, Zero);
193 Value *NotAllOnes = Builder.CreateICmpNE(Exp, ExpBitMask);
194 Value *B1 = Builder.CreateAnd(NotAllZeroes, NotAllOnes);
195 return B1;
196}
197
199 switch (F.getIntrinsicID()) {
200 case Intrinsic::assume:
201 case Intrinsic::abs:
202 case Intrinsic::atan2:
203 case Intrinsic::exp:
204 case Intrinsic::is_fpclass:
205 case Intrinsic:🪵
206 case Intrinsic::log10:
207 case Intrinsic::pow:
208 case Intrinsic::powi:
209 case Intrinsic::dx_all:
210 case Intrinsic::dx_any:
211 case Intrinsic::dx_cross:
212 case Intrinsic::dx_uclamp:
213 case Intrinsic::dx_sclamp:
214 case Intrinsic::dx_nclamp:
215 case Intrinsic::dx_degrees:
216 case Intrinsic::dx_isinf:
217 case Intrinsic::dx_isnan:
218 case Intrinsic::dx_lerp:
219 case Intrinsic::dx_normalize:
220 case Intrinsic::dx_fdot:
221 case Intrinsic::dx_sdot:
222 case Intrinsic::dx_udot:
223 case Intrinsic::dx_sign:
224 case Intrinsic::dx_step:
225 case Intrinsic::dx_radians:
226 case Intrinsic::usub_sat:
227 case Intrinsic::vector_reduce_add:
228 case Intrinsic::vector_reduce_fadd:
229 return true;
230 case Intrinsic::dx_resource_load_rawbuffer:
232 F.getParent(), F.getReturnType()->getStructElementType(0),
233 true);
234 case Intrinsic::dx_resource_load_typedbuffer:
236 F.getParent(), F.getReturnType()->getStructElementType(0),
237 false);
238 case Intrinsic::dx_resource_store_rawbuffer:
240 F.getParent(), F.getFunctionType()->getParamType(3), true);
241 case Intrinsic::dx_resource_store_typedbuffer:
243 F.getParent(), F.getFunctionType()->getParamType(2), false);
244 }
245 return false;
246}
247
252
254
255 Value *Cmp = Builder.CreateICmpULT(A, B, "usub.cmp");
256 Value *Sub = Builder.CreateSub(A, B, "usub.sub");
257 Value *Zero = ConstantInt::get(Ty, 0);
258 return Builder.CreateSelect(Cmp, Zero, Sub, "usub.sat");
259}
260
262 assert(IntrinsicId == Intrinsic::vector_reduce_add ||
263 IntrinsicId == Intrinsic::vector_reduce_fadd);
264
266 bool IsFAdd = (IntrinsicId == Intrinsic::vector_reduce_fadd);
267
271 unsigned XVecSize = XVec->getNumElements();
272 Value *Sum = Builder.CreateExtractElement(X, static_cast<uint64_t>(0));
273
274
275 if (IsFAdd) {
277 if (StartValue && !StartValue->isZeroValue())
278 Sum = Builder.CreateFAdd(Sum, StartValue);
279 }
280
281
282 for (unsigned I = 1; I < XVecSize; I++) {
283 Value *Elt = Builder.CreateExtractElement(X, I);
284 if (IsFAdd)
285 Sum = Builder.CreateFAdd(Sum, Elt);
286 else
287 Sum = Builder.CreateAdd(Sum, Elt);
288 }
289
290 return Sum;
291}
292
298 Constant *Zero = Ty->isVectorTy()
302 ConstantInt::get(EltTy, 0))
303 : ConstantInt::get(EltTy, 0);
304 auto *V = Builder.CreateSub(Zero, X);
305 return Builder.CreateIntrinsic(Ty, Intrinsic::smax, {X, V}, nullptr,
306 "dx.max");
307}
308
310
314
318
319 Value *op0_x = Builder.CreateExtractElement(op0, (uint64_t)0, "x0");
320 Value *op0_y = Builder.CreateExtractElement(op0, 1, "x1");
321 Value *op0_z = Builder.CreateExtractElement(op0, 2, "x2");
322
323 Value *op1_x = Builder.CreateExtractElement(op1, (uint64_t)0, "y0");
324 Value *op1_y = Builder.CreateExtractElement(op1, 1, "y1");
325 Value *op1_z = Builder.CreateExtractElement(op1, 2, "y2");
326
328 Value *xy = Builder.CreateFMul(x0, y1);
329 Value *yx = Builder.CreateFMul(y0, x1);
330 return Builder.CreateFSub(xy, yx, Orig->getName());
331 };
332
333 Value *yz_zy = MulSub(op0_y, op0_z, op1_y, op1_z);
334 Value *zx_xz = MulSub(op0_z, op0_x, op1_z, op1_x);
335 Value *xy_yx = MulSub(op0_x, op0_y, op1_x, op1_y);
336
338 cross = Builder.CreateInsertElement(cross, yz_zy, (uint64_t)0);
339 cross = Builder.CreateInsertElement(cross, zx_xz, 1);
340 cross = Builder.CreateInsertElement(cross, xy_yx, 2);
341 return cross;
342}
343
344
345
346
349 [[maybe_unused]] Type *BTy = B->getType();
351
353
355
357
359 int NumElts = AVec->getNumElements();
360 switch (NumElts) {
361 case 2:
362 DotIntrinsic = Intrinsic::dx_dot2;
363 break;
364 case 3:
365 DotIntrinsic = Intrinsic::dx_dot3;
366 break;
367 case 4:
368 DotIntrinsic = Intrinsic::dx_dot4;
369 break;
370 default:
372 "Invalid dot product input vector: length is outside 2-4");
373 return nullptr;
374 }
375
377 for (int I = 0; I < NumElts; ++I)
378 Args.push_back(Builder.CreateExtractElement(A, Builder.getInt32(I)));
379 for (int I = 0; I < NumElts; ++I)
380 Args.push_back(Builder.CreateExtractElement(B, Builder.getInt32(I)));
381 return Builder.CreateIntrinsic(ATy->getScalarType(), DotIntrinsic, Args,
382 nullptr, "dot");
383}
384
385
386
387
392
393
396 assert(DotIntrinsic == Intrinsic::dx_sdot ||
397 DotIntrinsic == Intrinsic::dx_udot);
401 [[maybe_unused]] Type *BTy = B->getType();
403
405
407
409
411 Intrinsic::ID MadIntrinsic = DotIntrinsic == Intrinsic::dx_sdot
412 ? Intrinsic::dx_imad
413 : Intrinsic::dx_umad;
414 Value *Elt0 = Builder.CreateExtractElement(A, (uint64_t)0);
415 Value *Elt1 = Builder.CreateExtractElement(B, (uint64_t)0);
416 Result = Builder.CreateMul(Elt0, Elt1);
417 for (unsigned I = 1; I < AVec->getNumElements(); I++) {
418 Elt0 = Builder.CreateExtractElement(A, I);
419 Elt1 = Builder.CreateExtractElement(B, I);
420 Result = Builder.CreateIntrinsic(Result->getType(), MadIntrinsic,
422 nullptr, "dx.mad");
423 }
424 return Result;
425}
426
438 Value *NewX = Builder.CreateFMul(Log2eConst, X);
439 auto *Exp2Call =
440 Builder.CreateIntrinsic(Ty, Intrinsic::exp2, {NewX}, nullptr, "dx.exp2");
441 Exp2Call->setTailCall(Orig->isTailCall());
443 return Exp2Call;
444}
445
449
450
451
452 switch (TCI->getZExtValue()) {
461 }
462
464
467 unsigned FNumElem = 0;
468
469 unsigned BitWidth;
470 Type *BitCastTy;
471
473 Type *ElemTy = FVecTy->getElementType();
474 FNumElem = FVecTy->getNumElements();
475 BitWidth = ElemTy->getPrimitiveSizeInBits();
477 } else {
480 }
481
482 Value *FBitCast = Builder.CreateBitCast(F, BitCastTy);
483 switch (TCI->getZExtValue()) {
486 ConstantInt::get(Builder.getIntNTy(BitWidth), 1 << (BitWidth - 1));
488 if (FNumElem) {
489 Value *NegZeroSplat = Builder.CreateVectorSplat(FNumElem, NegZero);
490 RetVal =
491 Builder.CreateICmpEQ(FBitCast, NegZeroSplat, "is.fpclass.negzero");
492 } else
493 RetVal = Builder.CreateICmpEQ(FBitCast, NegZero, "is.fpclass.negzero");
494 return RetVal;
495 }
496 default:
498 }
499}
500
507
510 if (IntrinsicId == Intrinsic::dx_any)
511 return Builder.CreateOr(Result, Elt);
512 assert(IntrinsicId == Intrinsic::dx_all);
513 return Builder.CreateAnd(Result, Elt);
514 };
515
516 Value *Result = nullptr;
517 if (!Ty->isVectorTy()) {
519 ? Builder.CreateFCmpUNE(X, ConstantFP::get(EltTy, 0))
520 : Builder.CreateICmpNE(X, ConstantInt::get(EltTy, 0));
521 } else {
525 ? Builder.CreateFCmpUNE(
528 ConstantFP::get(EltTy, 0)))
529 : Builder.CreateICmpNE(
532 ConstantInt::get(EltTy, 0)));
533 Result = Builder.CreateExtractElement(Cond, (uint64_t)0);
534 for (unsigned I = 1; I < XVec->getNumElements(); I++) {
535 Value *Elt = Builder.CreateExtractElement(Cond, I);
536 Result = ApplyOp(IntrinsicId, Result, Elt);
537 }
538 }
539 return Result;
540}
541
547 auto *V = Builder.CreateFSub(Y, X);
548 V = Builder.CreateFMul(S, V);
549 return Builder.CreateFAdd(X, V, "dx.lerp");
550}
551
562 ConstantFP::get(EltTy, LogConstVal))
563 : ConstantFP::get(EltTy, LogConstVal);
564 auto *Log2Call =
565 Builder.CreateIntrinsic(Ty, Intrinsic::log2, {X}, nullptr, "elt.log2");
566 Log2Call->setTailCall(Orig->isTailCall());
568 return Builder.CreateFMul(Ln2Const, Log2Call);
569}
573
574
575
581
583 if (!XVec) {
585 const APFloat &fpVal = constantFP->getValueAPF();
588 }
589 return Builder.CreateFDiv(X, X);
590 }
591
593
594
595
597 const APFloat &fpVal = constantFP->getValueAPF();
600 }
601
602 Value *Multiplicand = Builder.CreateIntrinsic(EltTy, Intrinsic::dx_rsqrt,
604 nullptr, "dx.rsqrt");
605
606 Value *MultiplicandVec =
607 Builder.CreateVectorSplat(XVec->getNumElements(), Multiplicand);
608 return Builder.CreateFMul(X, MultiplicandVec);
609}
610
617
618 Value *Tan = Builder.CreateFDiv(Y, X);
619
621 Builder.CreateIntrinsic(Ty, Intrinsic::atan, {Tan}, nullptr, "Elt.Atan");
624
625
629 Constant *Zero = ConstantFP::get(Ty, 0);
630 Value *AtanAddPi = Builder.CreateFAdd(Atan, Pi);
631 Value *AtanSubPi = Builder.CreateFSub(Atan, Pi);
632
633
634 Value *Result = Atan;
635 Value *XLt0 = Builder.CreateFCmpOLT(X, Zero);
636 Value *XEq0 = Builder.CreateFCmpOEQ(X, Zero);
637 Value *YGe0 = Builder.CreateFCmpOGE(Y, Zero);
638 Value *YLt0 = Builder.CreateFCmpOLT(Y, Zero);
639
640
641 Value *XLt0AndYGe0 = Builder.CreateAnd(XLt0, YGe0);
642 Result = Builder.CreateSelect(XLt0AndYGe0, AtanAddPi, Result);
643
644
645 Value *XLt0AndYLt0 = Builder.CreateAnd(XLt0, YLt0);
646 Result = Builder.CreateSelect(XLt0AndYLt0, AtanSubPi, Result);
647
648
649 Value *XEq0AndYLt0 = Builder.CreateAnd(XEq0, YLt0);
650 Result = Builder.CreateSelect(XEq0AndYLt0, NegHalfPi, Result);
651
652
653 Value *XEq0AndYGe0 = Builder.CreateAnd(XEq0, YGe0);
654 Result = Builder.CreateSelect(XEq0AndYGe0, HalfPi, Result);
655
656 return Result;
657}
658
660
665
666 if (IntrinsicId == Intrinsic::powi)
667 Y = Builder.CreateSIToFP(Y, Ty);
668
669 auto *Log2Call =
670 Builder.CreateIntrinsic(Ty, Intrinsic::log2, {X}, nullptr, "elt.log2");
671 auto *Mul = Builder.CreateFMul(Log2Call, Y);
672 auto *Exp2Call =
673 Builder.CreateIntrinsic(Ty, Intrinsic::exp2, {Mul}, nullptr, "elt.exp2");
674 Exp2Call->setTailCall(Orig->isTailCall());
676 return Exp2Call;
677}
678
680
685
686 Constant *One = ConstantFP::get(Ty->getScalarType(), 1.0);
687 Constant *Zero = ConstantFP::get(Ty->getScalarType(), 0.0);
688 Value *Cond = Builder.CreateFCmpOLT(Y, X);
689
690 if (Ty != Ty->getScalarType()) {
696 }
697
698 return Builder.CreateSelect(Cond, Zero, One);
699}
700
706 return Builder.CreateFMul(X, PiOver180);
707}
708
711
714 bool IsDouble = ScalarTy->isDoubleTy();
716 "Only expand double or int64 scalars or vectors");
717 bool IsVector = false;
718 unsigned ExtractNum = 2;
720 ExtractNum = 2 * VT->getNumElements();
721 IsVector = true;
722 assert(IsRaw || ExtractNum == 4 && "TypedBufferLoad vector must be size 2");
723 }
724
727 unsigned Base = 0;
728
729
730
731 while (ExtractNum > 0) {
732 unsigned LoadNum = std::min(ExtractNum, 4u);
734
736 Intrinsic::ID LoadIntrinsic = Intrinsic::dx_resource_load_typedbuffer;
738 if (IsRaw) {
739 LoadIntrinsic = Intrinsic::dx_resource_load_rawbuffer;
740 Value *Tmp = Builder.getInt32(4 * Base * 2);
741 Args.push_back(Builder.CreateAdd(Orig->getOperand(2), Tmp));
742 }
743
744 CallInst *Load = Builder.CreateIntrinsic(LoadType, LoadIntrinsic, Args);
746
747
748 Value *Extract = Builder.CreateExtractValue(Load, {0});
749
751 for (unsigned I = 0; I < LoadNum; ++I)
753 Builder.CreateExtractElement(Extract, Builder.getInt32(I)));
754
755
756 for (unsigned I = 0; I < LoadNum; I += 2) {
757 Value *Combined = nullptr;
758 if (IsDouble)
759
760 Combined = Builder.CreateIntrinsic(
761 Builder.getDoubleTy(), Intrinsic::dx_asdouble,
762 {ExtractElements[I], ExtractElements[I + 1]});
763 else {
764
765
767 Builder.CreateZExt(ExtractElements[I], Builder.getInt64Ty());
769 Builder.CreateZExt(ExtractElements[I + 1], Builder.getInt64Ty());
770
771 Value *ShiftedHi = Builder.CreateShl(Hi, Builder.getInt64(32));
772
773 Combined = Builder.CreateOr(Lo, ShiftedHi);
774 }
775
776 if (IsVector)
777 Result = Builder.CreateInsertElement(Result, Combined,
778 Builder.getInt32((I / 2) + Base));
779 else
780 Result = Combined;
781 }
782
783 ExtractNum -= LoadNum;
784 Base += LoadNum / 2;
785 }
786
787 Value *CheckBit = nullptr;
789
790
792 if (!EVI)
794
797
798 if (Indices[0] == 0) {
799
800 EVI->replaceAllUsesWith(Result);
801 } else {
802
803 assert(Indices[0] == 1 && "Unexpected type for typedbufferload");
804
805
806 if (!CheckBit) {
808 for (Value *L : Loads)
809 CheckBits.push_back(Builder.CreateExtractValue(L, {1}));
810 CheckBit = Builder.CreateAnd(CheckBits);
811 }
812 EVI->replaceAllUsesWith(CheckBit);
813 }
814 EVI->eraseFromParent();
815 }
817 return true;
818}
819
822
823 unsigned ValIndex = IsRaw ? 3 : 2;
826 bool IsDouble = ScalarTy->isDoubleTy();
828 "Only expand double or int64 scalars or vectors");
829
830
831 bool IsVector = false;
832 unsigned ExtractNum = 2;
833 unsigned VecLen = 0;
835 VecLen = VT->getNumElements();
836 assert(IsRaw || VecLen == 2 && "TypedBufferStore vector must be size 2");
837 ExtractNum = VecLen * 2;
838 IsVector = true;
839 }
840
841
845
847 if (IsVector)
848 SplitElementTy = VectorType::get(SplitElementTy, VecLen, false);
849
850 Value *LowBits = nullptr;
851 Value *HighBits = nullptr;
852
853 if (IsDouble) {
855 Value *Split = Builder.CreateIntrinsic(SplitTy, Intrinsic::dx_splitdouble,
857 LowBits = Builder.CreateExtractValue(Split, 0);
858 HighBits = Builder.CreateExtractValue(Split, 1);
859 } else {
860
862 Constant *ShiftAmt = Builder.getInt64(32);
863 if (IsVector)
864 ShiftAmt =
866
867
868 LowBits = Builder.CreateTrunc(InputVal, SplitElementTy);
869 Value *ShiftedVal = Builder.CreateLShr(InputVal, ShiftAmt);
870 HighBits = Builder.CreateTrunc(ShiftedVal, SplitElementTy);
871 }
872
873 if (IsVector) {
875 for (unsigned I = 0; I < VecLen; ++I) {
876 Mask.push_back(I);
877 Mask.push_back(I + VecLen);
878 }
879 Val = Builder.CreateShuffleVector(LowBits, HighBits, Mask);
880 } else {
881 Val = Builder.CreateInsertElement(Val, LowBits, Builder.getInt32(0));
882 Val = Builder.CreateInsertElement(Val, HighBits, Builder.getInt32(1));
883 }
884
885
886
887
888 unsigned Base = 0;
889 while (ExtractNum > 0) {
890 unsigned StoreNum = std::min(ExtractNum, 4u);
891
892 Intrinsic::ID StoreIntrinsic = Intrinsic::dx_resource_store_typedbuffer;
894 if (IsRaw) {
895 StoreIntrinsic = Intrinsic::dx_resource_store_rawbuffer;
896 Value *Tmp = Builder.getInt32(4 * Base);
897 Args.push_back(Builder.CreateAdd(Orig->getOperand(2), Tmp));
898 }
899
901 for (unsigned I = 0; I < StoreNum; ++I) {
903 }
904
905 Value *SubVal = Val;
906 if (VecLen > 2)
907 SubVal = Builder.CreateShuffleVector(Val, Mask);
908
909 Args.push_back(SubVal);
910
911 Builder.CreateIntrinsic(Builder.getVoidTy(), StoreIntrinsic, Args);
912
913 ExtractNum -= StoreNum;
914 Base += StoreNum;
915 }
917 return true;
918}
919
921 if (ClampIntrinsic == Intrinsic::dx_uclamp)
922 return Intrinsic::umax;
923 if (ClampIntrinsic == Intrinsic::dx_sclamp)
924 return Intrinsic::smax;
925 assert(ClampIntrinsic == Intrinsic::dx_nclamp);
926 return Intrinsic::maxnum;
927}
928
930 if (ClampIntrinsic == Intrinsic::dx_uclamp)
931 return Intrinsic::umin;
932 if (ClampIntrinsic == Intrinsic::dx_sclamp)
933 return Intrinsic::smin;
934 assert(ClampIntrinsic == Intrinsic::dx_nclamp);
935 return Intrinsic::minnum;
936}
937
945 auto *MaxCall = Builder.CreateIntrinsic(Ty, getMaxForClamp(ClampIntrinsic),
946 {X, Min}, nullptr, "dx.max");
947 return Builder.CreateIntrinsic(Ty, getMinForClamp(ClampIntrinsic),
948 {MaxCall, Max}, nullptr, "dx.min");
949}
950
956 return Builder.CreateFMul(X, DegreesRatio);
957}
958
965
967
971 GT = Builder.CreateFCmpOLT(Zero, X);
972 LT = Builder.CreateFCmpOLT(X, Zero);
973 } else {
975 GT = Builder.CreateICmpSLT(Zero, X);
976 LT = Builder.CreateICmpSLT(X, Zero);
977 }
978
979 Value *ZextGT = Builder.CreateZExt(GT, RetTy);
980 Value *ZextLT = Builder.CreateZExt(LT, RetTy);
981
982 return Builder.CreateSub(ZextGT, ZextLT);
983}
984
986 Value *Result = nullptr;
988 switch (IntrinsicId) {
989 case Intrinsic::abs:
991 break;
992 case Intrinsic::assume:
994 return true;
995 case Intrinsic::atan2:
997 break;
998 case Intrinsic::exp:
1000 break;
1001 case Intrinsic::is_fpclass:
1003 break;
1004 case Intrinsic:🪵
1006 break;
1007 case Intrinsic::log10:
1009 break;
1010 case Intrinsic::pow:
1011 case Intrinsic::powi:
1013 break;
1014 case Intrinsic::dx_all:
1015 case Intrinsic::dx_any:
1017 break;
1018 case Intrinsic::dx_cross:
1020 break;
1021 case Intrinsic::dx_uclamp:
1022 case Intrinsic::dx_sclamp:
1023 case Intrinsic::dx_nclamp:
1025 break;
1026 case Intrinsic::dx_degrees:
1028 break;
1029 case Intrinsic::dx_isinf:
1031 break;
1032 case Intrinsic::dx_isnan:
1034 break;
1035 case Intrinsic::dx_lerp:
1037 break;
1038 case Intrinsic::dx_normalize:
1040 break;
1041 case Intrinsic::dx_fdot:
1043 break;
1044 case Intrinsic::dx_sdot:
1045 case Intrinsic::dx_udot:
1047 break;
1048 case Intrinsic::dx_sign:
1050 break;
1051 case Intrinsic::dx_step:
1053 break;
1054 case Intrinsic::dx_radians:
1056 break;
1057 case Intrinsic::dx_resource_load_rawbuffer:
1059 return true;
1060 break;
1061 case Intrinsic::dx_resource_store_rawbuffer:
1063 return true;
1064 break;
1065 case Intrinsic::dx_resource_load_typedbuffer:
1067 return true;
1068 break;
1069 case Intrinsic::dx_resource_store_typedbuffer:
1071 return true;
1072 break;
1073 case Intrinsic::usub_sat:
1075 break;
1076 case Intrinsic::vector_reduce_add:
1077 case Intrinsic::vector_reduce_fadd:
1079 break;
1080 }
1081 if (Result) {
1084 return true;
1085 }
1086 return false;
1087}
1088
1092 continue;
1093 bool IntrinsicExpanded = false;
1096 if (!IntrinsicCall)
1097 continue;
1099 }
1100 if (F.user_empty() && IntrinsicExpanded)
1101 F.eraseFromParent();
1102 }
1103 return true;
1104}
1105
1112
1116
1118
1120 "DXIL Intrinsic Expansion", false, false)
1123
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")
static Value * expand16BitIsNormal(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:162
static Value * expandNormalizeIntrinsic(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:576
static bool expandIntrinsic(Function &F, CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:985
static Value * expandClampIntrinsic(CallInst *Orig, Intrinsic::ID ClampIntrinsic)
Definition DXILIntrinsicExpansion.cpp:938
static Value * expand16BitIsInf(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:54
static bool expansionIntrinsics(Module &M)
Definition DXILIntrinsicExpansion.cpp:1089
static Value * expand16BitIsFinite(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:135
static Value * expandLerpIntrinsic(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:542
static Value * expandCrossIntrinsic(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:309
static Value * expandUsubSat(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:248
static Value * expandAnyOrAllIntrinsic(CallInst *Orig, Intrinsic::ID IntrinsicId)
Definition DXILIntrinsicExpansion.cpp:501
static Value * expandVecReduceAdd(CallInst *Orig, Intrinsic::ID IntrinsicId)
Definition DXILIntrinsicExpansion.cpp:261
static Value * expandAtan2Intrinsic(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:611
static Value * expandLog10Intrinsic(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:570
static Intrinsic::ID getMinForClamp(Intrinsic::ID ClampIntrinsic)
Definition DXILIntrinsicExpansion.cpp:929
static Value * expandStepIntrinsic(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:679
static Value * expandIntegerDotIntrinsic(CallInst *Orig, Intrinsic::ID DotIntrinsic)
Definition DXILIntrinsicExpansion.cpp:394
static bool expandBufferStoreIntrinsic(CallInst *Orig, bool IsRaw)
Definition DXILIntrinsicExpansion.cpp:820
static Value * expandLogIntrinsic(CallInst *Orig, float LogConstVal=numbers::ln2f)
Definition DXILIntrinsicExpansion.cpp:552
static Value * expandDegreesIntrinsic(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:951
static Value * expandPowIntrinsic(CallInst *Orig, Intrinsic::ID IntrinsicId)
Definition DXILIntrinsicExpansion.cpp:659
static bool resourceAccessNeeds64BitExpansion(Module *M, Type *OverloadTy, bool IsRaw)
Definition DXILIntrinsicExpansion.cpp:45
static Value * expandExpIntrinsic(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:427
static Value * expand16BitIsNaN(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:89
static Value * expandSignIntrinsic(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:959
static Intrinsic::ID getMaxForClamp(Intrinsic::ID ClampIntrinsic)
Definition DXILIntrinsicExpansion.cpp:920
static Value * expandAbs(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:293
static Value * expandFloatDotIntrinsic(CallInst *Orig, Value *A, Value *B)
Definition DXILIntrinsicExpansion.cpp:347
static Value * expandRadiansIntrinsic(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:701
static bool isIntrinsicExpansion(Function &F)
Definition DXILIntrinsicExpansion.cpp:198
static bool expandBufferLoadIntrinsic(CallInst *Orig, bool IsRaw)
Definition DXILIntrinsicExpansion.cpp:709
static Value * expandIsFPClass(CallInst *Orig)
Definition DXILIntrinsicExpansion.cpp:446
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:42
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
Definition DXILIntrinsicExpansion.cpp:1113
DXILIntrinsicExpansionLegacy()
Definition DXILIntrinsicExpansion.cpp:40
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:1106
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...
ModulePass * createDXILIntrinsicExpansionLegacyPass()
Pass to expand intrinsic operations that lack DXIL opCodes.
Definition DXILIntrinsicExpansion.cpp:1124
@ 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.