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

43 static char ID;

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

254 Type *Ty = A->getType();

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

272 Type *Ty = X->getType();

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

299 Type *Ty = X->getType();

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

351 Type *ATy = A->getType();

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);

403 Type *ATy = A->getType();

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

433 Type *Ty = X->getType();

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

469 Type *FTy = F->getType();

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

508 Type *Ty = X->getType();

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

559 Type *Ty = X->getType();

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

617 Type *Ty = X->getType();

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

723 Type *Ty = X->getType();

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

743 Type *Ty = X->getType();

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

763 Type *Ty = X->getType();

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) {

962 Mask.push_back(Base + 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

1003 Type *Ty = X->getType();

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

1013 Type *Ty = X->getType();

1016 return Builder.CreateFMul(X, DegreesRatio);

1017}

1018

1021 Type *Ty = X->getType();

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.