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

1

2

3

4

5

6

7

8

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

31

32#define DEBUG_TYPE "dxil-op-lower"

33

34using namespace llvm;

36

38 switch (F.getIntrinsicID()) {

39 case Intrinsic::dx_dot2:

40 case Intrinsic::dx_dot3:

41 case Intrinsic::dx_dot4:

42 return true;

43 }

44 return false;

45}

46

49 auto *VecArg = dyn_cast(Arg->getType());

50 for (unsigned I = 0; I < VecArg->getNumElements(); ++I) {

53 ExtractedElements.push_back(ExtractedElement);

54 }

55 return ExtractedElements;

56}

57

60

62 assert(NumOperands > 0);

64 [[maybe_unused]] auto *VecArg0 = dyn_cast(Arg0->getType());

67 for (unsigned I = 1; I < NumOperands; ++I) {

69 [[maybe_unused]] auto *VecArg = dyn_cast(Arg->getType());

71 assert(VecArg0->getElementType() == VecArg->getElementType());

72 assert(VecArg0->getNumElements() == VecArg->getNumElements());

74 NewOperands.append(NextOperandList.begin(), NextOperandList.end());

75 }

76 return NewOperands;

77}

78

79namespace {

80class OpLowerer {

86

87public:

89 : M(M), OpBuilder(M), DBM(DBM), DRTM(DRTM) {}

90

91

92

93 [[nodiscard]] bool

97 CallInst *CI = dyn_cast(U);

98 if (!CI)

99 continue;

100

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

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

105 M.getContext().diagnose(Diag);

106 return true;

107 }

108 }

109 if (F.user_empty())

110 F.eraseFromParent();

111 return false;

112 }

113

114 struct IntrinArgSelect {

115 enum class Type {

116#define DXIL_OP_INTRINSIC_ARG_SELECT_TYPE(name) name,

117#include "DXILOperation.inc"

118 };

121 };

122

123 [[nodiscard]] bool

127 assert(!(IsVectorArgExpansion && ArgSelects.size()) &&

128 "Cann't do vector arg expansion when using arg selects.");

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

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

132 if (ArgSelects.size()) {

133 for (const IntrinArgSelect &A : ArgSelects) {

134 switch (A.Type) {

135 case IntrinArgSelect::Type::Index:

136 Args.push_back(CI->getArgOperand(A.Value));

137 break;

138 case IntrinArgSelect::Type::I8:

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

140 break;

141 case IntrinArgSelect::Type::I32:

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

143 break;

144 }

145 }

146 } else if (IsVectorArgExpansion) {

148 } else {

150 }

151

155 return E;

156

160 });

161 }

162

163 [[nodiscard]] bool replaceFunctionWithNamedStructOp(

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

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

170 if (IsVectorArgExpansion) {

173 } else

175

179 return E;

180 if (Error E = ReplaceUses(CI, *OpCall))

181 return E;

182

184 });

185 }

186

187

188

189

190

191

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

196 return Cast;

197 }

198

199 void cleanupHandleCasts() {

202

203 for (CallInst *Cast : CleanupCasts) {

204

205

206

207

209

210

211

214 continue;

215 }

216

217

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

220 "Unbalanced pair of temporary handle casts");

223 }

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

227 }

228

229

233 F->eraseFromParent();

234

235 CleanupCasts.clear();

236 }

237

238

239

240

241

242

243 void removeResourceGlobals(CallInst *CI) {

245 if (StoreInst *Store = dyn_cast(User)) {

247 Store->eraseFromParent();

248 if (GlobalVariable *GV = dyn_cast(V))

249 if (GV->use_empty()) {

250 GV->removeDeadConstantUsers();

251 GV->eraseFromParent();

252 }

253 }

254 }

255 }

256

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

261

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

264

265 auto *It = DBM.find(CI);

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

268

269 const auto &Binding = RI.getBinding();

271

273 if (Binding.LowerBound != 0)

275 ConstantInt::get(Int32Ty, Binding.LowerBound));

276

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

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

284 return E;

285

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

287

288 removeResourceGlobals(CI);

289

293 });

294 }

295

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

299

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

302

303 auto *It = DBM.find(CI);

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

