LLVM: lib/Target/DirectX/DXILOpLowering.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

25#include "llvm/IR/IntrinsicsDirectX.h"

33

34#define DEBUG_TYPE "dxil-op-lower"

35

36using namespace llvm;

38

39namespace {

40class OpLowerer {

47 Function *CleanupNURI = nullptr;

48

49public:

52 : M(M), OpBuilder(M), DRM(DRM), DRTM(DRTM), MMDI(MMDI) {}

53

54

55

56 [[nodiscard]] bool

61 if (!CI)

62 continue;

63

64 if (Error E = ReplaceCall(CI)) {

65 std::string Message(toString(std::move(E)));

68

69 return true;

70 }

71 }

72 if (F.user_empty())

73 F.eraseFromParent();

74 return false;

75 }

76

77 struct IntrinArgSelect {

78 enum class Type {

79#define DXIL_OP_INTRINSIC_ARG_SELECT_TYPE(name) name,

80#include "DXILOperation.inc"

81 };

82 Type Type;

83 int Value;

84 };

85

86

87

88

89

90 Error replaceNamedStructUses(CallInst *Intrin, CallInst *DXILOp) {

93 if (!IntrinTy->isLayoutIdentical(DXILOpTy))

95 "Type mismatch between intrinsic and DXIL op",

97

100 EVI->setOperand(0, DXILOp);

102 IVI->setOperand(0, DXILOp);

103 else

105 "be used by insert- and extractvalue",

108 }

109

110 [[nodiscard]] bool

111 replaceFunctionWithOp(Function &F, dxil::OpCode DXILOp,

113 return replaceFunction(F, [&](CallInst *CI) -> Error {

114 OpBuilder.getIRB().SetInsertPoint(CI);

116 if (ArgSelects.size()) {

117 for (const IntrinArgSelect &A : ArgSelects) {

118 switch (A.Type) {

119 case IntrinArgSelect::Type::Index:

121 break;

122 case IntrinArgSelect::Type::I8:

123 Args.push_back(OpBuilder.getIRB().getInt8((uint8_t)A.Value));

124 break;

125 case IntrinArgSelect::Type::I32:

126 Args.push_back(OpBuilder.getIRB().getInt32(A.Value));

127 break;

128 }

129 }

130 } else {

132 }

133

134 Expected<CallInst *> OpCall =

135 OpBuilder.tryCreateOp(DXILOp, Args, CI->getName(), F.getReturnType());

137 return E;

138

140 if (Error E = replaceNamedStructUses(CI, *OpCall))

141 return E;

142 } else

144

147 });

148 }

149

150

151

152

153

154

156 CallInst *Cast = OpBuilder.getIRB().CreateIntrinsic(

157 Intrinsic::dx_resource_casthandle, {Ty, V->getType()}, {V});

158 CleanupCasts.push_back(Cast);

159 return Cast;

160 }

161

162 void cleanupHandleCasts() {

165

166 for (CallInst *Cast : CleanupCasts) {

167

168

169

170

172

173

174

175 if (Cast->getType() != OpBuilder.getHandleType()) {

177 continue;

178 }

179

180

182 assert(Def->getIntrinsicID() == Intrinsic::dx_resource_casthandle &&

183 "Unbalanced pair of temporary handle casts");

186 }

187 for (CallInst *Cast : ToRemove) {

188 assert(Cast->user_empty() && "Temporary handle cast still has users");

190 }

191

192

195 for (Function *F : CastFns)

196 F->eraseFromParent();

197

198 CleanupCasts.clear();

199 }

200

201 void cleanupNonUniformResourceIndexCalls() {

202

203 if (!CleanupNURI)

204 return;

207 if (!CI)

208 continue;

211 }

212 CleanupNURI->eraseFromParent();

213 CleanupNURI = nullptr;

214 }

215

216

217

218

219

220

221 void removeResourceGlobals(CallInst *CI) {

225 Store->eraseFromParent();

227 if (GV->use_empty()) {

228 GV->removeDeadConstantUsers();

229 GV->eraseFromParent();

230 }

231 }

232 }

233 }

234

