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",
110 bool isFast(FastMathFlags Flags) {
114 Flags.noSignedZeros() &&
Flags.allowReciprocal() &&
118 void setDxPrecise(CallInst *CI) {
119 const StringRef
Key =
"dx.precise";
133 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
134 OpBuilder.getIRB().SetInsertPoint(CI);
136 if (ArgSelects.
size()) {
137 for (
const IntrinArgSelect &
A : ArgSelects) {
139 case IntrinArgSelect::Type::Index:
142 case IntrinArgSelect::Type::I8:
143 Args.push_back(OpBuilder.getIRB().getInt8((uint8_t)
A.Value));
145 case IntrinArgSelect::Type::I32:
146 Args.push_back(OpBuilder.getIRB().getInt32(
A.Value));
154 Expected<CallInst *> OpCall =
155 OpBuilder.tryCreateOp(DXILOp, Args, CI->
getName(),
F.getReturnType());
161 setDxPrecise(*OpCall);
164 if (
Error E = replaceNamedStructUses(CI, *OpCall))
180 CallInst *Cast = OpBuilder.getIRB().CreateIntrinsic(
181 Intrinsic::dx_resource_casthandle, {Ty,
V->getType()}, {
V});
182 CleanupCasts.push_back(Cast);
186 void cleanupHandleCasts() {
190 for (CallInst *Cast : CleanupCasts) {
199 if (Cast->
getType() != OpBuilder.getHandleType()) {
206 assert(
Def->getIntrinsicID() == Intrinsic::dx_resource_casthandle &&
207 "Unbalanced pair of temporary handle casts");
219 for (Function *
F : CastFns)
220 F->eraseFromParent();
222 CleanupCasts.clear();
225 void cleanupNonUniformResourceIndexCalls() {
236 CleanupNURI->eraseFromParent();
237 CleanupNURI =
nullptr;
245 void removeResourceGlobals(CallInst *CI) {
249 Store->eraseFromParent();
251 if (GV->use_empty()) {
252 GV->removeDeadConstantUsers();
253 GV->eraseFromParent();
259 void replaceHandleFromBindingCall(CallInst *CI,
Value *Replacement) {
261 Intrinsic::dx_resource_handlefrombinding);
263 removeResourceGlobals(CI);
270 if (NameGlobal && NameGlobal->use_empty())
271 NameGlobal->removeFromParent();
274 bool hasNonUniformIndex(
Value *IndexOp) {
278 SmallVector<Value *, 16> Worklist;
279 SmallPtrSet<Value *, 16> Visited;
282 while (!Worklist.
empty()) {
288 if (!Visited.
insert(V).second)
292 if (CI->
getIntrinsicID() == Intrinsic::dx_resource_nonuniformindex)
298 for (
Value *Incoming :
Phi->incoming_values())
304 if (Inst->getNumOperands() > 0 && !Inst->isTerminator())
305 for (
Value *
Op : Inst->operands())
311 Error validateRawBufferElementIndex(
Value *Resource,
Value *ElementIndex) {
316 if (IsStructured && IsPoison)
318 "Element index of structured buffer may not be poison",
321 if (!IsStructured && !IsPoison)
323 "Element index of raw buffer must be poison",
329 [[nodiscard]]
bool lowerToCreateHandle(Function &
F) {
335 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
338 auto *It = DRM.find(CI);
339 assert(It != DRM.end() &&
"Resource not in map?");
340 dxil::ResourceInfo &RI = *It;
350 bool HasNonUniformIndex =
351 (
Binding.Size == 1) ?
false : hasNonUniformIndex(IndexOp);
352 std::array<Value *, 4>
Args{
355 ConstantInt::get(Int1Ty, HasNonUniformIndex)};
356 Expected<CallInst *> OpCall =
357 OpBuilder.tryCreateOp(OpCode::CreateHandle, Args, CI->
getName());
361 Value *Cast = createTmpHandleCast(*OpCall, CI->
getType());
362 replaceHandleFromBindingCall(CI, Cast);
367 [[nodiscard]]
bool lowerToBindAndAnnotateHandle(Function &
F) {
372 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
375 auto *It = DRM.find(CI);
376 assert(It != DRM.end() &&
"Resource not in map?");
377 dxil::ResourceInfo &RI = *It;
380 dxil::ResourceTypeInfo &RTI = DRTM[RI.
getHandleTy()];
388 std::pair<uint32_t, uint32_t> Props =
393 uint32_t UpperBound =
Binding.Size == 0
394 ? std::numeric_limits<uint32_t>::max()
396 Constant *ResBind = OpBuilder.getResBind(
Binding.LowerBound, UpperBound,
398 bool NonUniformIndex =
399 (
Binding.Size == 1) ?
false : hasNonUniformIndex(IndexOp);
400 Constant *NonUniformOp = ConstantInt::get(Int1Ty, NonUniformIndex);
401 std::array<Value *, 3> BindArgs{ResBind, IndexOp, NonUniformOp};
402 Expected<CallInst *> OpBind = OpBuilder.tryCreateOp(
403 OpCode::CreateHandleFromBinding, BindArgs, CI->
getName());
407 std::array<Value *, 2> AnnotateArgs{
408 *OpBind, OpBuilder.getResProps(Props.first, Props.second)};
409 Expected<CallInst *> OpAnnotate = OpBuilder.tryCreateOp(
410 OpCode::AnnotateHandle, AnnotateArgs,
415 Value *Cast = createTmpHandleCast(*OpAnnotate, CI->
getType());
416 replaceHandleFromBindingCall(CI, Cast);
424 bool lowerHandleFromBinding(Function &
F) {
425 if (MMDI.DXILVersion < VersionTuple(1, 6))
426 return lowerToCreateHandle(
F);
427 return lowerToBindAndAnnotateHandle(
F);
432 Error replaceResRetUses(CallInst *Intrin, CallInst *
Op,
bool HasCheckBit) {
441 Value *CheckOp =
nullptr;
445 ArrayRef<unsigned> Indices = EVI->getIndices();
452 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(
453 OpCode::CheckAccessFullyMapped, {NewEVI},
461 EVI->replaceAllUsesWith(CheckOp);
462 EVI->eraseFromParent();
474 "Expected only use to be extract of first element");
476 OldTy =
ST->getElementType(0);
484 if (OldResult != Intrin) {
491 std::array<Value *, 4> Extracts = {};
499 size_t IndexVal = IndexOp->getZExtValue();
500 assert(IndexVal < 4 &&
"Index into buffer load out of range");
501 if (!Extracts[IndexVal])
504 EEI->eraseFromParent();
512 const unsigned N = VecTy->getNumElements();
516 if (!DynamicAccesses.
empty()) {
520 Type *ElTy = VecTy->getElementType();
521 Type *ArrayTy = ArrayType::get(ElTy,
N);
524 for (
int I = 0,
E =
N;
I !=
E; ++
I) {
532 for (ExtractElementInst *EEI : DynamicAccesses) {
534 {
Zero, EEI->getIndexOperand()});
537 EEI->eraseFromParent();
545 for (
int I = 0,
E =
N;
I !=
E; ++
I)
550 for (
int I = 0,
E =
N;
I !=
E; ++
I)
556 if (OldResult != Intrin) {
564 [[nodiscard]]
bool lowerTypedBufferLoad(Function &
F,
bool HasCheckBit) {
568 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
572 createTmpHandleCast(CI->
getArgOperand(0), OpBuilder.getHandleType());
581 std::array<Value *, 3>
Args{Handle, Index0, Index1};
582 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(
583 OpCode::BufferLoad, Args, CI->
getName(), NewRetTy);
586 if (
Error E = replaceResRetUses(CI, *OpCall, HasCheckBit))
596 static void extractElementsIntoArgs(
IRBuilder<> &IRB,
598 unsigned ArgIdx,
Value *Src,
599 unsigned MaxElements) {
600 Type *Ty = Src->getType();
602 unsigned Count = VecTy->getNumElements();
603 assert(
Count <= MaxElements &&
"Expected at most 3 elements in vector");
604 for (
unsigned I = 0;
I <
Count; ++
I)
613 static void extractNonZeroOffsets(
IRBuilder<> &IRB,
615 unsigned ArgIdx,
Value *Offsets,
616 unsigned MaxElements) {
618 bool OffsetsAreZero = COff && COff->isNullValue();
620 extractElementsIntoArgs(IRB, Args, ArgIdx, Offsets, MaxElements);
623 [[nodiscard]]
bool lowerTextureLoad(Function &
F) {
627 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
631 createTmpHandleCast(CI->
getArgOperand(0), OpBuilder.getHandleType());
644 extractElementsIntoArgs(IRB, Args, 2, Coords, 3);
645 extractNonZeroOffsets(IRB, Args, 5, Offsets, 3);
647 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(
648 OpCode::TextureLoad, Args, CI->
getName(), NewRetTy);
651 if (
Error E = replaceResRetUses(CI, *OpCall,
false))
661 [[nodiscard]]
bool lowerSampleOp(
662 Function &
F,
OpCode Op,
unsigned CoordsIdx,
unsigned OffsetsIdx,
664 SmallVectorImpl<Value *> &)> EmitExtraArgs) {
666 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
670 createTmpHandleCast(CI->
getArgOperand(0), OpBuilder.getHandleType());
672 createTmpHandleCast(CI->
getArgOperand(1), OpBuilder.getHandleType());
683 UndefF, UndefI, UndefI, UndefI};
686 extractElementsIntoArgs(IRB, Args, 2, Coords, 4);
687 extractNonZeroOffsets(IRB, Args, 6, Offsets, 3);
690 EmitExtraArgs(IRB, CI, Args);
692 Expected<CallInst *> OpCall =
693 OpBuilder.tryCreateOp(
Op, Args, CI->
getName(), NewRetTy);
696 if (
Error E = replaceResRetUses(CI, *OpCall,
false))
703 [[nodiscard]]
bool lowerSample(Function &
F,
bool HasClamp) {
704 return lowerSampleOp(
F, OpCode::Sample, 2, 3,
706 SmallVectorImpl<Value *> &Args) {
714 [[nodiscard]]
bool lowerSampleBias(Function &
F,
bool HasClamp) {
715 return lowerSampleOp(
716 F, OpCode::SampleBias, 2, 4,
718 SmallVectorImpl<Value *> &Args) {
727 [[nodiscard]]
bool lowerSampleLevel(Function &
F) {
728 return lowerSampleOp(
729 F, OpCode::SampleLevel, 2, 4,
730 [](
IRBuilder<> &, CallInst *CI, SmallVectorImpl<Value *> &Args) {
736 [[nodiscard]]
bool lowerSampleGrad(Function &
F,
bool HasClamp) {
737 return lowerSampleOp(
738 F, OpCode::SampleGrad, 2, 5,
740 SmallVectorImpl<Value *> &Args) {
745 size_t DDXStart =
Args.size();
746 Args.append(3, UndefF);
747 extractElementsIntoArgs(IRB, Args, DDXStart, DDX, 3);
749 size_t DDYStart =
Args.size();
750 Args.append(3, UndefF);
751 extractElementsIntoArgs(IRB, Args, DDYStart, DDY, 3);
757 [[nodiscard]]
bool lowerRawBufferLoad(Function &
F) {
758 const DataLayout &
DL =
F.getDataLayout();
763 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
768 Type *NewRetTy = OpBuilder.getResRetType(ScalarTy);
771 createTmpHandleCast(CI->
getArgOperand(0), OpBuilder.getHandleType());
774 uint64_t NumElements =
775 DL.getTypeSizeInBits(OldTy) /
DL.getTypeSizeInBits(ScalarTy);
776 Value *
Mask = ConstantInt::get(Int8Ty, ~(~0U << NumElements));
778 ConstantInt::get(
Int32Ty,
DL.getPrefTypeAlign(ScalarTy).value());
785 Expected<CallInst *> OpCall =
786 MMDI.DXILVersion >= VersionTuple(1, 2)
787 ? OpBuilder.tryCreateOp(OpCode::RawBufferLoad,
790 : OpBuilder.tryCreateOp(OpCode::BufferLoad,
791 {Handle, Index0, Index1}, CI->
getName(),
795 if (
Error E = replaceResRetUses(CI, *OpCall,
true))
802 [[nodiscard]]
bool lowerCBufferLoad(Function &
F) {
805 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
810 Type *NewRetTy = OpBuilder.getCBufRetType(ScalarTy);
813 createTmpHandleCast(CI->
getArgOperand(0), OpBuilder.getHandleType());
816 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(
817 OpCode::CBufferLoadLegacy, {Handle,
Index}, CI->
getName(), NewRetTy);
820 if (
Error E = replaceNamedStructUses(CI, *OpCall))
828 [[nodiscard]]
bool lowerUpdateCounter(Function &
F) {
832 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
835 createTmpHandleCast(CI->
getArgOperand(0), OpBuilder.getHandleType());
838 std::array<Value *, 2>
Args{Handle, Op1};
840 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(
852 [[nodiscard]]
bool lowerGetDimensionsX(Function &
F) {
856 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
859 createTmpHandleCast(CI->
getArgOperand(0), OpBuilder.getHandleType());
862 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(
874 [[nodiscard]]
bool lowerGetPointer(Function &
F) {
877 assert(
F.user_empty() &&
"getpointer operations should have been removed");
882 [[nodiscard]]
bool lowerBufferStore(Function &
F,
bool IsRaw) {
883 const DataLayout &
DL =
F.getDataLayout();
888 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
892 createTmpHandleCast(CI->
getArgOperand(0), OpBuilder.getHandleType());
907 uint64_t NumElements =
908 DL.getTypeSizeInBits(DataTy) /
DL.getTypeSizeInBits(ScalarTy);
910 ConstantInt::get(Int8Ty, IsRaw ? ~(~0U << NumElements) : 15U);
915 "Buffer store data must have at most 4 elements",
918 std::array<Value *, 4> DataElements{
nullptr,
nullptr,
nullptr,
nullptr};
919 if (DataTy == ScalarTy)
920 DataElements[0] =
Data;
930 size_t IndexVal = IndexOp->getZExtValue();
931 assert(IndexVal < 4 &&
"Too many elements for buffer store");
932 DataElements[IndexVal] = IEI->getOperand(1);
940 for (
int I = 0,
E = NumElements;
I <
E; ++
I)
941 if (DataElements[
I] ==
nullptr)
948 for (
int I = NumElements,
E = 4;
I <
E; ++
I)
949 if (DataElements[
I] ==
nullptr)
954 Handle, Index0, Index1, DataElements[0],
955 DataElements[1], DataElements[2], DataElements[3],
Mask};
956 if (IsRaw && MMDI.DXILVersion >= VersionTuple(1, 2)) {
957 Op = OpCode::RawBufferStore;
960 ConstantInt::get(
Int32Ty,
DL.getPrefTypeAlign(ScalarTy).value()));
962 Expected<CallInst *> OpCall =
963 OpBuilder.tryCreateOp(
Op, Args, CI->
getName());
970 while (IEI && IEI->use_empty()) {
971 InsertElementInst *Tmp = IEI;
980 [[nodiscard]]
bool lowerCtpopToCountBits(Function &
F) {
984 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
990 Type *FRT =
F.getReturnType();
992 RetTy = VectorType::get(RetTy, VT);
994 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(
995 dxil::OpCode::CountBits, Args, CI->
getName(), RetTy);
1009 CastOp = Instruction::ZExt;
1010 CastOp2 = Instruction::SExt;
1013 "Currently only lowering 16, 32, or 64 bit ctpop to CountBits \
1015 CastOp = Instruction::Trunc;
1016 CastOp2 = Instruction::Trunc;
1021 bool NeedsCast =
false;
1024 if (
I && (
I->getOpcode() == CastOp ||
I->getOpcode() == CastOp2) &&
1025 I->getType() == RetTy) {
1026 I->replaceAllUsesWith(*OpCall);
1027 I->eraseFromParent();
1047 [[nodiscard]]
bool lowerLifetimeIntrinsic(Function &
F) {
1049 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
1053 "Expected operand of lifetime intrinsic to be a pointer");
1055 auto ZeroOrUndef = [&](
Type *Ty) {
1056 return MMDI.ValidatorVersion < VersionTuple(1, 6)
1058 : UndefValue::
get(Ty);
1061 Value *Val =
nullptr;
1063 if (GV->hasInitializer() || GV->isExternallyInitialized())
1065 Val = ZeroOrUndef(GV->getValueType());
1067 Val = ZeroOrUndef(AI->getAllocatedType());
1069 assert(Val &&
"Expected operand of lifetime intrinsic to be a global "
1070 "variable or alloca instruction");
1078 [[nodiscard]]
bool lowerIsFPClass(Function &
F) {
1082 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
1091 switch (TCI->getZExtValue()) {
1092 case FPClassTest::fcInf:
1093 OpCode = dxil::OpCode::IsInf;
1095 case FPClassTest::fcNan:
1096 OpCode = dxil::OpCode::IsNaN;
1098 case FPClassTest::fcNormal:
1099 OpCode = dxil::OpCode::IsNormal;
1101 case FPClassTest::fcFinite:
1102 OpCode = dxil::OpCode::IsFinite;
1105 SmallString<128> Msg =
1106 formatv(
"Unsupported FPClassTest {0} for DXIL Op Lowering",
1107 TCI->getZExtValue());
1111 Expected<CallInst *> OpCall =
1122 bool lowerIntrinsics() {
1123 bool Updated =
false;
1124 bool HasErrors =
false;
1127 if (!
F.isDeclaration())
1133 case Intrinsic::dx_resource_casthandle:
1135 case Intrinsic::dbg_value:
1138 F.eraseFromParent();
1142 F.eraseFromParent();
1144 SmallString<128> Msg =
formatv(
1145 "Unsupported intrinsic {0} for DXIL lowering",
F.getName());
1146 M.getContext().emitError(Msg);
1151#define DXIL_OP_INTRINSIC(OpCode, Intrin, ...) \
1153 HasErrors |= replaceFunctionWithOp( \
1154 F, OpCode, ArrayRef<IntrinArgSelect>{__VA_ARGS__}); \
1156#include "DXILOperation.inc"
1157 case Intrinsic::dx_resource_handlefrombinding:
1158 HasErrors |= lowerHandleFromBinding(
F);
1160 case Intrinsic::dx_resource_getpointer:
1161 HasErrors |= lowerGetPointer(
F);
1163 case Intrinsic::dx_resource_nonuniformindex:
1165 "overloaded llvm.dx.resource.nonuniformindex intrinsics?");
1168 case Intrinsic::dx_resource_load_typedbuffer:
1169 HasErrors |= lowerTypedBufferLoad(
F,
true);
1171 case Intrinsic::dx_resource_load_level:
1172 HasErrors |= lowerTextureLoad(
F);
1174 case Intrinsic::dx_resource_sample:
1175 HasErrors |= lowerSample(
F,
false);
1177 case Intrinsic::dx_resource_sample_clamp:
1178 HasErrors |= lowerSample(
F,
true);
1180 case Intrinsic::dx_resource_samplebias:
1181 HasErrors |= lowerSampleBias(
F,
false);
1183 case Intrinsic::dx_resource_samplebias_clamp:
1184 HasErrors |= lowerSampleBias(
F,
true);
1186 case Intrinsic::dx_resource_samplelevel:
1187 HasErrors |= lowerSampleLevel(
F);
1189 case Intrinsic::dx_resource_samplegrad:
1190 HasErrors |= lowerSampleGrad(
F,
false);
1192 case Intrinsic::dx_resource_samplegrad_clamp:
1193 HasErrors |= lowerSampleGrad(
F,
true);
1195 case Intrinsic::dx_resource_store_typedbuffer:
1196 HasErrors |= lowerBufferStore(
F,
false);
1198 case Intrinsic::dx_resource_load_rawbuffer:
1199 HasErrors |= lowerRawBufferLoad(
F);
1201 case Intrinsic::dx_resource_store_rawbuffer:
1202 HasErrors |= lowerBufferStore(
F,
true);
1204 case Intrinsic::dx_resource_load_cbufferrow_2:
1205 case Intrinsic::dx_resource_load_cbufferrow_4:
1206 case Intrinsic::dx_resource_load_cbufferrow_8:
1207 HasErrors |= lowerCBufferLoad(
F);
1209 case Intrinsic::dx_resource_updatecounter:
1210 HasErrors |= lowerUpdateCounter(
F);
1212 case Intrinsic::dx_resource_getdimensions_x:
1213 HasErrors |= lowerGetDimensionsX(
F);
1215 case Intrinsic::ctpop:
1216 HasErrors |= lowerCtpopToCountBits(
F);
1218 case Intrinsic::lifetime_start:
1219 case Intrinsic::lifetime_end:
1221 F.eraseFromParent();
1223 if (MMDI.DXILVersion < VersionTuple(1, 6))
1224 HasErrors |= lowerLifetimeIntrinsic(
F);
1229 case Intrinsic::is_fpclass:
1230 HasErrors |= lowerIsFPClass(
F);
1235 if (Updated && !HasErrors) {
1236 cleanupHandleCasts();
1237 cleanupNonUniformResourceIndexCalls();
1250 const bool MadeChanges = OpLowerer(M, DRM, DRTM, MMDI).lowerIntrinsics();
1262class DXILOpLoweringLegacy :
public ModulePass {
1264 bool runOnModule(
Module &M)
override {
1266 getAnalysis<DXILResourceWrapperPass>().getResourceMap();
1268 getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
1270 getAnalysis<DXILMetadataAnalysisWrapperPass>().getModuleMetadata();
1272 return OpLowerer(M, DRM, DRTM, MMDI).lowerIntrinsics();
1274 StringRef getPassName()
const override {
return "DXIL Op Lowering"; }
1275 DXILOpLoweringLegacy() : ModulePass(
ID) {}
1278 void getAnalysisUsage(llvm::AnalysisUsage &AU)
const override {
1281 AU.
addRequired<DXILMetadataAnalysisWrapperPass>();
1288char DXILOpLoweringLegacy::ID = 0;
1299 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.
Machine Check Debug Module
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
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.
LLVM_ABI Intrinsic::ID getIntrinsicID() const
Returns the intrinsic ID of the intrinsic called or Intrinsic::not_intrinsic if the called function i...
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)
Type * getFloatTy()
Fetch the type representing a 32-bit floating point value.
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 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 const Function * getFunction() const
Return the function this instruction belongs to.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
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.
LLVMContext & getContext() const
Get the global data context.
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.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
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.
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.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
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.
NodeAddr< DefNode * > Def
NodeAddr< PhiNode * > Phi
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
@ Undef
Value of the register doesn't matter.
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.
FunctionAddr VTableAddr Count
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...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
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.