306

307 const auto &Binding = RI.getBinding();

310

312 if (Binding.LowerBound != 0)

314 ConstantInt::get(Int32Ty, Binding.LowerBound));

315

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

318

319

320

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

322 uint32_t UpperBound = Binding.Size == Unbounded

323 ? Unbounded

324 : Binding.LowerBound + Binding.Size - 1;

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

326 Binding.Space, RC);

327 std::array<Value *, 3> BindArgs{ResBind, IndexOp, CI->getArgOperand(4)};

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

331 return E;

332

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

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

336 OpCode::AnnotateHandle, AnnotateArgs,

339 return E;

340

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

342

343 removeResourceGlobals(CI);

344

347

349 });

350 }

351

352

353

354

355 bool lowerHandleFromBinding(Function &F) {

358 return lowerToCreateHandle(F);

359 return lowerToBindAndAnnotateHandle(F);

360 }

361

364 if (auto *EVI = dyn_cast(U.getUser())) {

365

366 if (EVI->getNumIndices() != 1)

368 "Splitdouble has only 2 elements");

369 EVI->setOperand(0, Op);

370 } else {

371 return make_error(

372 "Splitdouble use is not ExtractValueInst",

374 }

375 }

376

378

380 }

381

382

383

386

389

390 if (HasCheckBit) {

391 auto *ST = cast(OldTy);

392

393 Value *CheckOp = nullptr;

396 if (auto *EVI = dyn_cast(U.getUser())) {

399

400 if (Indices[0] != 1)

401 continue;

402 if (!CheckOp) {

405 OpCode::CheckAccessFullyMapped, {NewEVI},

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

408 Int32Ty);

410 return E;

411 CheckOp = *OpCall;

412 }

413 EVI->replaceAllUsesWith(CheckOp);

414 EVI->eraseFromParent();

415 }

416 }

417

419

422 }

423

425 isa(*OldResult->user_begin()) &&

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

427 OldResult = cast(*OldResult->user_begin());

428 OldTy = ST->getElementType(0);

429 }

430

431

432 if (!isa(OldTy)) {

436 if (OldResult != Intrin) {

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

439 }

441 }

442

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

445

446

447

449 if (auto *EEI = dyn_cast(U.getUser())) {

450 if (auto *IndexOp = dyn_cast(EEI->getIndexOperand())) {

451 size_t IndexVal = IndexOp->getZExtValue();

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

453 if (!Extracts[IndexVal])

456 EEI->eraseFromParent();

457 } else {

459 }

460 }

461 }

462

463 const auto *VecTy = cast(OldTy);

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

465

466

467

468 if (!DynamicAccesses.empty()) {

470 Constant *Zero = ConstantInt::get(Int32Ty, 0);

471

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

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

475

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

477 if (!Extracts[I])

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

482 }

483

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

489 EEI->eraseFromParent();

490 }

491 }

492

493

494

495

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

498 if (!Extracts[I])

500

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

505 }

506

508 if (OldResult != Intrin) {

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

511 }

512

514 }

515

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

519

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

522

527

529 if (HasCheckBit)

530 OldTy = cast(OldTy)->getElementType(0);

532

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

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

537 return E;

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

539 return E;

540

542 });

543 }

544

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

552

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

555

556 Type *OldTy = cast(CI->getType())->getElementType(0);

559

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

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

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

569

572 ? OpBuilder.tryCreateOp(OpCode::RawBufferLoad,

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

575 : OpBuilder.tryCreateOp(OpCode::BufferLoad,

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

577 NewRetTy);

579 return E;

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

581 return E;

582

584 });

585 }

586

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

590

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

596

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

598

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

601

603 return E;

604

608 });

609 }

610

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

612

613

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

615 F.eraseFromParent();

616 return false;

617 }

618

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

626

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

629

634

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

638

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

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

642

643

644 if (!IsRaw && NumElements != 4)