235 void replaceHandleFromBindingCall(CallInst *CI, Value *Replacement) {

237 Intrinsic::dx_resource_handlefrombinding);

238

239 removeResourceGlobals(CI);

240

242

245

246 if (NameGlobal && NameGlobal->use_empty())

247 NameGlobal->removeFromParent();

248 }

249

250 bool hasNonUniformIndex(Value *IndexOp) {

252 return false;

253

256

257 while (!WorkList.empty()) {

261 Intrinsic::dx_resource_nonuniformindex)

262 return true;

263 }

267 continue;

269 }

270 }

271 }

272 return false;

273 }

274

275 [[nodiscard]] bool lowerToCreateHandle(Function &F) {

280

281 return replaceFunction(F, [&](CallInst *CI) -> Error {

283

284 auto *It = DRM.find(CI);

285 assert(It != DRM.end() && "Resource not in map?");

286 dxil::ResourceInfo &RI = *It;

287

290

292 if (Binding.LowerBound != 0)

295

296 bool HasNonUniformIndex =

297 (Binding.Size == 1) ? false : hasNonUniformIndex(IndexOp);

298 std::array<Value *, 4> Args{

300 ConstantInt::get(Int32Ty, Binding.RecordID), IndexOp,

301 ConstantInt::get(Int1Ty, HasNonUniformIndex)};

302 Expected<CallInst *> OpCall =

303 OpBuilder.tryCreateOp(OpCode::CreateHandle, Args, CI->getName());

305 return E;

306

307 Value *Cast = createTmpHandleCast(*OpCall, CI->getType());

308 replaceHandleFromBindingCall(CI, Cast);

310 });

311 }

312

313 [[nodiscard]] bool lowerToBindAndAnnotateHandle(Function &F) {

317

318 return replaceFunction(F, [&](CallInst *CI) -> Error {

320

321 auto *It = DRM.find(CI);

322 assert(It != DRM.end() && "Resource not in map?");

323 dxil::ResourceInfo &RI = *It;

324

326 dxil::ResourceTypeInfo &RTI = DRTM[RI.getHandleTy()];

328

330 if (Binding.LowerBound != 0)

333

334 std::pair<uint32_t, uint32_t> Props =

336

337

338

339 uint32_t Unbounded = std::numeric_limits<uint32_t>::max();

340 uint32_t UpperBound = Binding.Size == Unbounded

341 ? Unbounded

343 Constant *ResBind = OpBuilder.getResBind(Binding.LowerBound, UpperBound,

345 bool NonUniformIndex =

346 (Binding.Size == 1) ? false : hasNonUniformIndex(IndexOp);

347 Constant *NonUniformOp = ConstantInt::get(Int1Ty, NonUniformIndex);

348 std::array<Value *, 3> BindArgs{ResBind, IndexOp, NonUniformOp};

349 Expected<CallInst *> OpBind = OpBuilder.tryCreateOp(

350 OpCode::CreateHandleFromBinding, BindArgs, CI->getName());

352 return E;

353

354 std::array<Value *, 2> AnnotateArgs{

355 *OpBind, OpBuilder.getResProps(Props.first, Props.second)};

356 Expected<CallInst *> OpAnnotate = OpBuilder.tryCreateOp(

357 OpCode::AnnotateHandle, AnnotateArgs,

360 return E;

361

362 Value *Cast = createTmpHandleCast(*OpAnnotate, CI->getType());

363 replaceHandleFromBindingCall(CI, Cast);

365 });

366 }

367

368

369

370

371 bool lowerHandleFromBinding(Function &F) {

372 if (MMDI.DXILVersion < VersionTuple(1, 6))

373 return lowerToCreateHandle(F);

374 return lowerToBindAndAnnotateHandle(F);

375 }

376

377

378

379 Error replaceResRetUses(CallInst *Intrin, CallInst *Op, bool HasCheckBit) {

381

384

385 if (HasCheckBit) {

387

388 Value *CheckOp = nullptr;

392 ArrayRef Indices = EVI->getIndices();

394

395 if (Indices[0] != 1)

396 continue;

397 if (!CheckOp) {

399 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(

400 OpCode::CheckAccessFullyMapped, {NewEVI},

401 OldResult->hasName() ? OldResult->getName() + "_check"

402 : Twine(),

405 return E;

406 CheckOp = *OpCall;

407 }

408 EVI->replaceAllUsesWith(CheckOp);

409 EVI->eraseFromParent();

410 }

411 }

412

414

417 }

418

421 "Expected only use to be extract of first element");

423 OldTy = ST->getElementType(0);

424 }

