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

42 static char ID;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

956 return Builder.CreateFMul(X, DegreesRatio);

957}

958

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

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.