25#include "llvm/IR/IntrinsicsDirectX.h"
34#define DEBUG_TYPE "dxil-op-lower"
52 : M(M), OpBuilder(M), DRM(DRM), DRTM(DRTM), MMDI(MMDI) {}
64 if (
Error E = ReplaceCall(CI)) {
65 std::string Message(
toString(std::move(
E)));
77 struct IntrinArgSelect {
79#define DXIL_OP_INTRINSIC_ARG_SELECT_TYPE(name) name,
80#include "DXILOperation.inc"
90 Error replaceNamedStructUses(CallInst *Intrin, CallInst *DXILOp) {
93 if (!IntrinTy->isLayoutIdentical(DXILOpTy))
95 "Type mismatch between intrinsic and DXIL op",
100 EVI->setOperand(0, DXILOp);
102 IVI->setOperand(0, DXILOp);
105 "be used by insert- and extractvalue",
113 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
114 OpBuilder.getIRB().SetInsertPoint(CI);
116 if (ArgSelects.
size()) {
117 for (
const IntrinArgSelect &
A : ArgSelects) {
119 case IntrinArgSelect::Type::Index:
122 case IntrinArgSelect::Type::I8:
123 Args.push_back(OpBuilder.getIRB().getInt8((uint8_t)
A.Value));
125 case IntrinArgSelect::Type::I32:
126 Args.push_back(OpBuilder.getIRB().getInt32(
A.Value));
134 Expected<CallInst *> OpCall =
135 OpBuilder.tryCreateOp(DXILOp, Args, CI->
getName(),
F.getReturnType());
140 if (
Error E = replaceNamedStructUses(CI, *OpCall))
156 CallInst *Cast = OpBuilder.getIRB().CreateIntrinsic(
157 Intrinsic::dx_resource_casthandle, {Ty,
V->getType()}, {
V});
158 CleanupCasts.push_back(Cast);
162 void cleanupHandleCasts() {
166 for (CallInst *Cast : CleanupCasts) {
175 if (Cast->
getType() != OpBuilder.getHandleType()) {
182 assert(
Def->getIntrinsicID() == Intrinsic::dx_resource_casthandle &&
183 "Unbalanced pair of temporary handle casts");
195 for (Function *
F : CastFns)
196 F->eraseFromParent();
198 CleanupCasts.clear();
201 void cleanupNonUniformResourceIndexCalls() {
212 CleanupNURI->eraseFromParent();
213 CleanupNURI =
nullptr;
221 void removeResourceGlobals(CallInst *CI) {
225 Store->eraseFromParent();
227 if (GV->use_empty()) {
228 GV->removeDeadConstantUsers();
229 GV->eraseFromParent();
235 void replaceHandleFromBindingCall(CallInst *CI,
Value *Replacement) {
237 Intrinsic::dx_resource_handlefrombinding);
239 removeResourceGlobals(CI);
246 if (NameGlobal && NameGlobal->use_empty())
247 NameGlobal->removeFromParent();
250 bool hasNonUniformIndex(
Value *IndexOp) {
257 while (!WorkList.
empty()) {
261 Intrinsic::dx_resource_nonuniformindex)
275 [[nodiscard]]
bool lowerToCreateHandle(Function &
F) {
281 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
284 auto *It = DRM.find(CI);
285 assert(It != DRM.end() &&
"Resource not in map?");
286 dxil::ResourceInfo &RI = *It;
296 bool HasNonUniformIndex =
297 (
Binding.Size == 1) ?
false : hasNonUniformIndex(IndexOp);
298 std::array<Value *, 4>
Args{
301 ConstantInt::get(Int1Ty, HasNonUniformIndex)};
302 Expected<CallInst *> OpCall =
303 OpBuilder.tryCreateOp(OpCode::CreateHandle, Args, CI->
getName());
307 Value *Cast = createTmpHandleCast(*OpCall, CI->
getType());
308 replaceHandleFromBindingCall(CI, Cast);
313 [[nodiscard]]
bool lowerToBindAndAnnotateHandle(Function &
F) {
318 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
321 auto *It = DRM.find(CI);
322 assert(It != DRM.end() &&
"Resource not in map?");
323 dxil::ResourceInfo &RI = *It;
326 dxil::ResourceTypeInfo &RTI = DRTM[RI.
getHandleTy()];
334 std::pair<uint32_t, uint32_t> Props =
339 uint32_t Unbounded = std::numeric_limits<uint32_t>::max();
340 uint32_t UpperBound =
Binding.Size == 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());
354 std::array<Value *, 2> AnnotateArgs{
355 *OpBind, OpBuilder.getResProps(Props.first, Props.second)};
356 Expected<CallInst *> OpAnnotate = OpBuilder.tryCreateOp(
357 OpCode::AnnotateHandle, AnnotateArgs,
362 Value *Cast = createTmpHandleCast(*OpAnnotate, CI->
getType());
363 replaceHandleFromBindingCall(CI, Cast);
371 bool lowerHandleFromBinding(Function &
F) {
372 if (MMDI.DXILVersion < VersionTuple(1, 6))
373 return lowerToCreateHandle(
F);
374 return lowerToBindAndAnnotateHandle(
F);
379 Error replaceResRetUses(CallInst *Intrin, CallInst *
Op,
bool HasCheckBit) {
388 Value *CheckOp =
nullptr;
392 ArrayRef<unsigned> Indices = EVI->getIndices();
399 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(
400 OpCode::CheckAccessFullyMapped, {NewEVI},
408 EVI->replaceAllUsesWith(CheckOp);
409 EVI->eraseFromParent();
421 "Expected only use to be extract of first element");
423 OldTy =
ST->getElementType(0);
431 if (OldResult != Intrin) {
438 std::array<Value *, 4> Extracts = {};
446 size_t IndexVal = IndexOp->getZExtValue();
447 assert(IndexVal < 4 &&
"Index into buffer load out of range");
448 if (!Extracts[IndexVal])
451 EEI->eraseFromParent();
459 const unsigned N = VecTy->getNumElements();
463 if (!DynamicAccesses.
empty()) {
467 Type *ElTy = VecTy->getElementType();
468 Type *ArrayTy = ArrayType::get(ElTy,
N);
471 for (
int I = 0,
E =
N;
I !=
E; ++
I) {
479 for (ExtractElementInst *EEI : DynamicAccesses) {
481 {
Zero, EEI->getIndexOperand()});
484 EEI->eraseFromParent();
492 for (
int I = 0,
E =
N;
I !=
E; ++
I)
497 for (
int I = 0,
E =
N;
I !=
E; ++
I)
503 if (OldResult != Intrin) {
511 [[nodiscard]]
bool lowerTypedBufferLoad(Function &
F,
bool HasCheckBit) {
515 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
519 createTmpHandleCast(CI->
getArgOperand(0), OpBuilder.getHandleType());
528 std::array<Value *, 3>
Args{Handle, Index0, Index1};
529 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(
530 OpCode::BufferLoad, Args, CI->
getName(), NewRetTy);
533 if (
Error E = replaceResRetUses(CI, *OpCall, HasCheckBit))
540 [[nodiscard]]
bool lowerRawBufferLoad(Function &
F) {
541 const DataLayout &
DL =
F.getDataLayout();
546 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
551 Type *NewRetTy = OpBuilder.getResRetType(ScalarTy);
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());
563 Expected<CallInst *> OpCall =
564 MMDI.DXILVersion >= VersionTuple(1, 2)
565 ? OpBuilder.tryCreateOp(OpCode::RawBufferLoad,
568 : OpBuilder.tryCreateOp(OpCode::BufferLoad,
569 {Handle, Index0, Index1}, CI->
getName(),
573 if (
Error E = replaceResRetUses(CI, *OpCall,
true))
580 [[nodiscard]]
bool lowerCBufferLoad(Function &
F) {
583 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
588 Type *NewRetTy = OpBuilder.getCBufRetType(ScalarTy);
591 createTmpHandleCast(CI->
getArgOperand(0), OpBuilder.getHandleType());
594 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(
595 OpCode::CBufferLoadLegacy, {Handle,
Index}, CI->
getName(), NewRetTy);
598 if (
Error E = replaceNamedStructUses(CI, *OpCall))
606 [[nodiscard]]
bool lowerUpdateCounter(Function &
F) {
610 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
613 createTmpHandleCast(CI->
getArgOperand(0), OpBuilder.getHandleType());
616 std::array<Value *, 2>
Args{Handle, Op1};
618 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(
630 [[nodiscard]]
bool lowerGetPointer(Function &
F) {
633 assert(
F.user_empty() &&
"getpointer operations should have been removed");
638 [[nodiscard]]
bool lowerBufferStore(Function &
F,
bool IsRaw) {
639 const DataLayout &
DL =
F.getDataLayout();
644 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
648 createTmpHandleCast(CI->
getArgOperand(0), OpBuilder.getHandleType());
656 uint64_t NumElements =
657 DL.getTypeSizeInBits(DataTy) /
DL.getTypeSizeInBits(ScalarTy);
659 ConstantInt::get(Int8Ty, IsRaw ? ~(~0U << NumElements) : 15U);
664 "Buffer store data must have at most 4 elements",
667 std::array<Value *, 4> DataElements{
nullptr,
nullptr,
nullptr,
nullptr};
668 if (DataTy == ScalarTy)
669 DataElements[0] =
Data;
679 size_t IndexVal = IndexOp->getZExtValue();
680 assert(IndexVal < 4 &&
"Too many elements for buffer store");
681 DataElements[IndexVal] = IEI->getOperand(1);
689 for (
int I = 0,
E = NumElements;
I <
E; ++
I)
690 if (DataElements[
I] ==
nullptr)
697 for (
int I = NumElements,
E = 4;
I <
E; ++
I)
698 if (DataElements[
I] ==
nullptr)
703 Handle, Index0, Index1, DataElements[0],
704 DataElements[1], DataElements[2], DataElements[3],
Mask};
705 if (IsRaw && MMDI.DXILVersion >= VersionTuple(1, 2)) {
706 Op = OpCode::RawBufferStore;
709 ConstantInt::get(
Int32Ty,
DL.getPrefTypeAlign(ScalarTy).value()));
711 Expected<CallInst *> OpCall =
712 OpBuilder.tryCreateOp(
Op, Args, CI->
getName());
719 while (IEI && IEI->use_empty()) {
720 InsertElementInst *Tmp = IEI;
729 [[nodiscard]]
bool lowerCtpopToCountBits(Function &
F) {
733 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
739 Type *FRT =
F.getReturnType();
741 RetTy = VectorType::get(RetTy, VT);
743 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(
744 dxil::OpCode::CountBits, Args, CI->
getName(), RetTy);
758 CastOp = Instruction::ZExt;
759 CastOp2 = Instruction::SExt;
762 "Currently only lowering 16, 32, or 64 bit ctpop to CountBits \
764 CastOp = Instruction::Trunc;
765 CastOp2 = Instruction::Trunc;
770 bool NeedsCast =
false;
773 if (
I && (
I->getOpcode() == CastOp ||
I->getOpcode() == CastOp2) &&
774 I->getType() == RetTy) {
775 I->replaceAllUsesWith(*OpCall);
776 I->eraseFromParent();
796 [[nodiscard]]
bool lowerLifetimeIntrinsic(Function &
F) {
798 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
802 "Expected operand of lifetime intrinsic to be a pointer");
804 auto ZeroOrUndef = [&](
Type *Ty) {
805 return MMDI.ValidatorVersion < VersionTuple(1, 6)
807 : UndefValue::
get(Ty);
810 Value *Val =
nullptr;
812 if (GV->hasInitializer() || GV->isExternallyInitialized())
814 Val = ZeroOrUndef(GV->getValueType());
816 Val = ZeroOrUndef(AI->getAllocatedType());
818 assert(Val &&
"Expected operand of lifetime intrinsic to be a global "
819 "variable or alloca instruction");
827 [[nodiscard]]
bool lowerIsFPClass(Function &
F) {
831 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
840 switch (TCI->getZExtValue()) {
841 case FPClassTest::fcInf:
842 OpCode = dxil::OpCode::IsInf;
844 case FPClassTest::fcNan:
845 OpCode = dxil::OpCode::IsNaN;
847 case FPClassTest::fcNormal:
848 OpCode = dxil::OpCode::IsNormal;
850 case FPClassTest::fcFinite:
851 OpCode = dxil::OpCode::IsFinite;
854 SmallString<128> Msg =
855 formatv(
"Unsupported FPClassTest {0} for DXIL Op Lowering",
856 TCI->getZExtValue());
860 Expected<CallInst *> OpCall =
871 bool lowerIntrinsics() {
872 bool Updated =
false;
873 bool HasErrors =
false;
876 if (!
F.isDeclaration())
882 case Intrinsic::dx_resource_casthandle:
884 case Intrinsic::dbg_value:
893 SmallString<128> Msg =
formatv(
894 "Unsupported intrinsic {0} for DXIL lowering",
F.getName());
895 M.getContext().emitError(Msg);
900#define DXIL_OP_INTRINSIC(OpCode, Intrin, ...) \
902 HasErrors |= replaceFunctionWithOp( \
903 F, OpCode, ArrayRef<IntrinArgSelect>{__VA_ARGS__}); \
905#include "DXILOperation.inc"
906 case Intrinsic::dx_resource_handlefrombinding:
907 HasErrors |= lowerHandleFromBinding(
F);
909 case Intrinsic::dx_resource_getpointer:
910 HasErrors |= lowerGetPointer(
F);
912 case Intrinsic::dx_resource_nonuniformindex:
914 "overloaded llvm.dx.resource.nonuniformindex intrinsics?");
917 case Intrinsic::dx_resource_load_typedbuffer:
918 HasErrors |= lowerTypedBufferLoad(
F,
true);
920 case Intrinsic::dx_resource_store_typedbuffer:
921 HasErrors |= lowerBufferStore(
F,
false);
923 case Intrinsic::dx_resource_load_rawbuffer:
924 HasErrors |= lowerRawBufferLoad(
F);
926 case Intrinsic::dx_resource_store_rawbuffer:
927 HasErrors |= lowerBufferStore(
F,
true);
929 case Intrinsic::dx_resource_load_cbufferrow_2:
930 case Intrinsic::dx_resource_load_cbufferrow_4:
931 case Intrinsic::dx_resource_load_cbufferrow_8:
932 HasErrors |= lowerCBufferLoad(
F);
934 case Intrinsic::dx_resource_updatecounter:
935 HasErrors |= lowerUpdateCounter(
F);
937 case Intrinsic::ctpop:
938 HasErrors |= lowerCtpopToCountBits(
F);
940 case Intrinsic::lifetime_start:
941 case Intrinsic::lifetime_end:
945 if (MMDI.DXILVersion < VersionTuple(1, 6))
946 HasErrors |= lowerLifetimeIntrinsic(
F);
951 case Intrinsic::is_fpclass:
952 HasErrors |= lowerIsFPClass(
F);
957 if (Updated && !HasErrors) {
958 cleanupHandleCasts();
959 cleanupNonUniformResourceIndexCalls();
972 const bool MadeChanges = OpLowerer(M, DRM, DRTM, MMDI).lowerIntrinsics();
984class DXILOpLoweringLegacy :
public ModulePass {
986 bool runOnModule(
Module &M)
override {
988 getAnalysis<DXILResourceWrapperPass>().getResourceMap();
990 getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
992 getAnalysis<DXILMetadataAnalysisWrapperPass>().getModuleMetadata();
994 return OpLowerer(M, DRM, DRTM, MMDI).lowerIntrinsics();
996 StringRef getPassName()
const override {
return "DXIL Op Lowering"; }
997 DXILOpLoweringLegacy() : ModulePass(
ID) {}
1000 void getAnalysisUsage(llvm::AnalysisUsage &AU)
const override {
1003 AU.
addRequired<DXILMetadataAnalysisWrapperPass>();
1010char DXILOpLoweringLegacy::ID = 0;
1021 return new DXILOpLoweringLegacy();
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)
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.
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.
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<X> - 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<X> - 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.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.