425

426

431 if (OldResult != Intrin) {

432 assert(Intrin->use_empty() && "Intrinsic still has uses?");

434 }

436 }

437

438 std::array<Value *, 4> Extracts = {};

440

441

442

446 size_t IndexVal = IndexOp->getZExtValue();

447 assert(IndexVal < 4 && "Index into buffer load out of range");

448 if (!Extracts[IndexVal])

451 EEI->eraseFromParent();

452 } else {

454 }

455 }

456 }

457

459 const unsigned N = VecTy->getNumElements();

460

461

462

463 if (!DynamicAccesses.empty()) {

466

467 Type *ElTy = VecTy->getElementType();

468 Type *ArrayTy = ArrayType::get(ElTy, N);

470

471 for (int I = 0, E = N; I != E; ++I) {

472 if (!Extracts[I])

475 ArrayTy, Alloca, {Zero, ConstantInt::get(Int32Ty, I)});

477 }

478

479 for (ExtractElementInst *EEI : DynamicAccesses) {

481 {Zero, EEI->getIndexOperand()});

484 EEI->eraseFromParent();

485 }

486 }

487

488

489

490

492 for (int I = 0, E = N; I != E; ++I)

493 if (!Extracts[I])

495

497 for (int I = 0, E = N; I != E; ++I)

500 }

501

503 if (OldResult != Intrin) {

504 assert(Intrin->use_empty() && "Intrinsic still has uses?");

506 }

507

509 }

510

511 [[nodiscard]] bool lowerTypedBufferLoad(Function &F, bool HasCheckBit) {

514

515 return replaceFunction(F, [&](CallInst *CI) -> Error {

517

519 createTmpHandleCast(CI->getArgOperand(0), OpBuilder.getHandleType());

522

524 if (HasCheckBit)

526 Type *NewRetTy = OpBuilder.getResRetType(OldTy->getScalarType());

527

528 std::array<Value *, 3> Args{Handle, Index0, Index1};

529 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(

530 OpCode::BufferLoad, Args, CI->getName(), NewRetTy);

532 return E;

533 if (Error E = replaceResRetUses(CI, *OpCall, HasCheckBit))

534 return E;

535

537 });

538 }

539