645 return make_error(

646 "typedBufferStore data must be a vector of 4 elements",

648 else if (NumElements > 4)

649 return make_error(

650 "rawBufferStore data must have at most 4 elements",

652

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

654 if (DataTy == ScalarTy)

655 DataElements[0] = Data;

656 else {

657

658

659

660 auto *IEI = dyn_cast(Data);

661 while (IEI) {

662 auto *IndexOp = dyn_cast(IEI->getOperand(2));

663 if (!IndexOp)

664 break;

665 size_t IndexVal = IndexOp->getZExtValue();

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

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

668 IEI = dyn_cast(IEI->getOperand(0));

669 }

670 }

671

672

673

674

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

676 if (DataElements[I] == nullptr)

677 DataElements[I] =

679

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

681 if (DataElements[I] == nullptr)

683

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

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

688 if (IsRaw && DXILVersion >= VersionTuple(1, 2)) {

689 Op = OpCode::RawBufferStore;

690

691 Args.push_back(

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

693 }

697 return E;

698

700

701 auto *IEI = dyn_cast(Data);

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

704 IEI = dyn_cast(IEI->getOperand(0));

706 }

707

709 });

710 }

711

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

715

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

720

722 Type *FRT = F.getReturnType();

723 if (const auto *VT = dyn_cast(FRT))

725

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

729 return E;

730

731

732 if (FRT->isIntOrIntVectorTy(32)) {

733 CI->replaceAllUsesWith(*OpCall);

734 CI->eraseFromParent();

735 return Error::success();

736 }

737

738 unsigned CastOp;

739 unsigned CastOp2;

740 if (FRT->isIntOrIntVectorTy(16)) {

741 CastOp = Instruction::ZExt;

742 CastOp2 = Instruction::SExt;

743 } else {

744 assert(FRT->isIntOrIntVectorTy(64) &&

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

746 is supported.");

747 CastOp = Instruction::Trunc;

748 CastOp2 = Instruction::Trunc;

749 }

750

751

752

753 bool NeedsCast = false;

755 Instruction *I = dyn_cast(User);

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

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

758 I->replaceAllUsesWith(*OpCall);

759 I->eraseFromParent();

760 } else

761 NeedsCast = true;

762 }

763

764

765

766

767

768 if (NeedsCast) {

772 }

773

776 });

777 }

778

779 bool lowerIntrinsics() {

780 bool Updated = false;

781 bool HasErrors = false;

782

784 if (F.isDeclaration())

785 continue;

787 switch (ID) {

788 default:

789 continue;

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

791 case Intrin: \

792 HasErrors |= replaceFunctionWithOp( \

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

794 break;

795#include "DXILOperation.inc"

796 case Intrinsic::dx_resource_handlefrombinding:

797 HasErrors |= lowerHandleFromBinding(F);

798 break;

799 case Intrinsic::dx_resource_getpointer:

800 HasErrors |= lowerGetPointer(F);

801 break;

802 case Intrinsic::dx_resource_load_typedbuffer:

803 HasErrors |= lowerTypedBufferLoad(F, true);

804 break;

805 case Intrinsic::dx_resource_store_typedbuffer:

806 HasErrors |= lowerBufferStore(F, false);

807 break;

808 case Intrinsic::dx_resource_load_rawbuffer:

809 HasErrors |= lowerRawBufferLoad(F);

810 break;

811 case Intrinsic::dx_resource_store_rawbuffer:

812 HasErrors |= lowerBufferStore(F, true);

813 break;

814 case Intrinsic::dx_resource_updatecounter:

815 HasErrors |= lowerUpdateCounter(F);

816 break;

817

818

819 case Intrinsic::dx_splitdouble:

820 HasErrors |= replaceFunctionWithNamedStructOp(

821 F, OpCode::SplitDouble,

824 return replaceSplitDoubleCallUsages(CI, Op);

825 });

826 break;

827 case Intrinsic::ctpop:

828 HasErrors |= lowerCtpopToCountBits(F);

829 break;

830 }

831 Updated = true;

832 }

833 if (Updated && !HasErrors)

834 cleanupHandleCasts();

835

836 return Updated;

837 }

838};

839}

840

844

845 bool MadeChanges = OpLowerer(M, DBM, DRTM).lowerIntrinsics();

846 if (!MadeChanges)

852 return PA;

853}

854

