-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DirectX] Lower @llvm.dx.handle.fromBinding
to DXIL ops
#104251
[DirectX] Lower @llvm.dx.handle.fromBinding
to DXIL ops
#104251
Conversation
Created using spr 1.3.5-bogner [skip ci]
Created using spr 1.3.5-bogner
@llvm/pr-subscribers-llvm-analysis @llvm/pr-subscribers-backend-directx Author: Justin Bogner (bogner) ChangesThe These DXIL ops all need to return the Patch is 21.67 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/104251.diff 8 Files Affected:
diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index 3ba0ae5de61d5..2ed508b28a908 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -23,6 +23,7 @@ class TargetExtType;
namespace dxil {
class ResourceInfo {
+public:
struct ResourceBinding {
uint32_t RecordID;
uint32_t Space;
@@ -89,6 +90,7 @@ class ResourceInfo {
bool operator!=(const FeedbackInfo &RHS) const { return !(*this == RHS); }
};
+private:
// Universal properties.
Value *Symbol;
StringRef Name;
@@ -115,6 +117,10 @@ class ResourceInfo {
MSInfo MultiSample;
+ // We need a default constructor if we want to insert this in a MapVector.
+ ResourceInfo() {}
+ friend class MapVector<CallInst *, ResourceInfo>;
+
public:
ResourceInfo(dxil::ResourceClass RC, dxil::ResourceKind Kind, Value *Symbol,
StringRef Name)
@@ -166,6 +172,8 @@ class ResourceInfo {
MultiSample.Count = Count;
}
+ dxil::ResourceClass getResourceClass() const { return RC; }
+
bool operator==(const ResourceInfo &RHS) const;
static ResourceInfo SRV(Value *Symbol, StringRef Name,
diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index c9102aa3dd972..ca3682fa47767 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -30,6 +30,9 @@ def int_dx_handle_fromBinding
[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i1_ty],
[IntrNoMem]>;
+// Cast between target extension handle types and dxil-style opaque handles
+def int_dx_cast_handle : Intrinsic<[llvm_any_ty], [llvm_any_ty]>;
+
def int_dx_all : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty]>;
def int_dx_any : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty]>;
def int_dx_clamp : DefaultAttrsIntrinsic<[llvm_any_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>;
diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td
index 34c7f84b1ca5b..31fee04d82158 100644
--- a/llvm/lib/Target/DirectX/DXIL.td
+++ b/llvm/lib/Target/DirectX/DXIL.td
@@ -42,6 +42,8 @@ def FloatTy : DXILOpParamType;
def DoubleTy : DXILOpParamType;
def ResRetTy : DXILOpParamType;
def HandleTy : DXILOpParamType;
+def ResBindTy : DXILOpParamType;
+def ResPropsTy : DXILOpParamType;
class DXILOpClass;
@@ -673,6 +675,14 @@ def Dot4 : DXILOp<56, dot4> {
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
}
+def CreateHandle : DXILOp<57, createHandle> {
+ let Doc = "creates the handle to a resource";
+ // ResourceClass, RangeID, Index, NonUniform
+ let arguments = [Int8Ty, Int32Ty, Int32Ty, Int1Ty];
+ let result = HandleTy;
+ let stages = [Stages<DXIL1_0, [all_stages]>];
+}
+
def ThreadId : DXILOp<93, threadId> {
let Doc = "Reads the thread ID";
let LLVMIntrinsic = int_dx_thread_id;
@@ -712,3 +722,17 @@ def FlattenedThreadIdInGroup : DXILOp<96, flattenedThreadIdInGroup> {
let stages = [Stages<DXIL1_0, [compute, mesh, amplification, node]>];
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
}
+
+def AnnotateHandle : DXILOp<217, annotateHandle> {
+ let Doc = "annotate handle with resource properties";
+ let arguments = [HandleTy, ResPropsTy];
+ let result = HandleTy;
+ let stages = [Stages<DXIL1_6, [all_stages]>];
+}
+
+def CreateHandleFromBinding : DXILOp<218, createHandleFromBinding> {
+ let Doc = "create resource handle from binding";
+ let arguments = [ResBindTy, Int32Ty, Int1Ty];
+ let result = HandleTy;
+ let stages = [Stages<DXIL1_6, [all_stages]>];
+}
diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
index 7d2b40cc515cc..692af1b359ced 100644
--- a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
@@ -208,6 +208,23 @@ static StructType *getHandleType(LLVMContext &Ctx) {
Ctx);
}
+static StructType *getResBindType(LLVMContext &Context) {
+ if (auto *ST = StructType::getTypeByName(Context, "dx.types.ResBind"))
+ return ST;
+ Type *Int32Ty = Type::getInt32Ty(Context);
+ Type *Int8Ty = Type::getInt8Ty(Context);
+ return StructType::create({Int32Ty, Int32Ty, Int32Ty, Int8Ty},
+ "dx.types.ResBind");
+}
+
+static StructType *getResPropsType(LLVMContext &Context) {
+ if (auto *ST =
+ StructType::getTypeByName(Context, "dx.types.ResourceProperties"))
+ return ST;
+ Type *Int32Ty = Type::getInt32Ty(Context);
+ return StructType::create({Int32Ty, Int32Ty}, "dx.types.ResourceProperties");
+}
+
static Type *getTypeFromOpParamType(OpParamType Kind, LLVMContext &Ctx,
Type *OverloadTy) {
switch (Kind) {
@@ -235,6 +252,10 @@ static Type *getTypeFromOpParamType(OpParamType Kind, LLVMContext &Ctx,
return getResRetType(OverloadTy, Ctx);
case OpParamType::HandleTy:
return getHandleType(Ctx);
+ case OpParamType::ResBindTy:
+ return getResBindType(Ctx);
+ case OpParamType::ResPropsTy:
+ return getResPropsType(Ctx);
}
llvm_unreachable("Invalid parameter kind");
return nullptr;
@@ -430,6 +451,29 @@ CallInst *DXILOpBuilder::createOp(dxil::OpCode OpCode, ArrayRef<Value *> Args,
return *Result;
}
+StructType *DXILOpBuilder::getHandleType() {
+ return ::getHandleType(IRB.getContext());
+}
+
+Constant *DXILOpBuilder::getResBind(uint32_t LowerBound, uint32_t UpperBound,
+ uint32_t SpaceID, dxil::ResourceClass RC) {
+ Type *Int32Ty = IRB.getInt32Ty();
+ Type *Int8Ty = IRB.getInt8Ty();
+ return ConstantStruct::get(
+ getResBindType(IRB.getContext()),
+ {ConstantInt::get(Int32Ty, LowerBound),
+ ConstantInt::get(Int32Ty, UpperBound),
+ ConstantInt::get(Int32Ty, SpaceID),
+ ConstantInt::get(Int8Ty, llvm::to_underlying(RC))});
+}
+
+Constant *DXILOpBuilder::getResProps(uint32_t Word0, uint32_t Word1) {
+ Type *Int32Ty = IRB.getInt32Ty();
+ return ConstantStruct::get(
+ getResPropsType(IRB.getContext()),
+ {ConstantInt::get(Int32Ty, Word0), ConstantInt::get(Int32Ty, Word1)});
+}
+
const char *DXILOpBuilder::getOpCodeName(dxil::OpCode DXILOp) {
return ::getOpCodeName(DXILOp);
}
diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.h b/llvm/lib/Target/DirectX/DXILOpBuilder.h
index 483d5ddc8b619..4a55a8ac9eadb 100644
--- a/llvm/lib/Target/DirectX/DXILOpBuilder.h
+++ b/llvm/lib/Target/DirectX/DXILOpBuilder.h
@@ -15,6 +15,7 @@
#include "DXILConstants.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/IRBuilder.h"
+#include "llvm/Support/DXILABI.h"
#include "llvm/Support/Error.h"
#include "llvm/TargetParser/Triple.h"
@@ -22,6 +23,7 @@ namespace llvm {
class Module;
class IRBuilderBase;
class CallInst;
+class Constant;
class Value;
class Type;
class FunctionType;
@@ -44,6 +46,15 @@ class DXILOpBuilder {
Expected<CallInst *> tryCreateOp(dxil::OpCode Op, ArrayRef<Value *> Args,
Type *RetTy = nullptr);
+ /// Get the `%dx.types.Handle` type.
+ StructType *getHandleType();
+
+ /// Get a constant `%dx.types.ResBind` value.
+ Constant *getResBind(uint32_t LowerBound, uint32_t UpperBound,
+ uint32_t SpaceID, dxil::ResourceClass RC);
+ /// Get a constant `%dx.types.ResourceProperties` value.
+ Constant *getResProps(uint32_t Word0, uint32_t Word1);
+
/// Return the name of the given opcode.
static const char *getOpCodeName(dxil::OpCode DXILOp);
diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
index fb708a61dd318..ab18c57efa307 100644
--- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
@@ -12,6 +12,7 @@
#include "DXILOpBuilder.h"
#include "DirectX.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/Analysis/DXILResource.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/IRBuilder.h"
@@ -20,6 +21,7 @@
#include "llvm/IR/IntrinsicsDirectX.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
+#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/ErrorHandling.h"
@@ -74,9 +76,11 @@ namespace {
class OpLowerer {
Module &M;
DXILOpBuilder OpBuilder;
+ DXILResourceMap &DRM;
+ SmallVector<CallInst *> CleanupCasts;
public:
- OpLowerer(Module &M) : M(M), OpBuilder(M) {}
+ OpLowerer(Module &M, DXILResourceMap &DRM) : M(M), OpBuilder(M), DRM(DRM) {}
void replaceFunction(Function &F,
llvm::function_ref<Error(CallInst *CI)> ReplaceCall) {
@@ -119,6 +123,119 @@ class OpLowerer {
});
}
+ Value *createTmpHandleCast(Value *V, Type *Ty) {
+ Function *CastFn = Intrinsic::getDeclaration(&M, Intrinsic::dx_cast_handle,
+ {Ty, V->getType()});
+ CallInst *Cast = OpBuilder.getIRB().CreateCall(CastFn, {V});
+ CleanupCasts.push_back(Cast);
+ return Cast;
+ }
+
+ void cleanupHandleCasts() {
+ SmallVector<CallInst *> ToRemove;
+ SmallVector<Function *> CastFns;
+
+ for (CallInst *Cast : CleanupCasts) {
+ CastFns.push_back(Cast->getCalledFunction());
+ // All of the ops should be using `dx.types.Handle` at this point, so if
+ // we're not producing that we should be part of a pair. Track this so we
+ // can remove it at the end.
+ if (Cast->getType() != OpBuilder.getHandleType()) {
+ ToRemove.push_back(Cast);
+ continue;
+ }
+ // Otherwise, we're the second handle in a pair. Forward the arguments and
+ // remove the (second) cast.
+ CallInst *Def = cast<CallInst>(Cast->getOperand(0));
+ assert(Def->getIntrinsicID() == Intrinsic::dx_cast_handle &&
+ "Unbalanced pair of temporary handle casts");
+ Cast->replaceAllUsesWith(Def->getOperand(0));
+ Cast->eraseFromParent();
+ }
+ for (CallInst *Cast : ToRemove) {
+ assert(Cast->user_empty() && "Temporary handle cast still has users");
+ Cast->eraseFromParent();
+ }
+ llvm::sort(CastFns);
+ CastFns.erase(llvm::unique(CastFns), CastFns.end());
+ for (Function *F : CastFns)
+ F->eraseFromParent();
+
+ CleanupCasts.clear();
+ }
+
+ void lowerToCreateHandle(Function &F) {
+ IRBuilder<> &IRB = OpBuilder.getIRB();
+ Type *Int8Ty = IRB.getInt8Ty();
+ Type *Int32Ty = IRB.getInt32Ty();
+
+ replaceFunction(F, [&](CallInst *CI) -> Error {
+ IRB.SetInsertPoint(CI);
+
+ dxil::ResourceInfo &RI = DRM[CI];
+ dxil::ResourceInfo::ResourceBinding Binding = RI.getBinding();
+
+ std::array<Value *, 4> Args{
+ ConstantInt::get(Int8Ty, llvm::to_underlying(RI.getResourceClass())),
+ ConstantInt::get(Int32Ty, Binding.RecordID), CI->getArgOperand(3),
+ CI->getArgOperand(4)};
+ Expected<CallInst *> OpCall =
+ OpBuilder.tryCreateOp(OpCode::CreateHandle, Args);
+ if (Error E = OpCall.takeError())
+ return E;
+
+ Value *Cast = createTmpHandleCast(*OpCall, CI->getType());
+
+ CI->replaceAllUsesWith(Cast);
+ CI->eraseFromParent();
+ return Error::success();
+ });
+ }
+
+ void lowerToBindAndAnnotateHandle(Function &F) {
+ IRBuilder<> &IRB = OpBuilder.getIRB();
+
+ replaceFunction(F, [&](CallInst *CI) -> Error {
+ IRB.SetInsertPoint(CI);
+
+ dxil::ResourceInfo &RI = DRM[CI];
+ dxil::ResourceInfo::ResourceBinding Binding = RI.getBinding();
+ std::pair<uint32_t, uint32_t> Props = RI.getAnnotateProps();
+
+ Constant *ResBind = OpBuilder.getResBind(
+ Binding.LowerBound, Binding.LowerBound + Binding.Size - 1,
+ Binding.Space, RI.getResourceClass());
+ std::array<Value *, 3> BindArgs{ResBind, CI->getArgOperand(3),
+ CI->getArgOperand(4)};
+ Expected<CallInst *> OpBind =
+ OpBuilder.tryCreateOp(OpCode::CreateHandleFromBinding, BindArgs);
+ if (Error E = OpBind.takeError())
+ return E;
+
+ std::array<Value *, 2> AnnotateArgs{
+ *OpBind, OpBuilder.getResProps(Props.first, Props.second)};
+ Expected<CallInst *> OpAnnotate =
+ OpBuilder.tryCreateOp(OpCode::AnnotateHandle, AnnotateArgs);
+ if (Error E = OpAnnotate.takeError())
+ return E;
+
+ Value *Cast = createTmpHandleCast(*OpAnnotate, CI->getType());
+
+ CI->replaceAllUsesWith(Cast);
+ CI->eraseFromParent();
+
+ return Error::success();
+ });
+ }
+
+ void lowerHandleFromBinding(Function &F) {
+ Triple TT(Triple(M.getTargetTriple()));
+ if (TT.getDXILVersion() < VersionTuple(1, 6))
+ lowerToCreateHandle(F);
+ else
+ lowerToBindAndAnnotateHandle(F);
+ }
+
bool lowerIntrinsics() {
bool Updated = false;
@@ -134,33 +251,47 @@ class OpLowerer {
replaceFunctionWithOp(F, OpCode); \
break;
#include "DXILOperation.inc"
+ case Intrinsic::dx_handle_fromBinding:
+ lowerHandleFromBinding(F);
}
Updated = true;
}
+ if (Updated)
+ cleanupHandleCasts();
+
return Updated;
}
};
} // namespace
-PreservedAnalyses DXILOpLowering::run(Module &M, ModuleAnalysisManager &) {
- if (OpLowerer(M).lowerIntrinsics())
- return PreservedAnalyses::none();
- return PreservedAnalyses::all();
+PreservedAnalyses DXILOpLowering::run(Module &M, ModuleAnalysisManager &MAM) {
+ DXILResourceMap &DRM = MAM.getResult<DXILResourceAnalysis>(M);
+
+ bool MadeChanges = OpLowerer(M, DRM).lowerIntrinsics();
+ if (!MadeChanges)
+ return PreservedAnalyses::all();
+ PreservedAnalyses PA;
+ PA.preserve<DXILResourceAnalysis>();
+ return PA;
}
namespace {
class DXILOpLoweringLegacy : public ModulePass {
public:
bool runOnModule(Module &M) override {
- return OpLowerer(M).lowerIntrinsics();
+ DXILResourceMap &DRM =
+ getAnalysis<DXILResourceWrapperPass>().getResourceMap();
+
+ return OpLowerer(M, DRM).lowerIntrinsics();
}
StringRef getPassName() const override { return "DXIL Op Lowering"; }
DXILOpLoweringLegacy() : ModulePass(ID) {}
static char ID; // Pass identification.
void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
- // Specify the passes that your pass depends on
AU.addRequired<DXILIntrinsicExpansionLegacy>();
+ AU.addRequired<DXILResourceWrapperPass>();
+ AU.addPreserved<DXILResourceWrapperPass>();
}
};
char DXILOpLoweringLegacy::ID = 0;
@@ -168,6 +299,7 @@ char DXILOpLoweringLegacy::ID = 0;
INITIALIZE_PASS_BEGIN(DXILOpLoweringLegacy, DEBUG_TYPE, "DXIL Op Lowering",
false, false)
+INITIALIZE_PASS_DEPENDENCY(DXILResourceWrapperPass)
INITIALIZE_PASS_END(DXILOpLoweringLegacy, DEBUG_TYPE, "DXIL Op Lowering", false,
false)
diff --git a/llvm/test/CodeGen/DirectX/CreateHandle.ll b/llvm/test/CodeGen/DirectX/CreateHandle.ll
new file mode 100644
index 0000000000000..ca4def78e73de
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/CreateHandle.ll
@@ -0,0 +1,59 @@
+; RUN: opt -S -dxil-op-lower %s | FileCheck %s
+
+target triple = "dxil-pc-shadermodel6.0-compute"
+
+define void @test_buffers() {
+ ; RWBuffer<float4> Buf : register(u5, space3)
+ %typed0 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
+ @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f32_1_0_0(
+ i32 3, i32 5, i32 1, i32 4, i1 false)
+ ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 4, i1 false)
+ ; CHECK-NOT: @llvm.dx.cast.handle
+
+ ; RWBuffer<int> Buf : register(u7, space2)
+ %typed1 = call target("dx.TypedBuffer", i32, 1, 0, 1)
+ @llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_1_0_1t(
+ i32 2, i32 7, i32 1, i32 6, i1 false)
+ ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 1, i32 6, i1 false)
+
+ ; Buffer<uint4> Buf[24] : register(t3, space5)
+ %typed2 = call target("dx.TypedBuffer", <4 x i32>, 0, 0, 0)
+ @llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_0_0_0t(
+ i32 2, i32 7, i32 24, i32 8, i1 false)
+ ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 8, i1 false)
+
+ ; struct S { float4 a; uint4 b; };
+ ; StructuredBuffer<S> Buf : register(t2, space4)
+ %struct0 = call target("dx.RawBuffer", {<4 x float>, <4 x i32>}, 0, 0)
+ @llvm.dx.handle.fromBinding.tdx.RawBuffer_sl_v4f32v4i32s_0_0t(
+ i32 4, i32 2, i32 1, i32 10, i1 true)
+ ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 1, i32 10, i1 true)
+
+ ; ByteAddressBuffer Buf : register(t8, space1)
+ %byteaddr0 = call target("dx.RawBuffer", i8, 0, 0)
+ @llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_0_0t(
+ i32 1, i32 8, i32 1, i32 12, i1 false)
+ ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 2, i32 12, i1 false)
+
+ ret void
+}
+
+; Note: We need declarations for each handle.fromBinding in the same order as
+; they appear in source to force a deterministic ordering of record IDs.
+declare target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
+ @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f32_1_0_0t(
+ i32, i32, i32, i32, i1) #0
+declare target("dx.TypedBuffer", i32, 1, 0, 1)
+ @llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_1_0_1t(
+ i32, i32, i32, i32, i1) #0
+declare target("dx.TypedBuffer", <4 x i32>, 0, 0, 0)
+ @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4i32_0_0_0t(
+ i32, i32, i32, i32, i1) #0
+declare target("dx.RawBuffer", { <4 x float>, <4 x i32> }, 0, 0)
+ @llvm.dx.handle.fromBinding.tdx.RawBuffer_sl_v4f32v4i32s_0_0t(
+ i32, i32, i32, i32, i1) #0
+declare target("dx.RawBuffer", i8, 0, 0)
+ @llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_0_0t(
+ i32, i32, i32, i32, i1) #0
+
+attributes #0 = { nocallback nofree nosync nounwind willreturn memory(none) }
diff --git a/llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll b/llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll
new file mode 100644
index 0000000000000..9b6688cb11d54
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll
@@ -0,0 +1,63 @@
+; RUN: opt -S -dxil-op-lower %s | FileCheck %s
+
+target triple = "dxil-pc-shadermodel6.6-compute"
+
+define void @test_bindings() {
+ ; RWBuffer<float4> Buf : register(u5, space3)
+ %typed0 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
+ @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f32_1_0_0(
+ i32 3, i32 5, i32 1, i32 4, i1 false)
+ ; CHECK: [[BUF0:%[0-9]*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 218, %dx.types.ResBind { i32 5, i32 5, i32 3, i8 1 }, i32 4, i1 false)
+ ; CHECK: call %dx.types.Handle @dx.op.annotateHandle(i32 217, %dx.types.Handle [[BUF0]], %dx.types.ResourceProperties { i32 4106, i32 1033 })
+
+ ; RWBuffer<int> Buf : register(u7, space2)
+ %typed1 = call target("dx.TypedBuffer", i32, 1, 0, 1)
+ @llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_1_0_0t(
+ i32 2, i32 7, i32 1, i32 6, i1 false)
+ ; CHECK: [[BUF1:%[0-9]*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 218, %dx.types.ResBind { i32 7, i32 7, i32 2, i8 1 }, i32 6, i1 false)
+ ; CHECK: call %dx.types.Handle @dx.op.annotateHandle(i32 217, %dx.types.Handle [[BUF1]], %dx.types.ResourceProperties { i32 4106, i32 260 })
+
+ ; Buffer<uint4> Buf[24] : register(t3, space5)
+ %typed2 = call target("dx.TypedBuffer", <4 x i32>, 0, 0, 0)
+ @llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_0_0_0t(
+ i32 2, i32 7, i32 24, i32 8, i1 false)
+ ; CHECK: [[BUF2:%[0-9]*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 218, %dx.types.ResBind { i32 7, i32 30, i32 2, i8 0 }, i32 8, i1 false)
+ ; CHECK: call %dx.types.Handle @dx.op.annotateHandle(i32 217, %dx.types.Handle [[BUF2]], %dx.types.ResourceProperties { i32 10, i32 1029 })
+
+ ; struct S { float4 a; uint4 b; };
+ ; StructuredBuffer<S> Buf : register(t2, space4)
+ %struct0 = call target("dx.RawBuffer", {<4 x float>, <4 x i32>}, 0, 0)
+ @llvm.dx.handle.fromBinding.tdx.RawBuffer_sl_v4f32v4i32s_0_0t(
+ i32 4, i32 2, i32 1, i32 10, i1 true)
+ ; CHECK: [[BUF3:%[0-9]*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 218, %dx.types.ResBind { i32 2, i32 2, i32 4, i8 0 }, i32 10, i1 tr...
[truncated]
|
The `@llvm.dx.handle.fromBinding` intrinsic is lowered either to the `CreateHandle` op or a pair of `CreateHandleFromBinding` and `AnnotateHandle` ops, depending on the DXIL version. Regardless of the DXIL version we need to emit metadata about the binding, but that's left to a separate change. These DXIL ops all need to return the `%dx.types.Handle` type, but the llvm intrinsic returns a target extension type. To facilitate changing the type of the operation and all of its users, we introduce `%llvm.dx.cast.handle`, which can cast between the two handle representations. Pull Request: llvm#104251
Created using spr 1.3.5-bogner [skip ci]
Created using spr 1.3.5-bogner
Created using spr 1.3.5-bogner [skip ci]
Created using spr 1.3.5-bogner
Created using spr 1.3.5-bogner [skip ci]
Created using spr 1.3.5-bogner
Created using spr 1.3.5-bogner [skip ci]
Created using spr 1.3.5-bogner
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Created using spr 1.3.5-bogner [skip ci]
Created using spr 1.3.5-bogner
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, LGTM!
Created using spr 1.3.5-bogner
The `@llvm.dx.handle.fromBinding` intrinsic is lowered either to the `CreateHandle` op or a pair of `CreateHandleFromBinding` and `AnnotateHandle` ops, depending on the DXIL version. Regardless of the DXIL version we need to emit metadata about the binding, but that's left to a separate change. These DXIL ops all need to return the `%dx.types.Handle` type, but the llvm intrinsic returns a target extension type. To facilitate changing the type of the operation and all of its users, we introduce `%llvm.dx.cast.handle`, which can cast between the two handle representations. Pull Request: #104251
The `@llvm.dx.handle.fromBinding` intrinsic is lowered either to the `CreateHandle` op or a pair of `CreateHandleFromBinding` and `AnnotateHandle` ops, depending on the DXIL version. Regardless of the DXIL version we need to emit metadata about the binding, but that's left to a separate change. These DXIL ops all need to return the `%dx.types.Handle` type, but the llvm intrinsic returns a target extension type. To facilitate changing the type of the operation and all of its users, we introduce `%llvm.dx.cast.handle`, which can cast between the two handle representations. Pull Request: llvm#104251
The
@llvm.dx.handle.fromBinding
intrinsic is lowered either to theCreateHandle
op or a pair ofCreateHandleFromBinding
andAnnotateHandle
ops, depending on the DXIL version. Regardless of the DXIL version we need to
emit metadata about the binding, but that's left to a separate change.
These DXIL ops all need to return the
%dx.types.Handle
type, but the llvmintrinsic returns a target extension type. To facilitate changing the type of
the operation and all of its users, we introduce
%llvm.dx.cast.handle
, whichcan cast between the two handle representations.