540 [[nodiscard]] bool lowerRawBufferLoad(Function &F) {

541 const DataLayout &DL = F.getDataLayout();

545

546 return replaceFunction(F, [&](CallInst *CI) -> Error {

548

551 Type *NewRetTy = OpBuilder.getResRetType(ScalarTy);

552

554 createTmpHandleCast(CI->getArgOperand(0), OpBuilder.getHandleType());

557 uint64_t NumElements =

558 DL.getTypeSizeInBits(OldTy) / DL.getTypeSizeInBits(ScalarTy);

559 Value *Mask = ConstantInt::get(Int8Ty, ~(~0U << NumElements));

561 ConstantInt::get(Int32Ty, DL.getPrefTypeAlign(ScalarTy).value());

562

563 Expected<CallInst *> OpCall =

564 MMDI.DXILVersion >= VersionTuple(1, 2)

565 ? OpBuilder.tryCreateOp(OpCode::RawBufferLoad,

566 {Handle, Index0, Index1, Mask, Align},

568 : OpBuilder.tryCreateOp(OpCode::BufferLoad,

569 {Handle, Index0, Index1}, CI->getName(),

570 NewRetTy);

572 return E;

573 if (Error E = replaceResRetUses(CI, *OpCall, true))

574 return E;

575

577 });

578 }

579

580 [[nodiscard]] bool lowerCBufferLoad(Function &F) {

582

583 return replaceFunction(F, [&](CallInst *CI) -> Error {

585

588 Type *NewRetTy = OpBuilder.getCBufRetType(ScalarTy);

589

591 createTmpHandleCast(CI->getArgOperand(0), OpBuilder.getHandleType());

593

594 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(

595 OpCode::CBufferLoadLegacy, {Handle, Index}, CI->getName(), NewRetTy);

597 return E;

598 if (Error E = replaceNamedStructUses(CI, *OpCall))

599 return E;

600

603 });

604 }

605

606 [[nodiscard]] bool lowerUpdateCounter(Function &F) {

609

610 return replaceFunction(F, [&](CallInst *CI) -> Error {

613 createTmpHandleCast(CI->getArgOperand(0), OpBuilder.getHandleType());

615

616 std::array<Value *, 2> Args{Handle, Op1};

617

618 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(

619 OpCode::UpdateCounter, Args, CI->getName(), Int32Ty);

620

622 return E;

623

627 });

628 }

629

630 [[nodiscard]] bool lowerGetDimensionsX(Function &F) {

633

634 return replaceFunction(F, [&](CallInst *CI) -> Error {

637 createTmpHandleCast(CI->getArgOperand(0), OpBuilder.getHandleType());

639

640 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(

643 return E;

645

649 });

650 }

651

652 [[nodiscard]] bool lowerGetPointer(Function &F) {

653

654

655 assert(F.user_empty() && "getpointer operations should have been removed");

656 F.eraseFromParent();

657 return false;

658 }

659

660 [[nodiscard]] bool lowerBufferStore(Function &F, bool IsRaw) {

661 const DataLayout &DL = F.getDataLayout();

665

666 return replaceFunction(F, [&](CallInst *CI) -> Error {

668

670 createTmpHandleCast(CI->getArgOperand(0), OpBuilder.getHandleType());

673

675 Type *DataTy = Data->getType();

677

678 uint64_t NumElements =

679 DL.getTypeSizeInBits(DataTy) / DL.getTypeSizeInBits(ScalarTy);

681 ConstantInt::get(Int8Ty, IsRaw ? ~(~0U << NumElements) : 15U);

682

683

684 if (NumElements > 4)

686 "Buffer store data must have at most 4 elements",

688

689 std::array<Value *, 4> DataElements{nullptr, nullptr, nullptr, nullptr};

690 if (DataTy == ScalarTy)

691 DataElements[0] = Data;

692 else {

693

694

695

697 while (IEI) {

699 if (!IndexOp)

700 break;

701 size_t IndexVal = IndexOp->getZExtValue();

702 assert(IndexVal < 4 && "Too many elements for buffer store");

703 DataElements[IndexVal] = IEI->getOperand(1);

705 }

706 }

707

708

709

710

711 for (int I = 0, E = NumElements; I < E; ++I)

712 if (DataElements[I] == nullptr)

713 DataElements[I] =

715

716

717

718

719 for (int I = NumElements, E = 4; I < E; ++I)

720 if (DataElements[I] == nullptr)

721 DataElements[I] = IsRaw ? UndefValue::get(ScalarTy) : DataElements[0];

722

725 Handle, Index0, Index1, DataElements[0],

726 DataElements[1], DataElements[2], DataElements[3], Mask};

727 if (IsRaw && MMDI.DXILVersion >= VersionTuple(1, 2)) {

728 Op = OpCode::RawBufferStore;

729

730 Args.push_back(

731 ConstantInt::get(Int32Ty, DL.getPrefTypeAlign(ScalarTy).value()));

732 }

733 Expected<CallInst *> OpCall =

734 OpBuilder.tryCreateOp(Op, Args, CI->getName());

736 return E;

737

739

741 while (IEI && IEI->use_empty()) {

742 InsertElementInst *Tmp = IEI;

745 }

746

748 });

749 }

750

751 [[nodiscard]] bool lowerCtpopToCountBits(Function &F) {

754

755 return replaceFunction(F, [&](CallInst *CI) -> Error {

759

761 Type *FRT = F.getReturnType();

763 RetTy = VectorType::get(RetTy, VT);

764

765 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(

766 dxil::OpCode::CountBits, Args, CI->getName(), RetTy);

768 return E;

769

770

775 }

776

777 unsigned CastOp;

778 unsigned CastOp2;

780 CastOp = Instruction::ZExt;

781 CastOp2 = Instruction::SExt;

782 } else {

784 "Currently only lowering 16, 32, or 64 bit ctpop to CountBits \

785 is supported.");

786 CastOp = Instruction::Trunc;

787 CastOp2 = Instruction::Trunc;

788 }

789

790

791

792 bool NeedsCast = false;

795 if (I && (I->getOpcode() == CastOp || I->getOpcode() == CastOp2) &&

796 I->getType() == RetTy) {

797 I->replaceAllUsesWith(*OpCall);

798 I->eraseFromParent();

799 } else

800 NeedsCast = true;

801 }

802

803

804

805

806

807 if (NeedsCast) {

811 }

812

815 });