855namespace {

856class DXILOpLoweringLegacy : public ModulePass {

857public:

858 bool runOnModule(Module &M) override {

860 getAnalysis().getBindingMap();

862 getAnalysis().getResourceTypeMap();

863

864 return OpLowerer(M, DBM, DRTM).lowerIntrinsics();

865 }

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

868

869 static char ID;

877 }

878};

879char DXILOpLoweringLegacy::ID = 0;

880}

881

883 false, false)

888

890 return new DXILOpLoweringLegacy();

891}

for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))

ReachingDefAnalysis InstSet & ToRemove

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

static bool isVectorArgExpansion(Function &F)

static SmallVector< Value * > argVectorFlatten(CallInst *Orig, IRBuilder<> &Builder)

static SmallVector< Value * > populateOperands(Value *Arg, IRBuilder<> &Builder)

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

This header defines various interfaces for pass management in LLVM.

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)

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

This file defines the SmallVector class.

A container for analyses that lazily runs them and caches their results.

PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)

Get the result of an analysis pass for a given IR unit.

Represent the analysis usage information of a pass.

AnalysisUsage & addRequired()

AnalysisUsage & addPreserved()

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

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

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.

This is an important base class in LLVM.

This class represents an Operation in the Expression.

iterator find(const CallInst *Key)

PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)

The legacy pass manager's analysis pass to compute DXIL resource information.

A parsed version of the target data layout string in and methods for querying it.

Diagnostic information for unsupported feature in backend.

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

Error takeError()

Take ownership of the stored error.

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

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

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="")

CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")

Create a call to intrinsic ID with Args, mangled using Types.

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.

This provides a uniform API for creating instructions and inserting them into a basic block: either a...

This instruction inserts a single (scalar) element into a VectorType value.

const DebugLoc & getDebugLoc() const

Return the debug location for this node as a DebugLoc.

InstListType::iterator eraseFromParent()

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

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.

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.

void preserve()

Mark an analysis as preserved.

iterator erase(const_iterator CI)

void append(ItTy in_start, ItTy in_end)

Add the specified range to the end of the SmallVector.

void push_back(const T &Elt)

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

An instruction for storing to memory.

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

Triple - Helper class for working with autoconf configuration names.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

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

static IntegerType * getInt32Ty(LLVMContext &C)

Type * getScalarType() const

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

static UndefValue * get(Type *T)

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

A Use represents the edge between a Value definition and its users.

Value * getOperand(unsigned i) const

unsigned getNumOperands() const

LLVM Value Representation.

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.

void replaceAllUsesWith(Value *V)

Change all uses of this to point to a new Value.

iterator_range< user_iterator > users()

LLVMContext & getContext() const

All values hold a context through their type.

iterator_range< use_iterator > uses()

StringRef getName() const

Return a constant reference to the value's name.

Represents a version number in the form major[.minor[.subminor[.build]]].

StructType * getResRetType(Type *ElementTy)

Get a dx.types.ResRet type with the given element type.

StructType * getSplitDoubleType(LLVMContext &Context)

Get the dx.types.splitdouble type.

Expected< CallInst * > tryCreateOp(dxil::OpCode Op, ArrayRef< Value * > Args, const Twine &Name="", Type *RetTy=nullptr)

Try to create a call instruction for the given DXIL op.

Constant * getResBind(uint32_t LowerBound, uint32_t UpperBound, uint32_t SpaceID, dxil::ResourceClass RC)

Get a constant dx.types.ResBind value.

Constant * getResProps(uint32_t Word0, uint32_t Word1)

Get a constant dx.types.ResourceProperties value.

StructType * getHandleType()

Get the dx.types.Handle type.

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

TargetExtType * getHandleTy() const

const ResourceBinding & getBinding() const

dxil::ResourceClass getResourceClass() const

Wrapper pass for the legacy pass manager.

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

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.

NodeAddr< DefNode * > Def

This is an optimization pass for GlobalISel generic memory operations.

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)

Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)

Create formatted StringError object.

void sort(IteratorTy Start, IteratorTy End)

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

Returns underlying integer value of an enum.

ModulePass * createDXILOpLoweringLegacyPass()

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

const char * toString(DWARFSectionKind Kind)

This struct is a compact representation of a valid (non-zero power of two) alignment.