816 }

817

818 [[nodiscard]] bool lowerLifetimeIntrinsic(Function &F) {

820 return replaceFunction(F, [&](CallInst *CI) -> Error {

824 "Expected operand of lifetime intrinsic to be a pointer");

825

826 auto ZeroOrUndef = [&](Type *Ty) {

827 return MMDI.ValidatorVersion < VersionTuple(1, 6)

829 : UndefValue::get(Ty);

830 };

831

832 Value *Val = nullptr;

834 if (GV->hasInitializer() || GV->isExternallyInitialized())

836 Val = ZeroOrUndef(GV->getValueType());

838 Val = ZeroOrUndef(AI->getAllocatedType());

839

840 assert(Val && "Expected operand of lifetime intrinsic to be a global "

841 "variable or alloca instruction");

843

846 });

847 }

848

849 [[nodiscard]] bool lowerIsFPClass(Function &F) {

852

853 return replaceFunction(F, [&](CallInst *CI) -> Error {

857 Args.push_back(Fl);

858

862 switch (TCI->getZExtValue()) {

863 case FPClassTest::fcInf:

864 OpCode = dxil::OpCode::IsInf;

865 break;

866 case FPClassTest::fcNan:

867 OpCode = dxil::OpCode::IsNaN;

868 break;

869 case FPClassTest::fcNormal:

870 OpCode = dxil::OpCode::IsNormal;

871 break;

872 case FPClassTest::fcFinite:

873 OpCode = dxil::OpCode::IsFinite;

874 break;

875 default:

876 SmallString<128> Msg =

877 formatv("Unsupported FPClassTest {0} for DXIL Op Lowering",

878 TCI->getZExtValue());

880 }

881

882 Expected<CallInst *> OpCall =

883 OpBuilder.tryCreateOp(OpCode, Args, CI->getName(), RetTy);

885 return E;

886

890 });

891 }

892

893 bool lowerIntrinsics() {

894 bool Updated = false;

895 bool HasErrors = false;

896

898 if (F.isDeclaration())

899 continue;

901 switch (ID) {

902

903

904 case Intrinsic::dx_resource_casthandle:

905

906 case Intrinsic::dbg_value:

908 if (F.use_empty())

909 F.eraseFromParent();

910 continue;

911 default:

912 if (F.use_empty())

913 F.eraseFromParent();

914 else {

915 SmallString<128> Msg = formatv(

916 "Unsupported intrinsic {0} for DXIL lowering", F.getName());

917 M.getContext().emitError(Msg);

918 HasErrors |= true;

919 }

920 break;

921

922#define DXIL_OP_INTRINSIC(OpCode, Intrin, ...) \

923 case Intrin: \

924 HasErrors |= replaceFunctionWithOp( \

925 F, OpCode, ArrayRef{__VA_ARGS__}); \

926 break;

927#include "DXILOperation.inc"

928 case Intrinsic::dx_resource_handlefrombinding:

929 HasErrors |= lowerHandleFromBinding(F);

930 break;

931 case Intrinsic::dx_resource_getpointer:

932 HasErrors |= lowerGetPointer(F);

933 break;

934 case Intrinsic::dx_resource_nonuniformindex:

935 assert(!CleanupNURI &&

936 "overloaded llvm.dx.resource.nonuniformindex intrinsics?");

937 CleanupNURI = &F;

938 break;

939 case Intrinsic::dx_resource_load_typedbuffer:

940 HasErrors |= lowerTypedBufferLoad(F, true);

941 break;

942 case Intrinsic::dx_resource_store_typedbuffer:

943 HasErrors |= lowerBufferStore(F, false);

944 break;

945 case Intrinsic::dx_resource_load_rawbuffer:

946 HasErrors |= lowerRawBufferLoad(F);

947 break;

948 case Intrinsic::dx_resource_store_rawbuffer:

949 HasErrors |= lowerBufferStore(F, true);

950 break;

951 case Intrinsic::dx_resource_load_cbufferrow_2:

952 case Intrinsic::dx_resource_load_cbufferrow_4:

953 case Intrinsic::dx_resource_load_cbufferrow_8:

954 HasErrors |= lowerCBufferLoad(F);

955 break;

956 case Intrinsic::dx_resource_updatecounter:

957 HasErrors |= lowerUpdateCounter(F);

958 break;

959 case Intrinsic::dx_resource_getdimensions_x:

960 HasErrors |= lowerGetDimensionsX(F);

961 break;

962 case Intrinsic::ctpop:

963 HasErrors |= lowerCtpopToCountBits(F);

964 break;

965 case Intrinsic::lifetime_start:

966 case Intrinsic::lifetime_end:

967 if (F.use_empty())

968 F.eraseFromParent();

969 else {

970 if (MMDI.DXILVersion < VersionTuple(1, 6))

971 HasErrors |= lowerLifetimeIntrinsic(F);

972 else

973 continue;

974 }

975 break;

976 case Intrinsic::is_fpclass:

977 HasErrors |= lowerIsFPClass(F);

978 break;

979 }

980 Updated = true;

981 }

982 if (Updated && !HasErrors) {

983 cleanupHandleCasts();

984 cleanupNonUniformResourceIndexCalls();

985 }

986

987 return Updated;

988 }

989};

990}

991

996

997 const bool MadeChanges = OpLowerer(M, DRM, DRTM, MMDI).lowerIntrinsics();

998 if (!MadeChanges)

1005 return PA;

1006}

1007

1008namespace {

1009class DXILOpLoweringLegacy : public ModulePass {

1010public:

1011 bool runOnModule(Module &M) override {

1013 getAnalysis().getResourceMap();

1015 getAnalysis().getResourceTypeMap();

1017 getAnalysis().getModuleMetadata();

1018

1019 return OpLowerer(M, DRM, DRTM, MMDI).lowerIntrinsics();

1020 }

1021 StringRef getPassName() const override { return "DXIL Op Lowering"; }

1022 DXILOpLoweringLegacy() : ModulePass(ID) {}

1023

1024 static char ID;

1025 void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {

1026 AU.addRequired();

1027 AU.addRequired();

1028 AU.addRequired();

1030 AU.addPreserved();

1031 AU.addPreserved();

1032 AU.addPreserved();

1033 }

1034};

1035char DXILOpLoweringLegacy::ID = 0;

1036}

1037

1039 false, false)

1044

1046 return new DXILOpLoweringLegacy();

1047}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

ReachingDefInfo InstSet & ToRemove

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

DXIL Resource Implicit Binding

Module.h This file contains the declarations for the Module class.

This header defines various interfaces for pass management in LLVM.

This defines the Use class.

ModuleAnalysisManager MAM

#define INITIALIZE_PASS_DEPENDENCY(depName)

#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)

#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)

This file defines the SmallVector class.

AnalysisUsage & addRequired()

AnalysisUsage & addPreserved()

Add the specified Pass class to the set of analyses preserved by this pass.

size_t size() const

size - Get the array size.

Function * getCalledFunction() const

Returns the function called, or null if this is an indirect function invocation or the function signa...

User::op_iterator arg_begin()

Return the iterator pointing to the beginning of the argument list.

Value * getArgOperand(unsigned i) const

User::op_iterator arg_end()

Return the iterator pointing to the end of the argument list.

This class represents a function call, abstracting a target machine's calling convention.

static LLVM_ABI Constant * getNullValue(Type *Ty)

Constructor to create a '0' constant of arbitrary type.

PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)

Definition DXILOpLowering.cpp:992

Diagnostic information for unsupported feature in backend.

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Error takeError()

Take ownership of the stored error.

Intrinsic::ID getIntrinsicID() const LLVM_READONLY

getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...

Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")

AllocaInst * CreateAlloca(Type *Ty, unsigned AddrSpace, Value *ArraySize=nullptr, const Twine &Name="")

IntegerType * getInt1Ty()

Fetch the type representing a single bit.

Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")

Value * CreateZExtOrTrunc(Value *V, Type *DestTy, const Twine &Name="")

Create a ZExt or Trunc from the integer value V to DestTy.

Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")

IntegerType * getInt32Ty()

Fetch the type representing a 32-bit integer.

Value * CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="")

LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)

Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...

StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)

Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)

void SetInsertPoint(BasicBlock *TheBB)

This specifies that created instructions should be appended to the end of the specified block.

IntegerType * getInt8Ty()

Fetch the type representing an 8-bit integer.

const DebugLoc & getDebugLoc() const

Return the debug location for this node as a DebugLoc.

LLVM_ABI InstListType::iterator eraseFromParent()

This method unlinks 'this' from the containing basic block and deletes it.

LLVM_ABI const Function * getFunction() const

Return the function this instruction belongs to.

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 all()

Construct a special preserved set that preserves all passes.

PreservedAnalyses & preserve()

Mark an analysis as preserved.

iterator erase(const_iterator CI)

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringRef - Represent a constant reference to a string, i.e.

The instances of the Type class are immutable: once they are created, they are never changed.

bool isIntOrIntVectorTy() const

Return true if this is an integer type or a vector of integer types.

bool isPointerTy() const

True if this is an instance of PointerType.

Type * getScalarType() const

If this is a vector type, return the element type, otherwise return 'this'.

static LLVM_ABI UndefValue * get(Type *T)

Static factory methods - Return an 'undef' object of the specified type.

Value * getOperand(unsigned i) const

Type * getType() const

All values are typed, get the type of this value.

user_iterator user_begin()

bool hasOneUse() const

Return true if there is exactly one use 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()

iterator_range< use_iterator > uses()

LLVM_ABI StringRef getName() const

Return a constant reference to the value's name.

TargetExtType * getHandleTy() const

LLVM_ABI std::pair< uint32_t, uint32_t > getAnnotateProps(Module &M, dxil::ResourceTypeInfo &RTI) const

const ResourceBinding & getBinding() const

dxil::ResourceClass getResourceClass() const

An efficient, type-erasing, non-owning reference to a callable.

constexpr char Align[]

Key for Kernel::Arg::Metadata::mAlign.

constexpr char Args[]

Key for Kernel::Metadata::mArgs.

constexpr std::underlying_type_t< E > Mask()

Get a bitmask with 1s in all places up to the high-order bit of E's largest value.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

@ Undef

Value of the register doesn't matter.

NodeAddr< DefNode * > Def

NodeAddr< UseNode * > Use

friend class Instruction

Iterator for Instructions in a `BasicBlock.

This is an optimization pass for GlobalISel generic memory operations.

FunctionAddr VTableAddr Value

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

LLVM_ABI std::error_code inconvertibleErrorCode()

The value returned by this function can be returned from convertToErrorCode for Error values where no...

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...

auto unique(Range &&R, Predicate P)

auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)

decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)

void sort(IteratorTy Start, IteratorTy End)

constexpr std::underlying_type_t< Enum > to_underlying(Enum E)

Returns underlying integer value of an enum.

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

Error make_error(ArgTs &&... Args)

Make a Error instance representing failure using the given error info type.

FunctionAddr VTableAddr uintptr_t uintptr_t Data

IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >

DWARFExpression::Operation Op

ArrayRef(const T &OneElt) -> ArrayRef< T >

std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)

ModulePass * createDXILOpLoweringLegacyPass()

Pass to lowering LLVM intrinsic call to DXIL op function call.

Definition DXILOpLowering.cpp:1045

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.