[llvm] Re-Apply "[DXIL][Analysis] Implement enough of DXILResourceAnalysis for buffers" (PR #104517)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 15 15:47:56 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-directx
Author: Justin Bogner (bogner)
<details>
<summary>Changes</summary>
Some build configs allow `llvm_unreachable` in a constexpr context, but not all, so these functions that map a fully covered enum to a string can't be constexpr.
This reverts commit fcc318ff7960d7de8cbac56eb4f32b44b5261677, reapplying 28d577ecefa1557f5dea5566bf33b885c563d14b.
Original message follows:
This implements the DXILResourceAnalysis pass for `dx.TypedBuffer` and `dx.RawBuffer` types. This should be sufficient to lower `dx.handle.fromBinding` for this set of types, but it leaves a number of TODOs around for other resource types.
This also includes a straightforward `print` method in `ResourceInfo` to make the analysis testable. This is deliberately different than the printer in `lib/Target/DirectX/DXILResource.cpp`, which attempts to print bindings in a format compatible with the comments `dxc` prints. We will eventually want to make that functionality driven by this analysis pass, but it isn't sufficient for testing so we need both.
---
Patch is 20.96 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/104517.diff
4 Files Affected:
- (modified) llvm/include/llvm/Analysis/DXILResource.h (+8-5)
- (modified) llvm/include/llvm/IR/IntrinsicsDirectX.td (+10)
- (modified) llvm/lib/Analysis/DXILResource.cpp (+377-3)
- (added) llvm/test/Analysis/DXILResource/buffer-frombinding.ll (+126)
``````````diff
diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index 7db088df260f3..3ba0ae5de61d5 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -18,19 +18,20 @@
namespace llvm {
class CallInst;
class MDTuple;
+class TargetExtType;
namespace dxil {
class ResourceInfo {
struct ResourceBinding {
- uint32_t UniqueID;
+ uint32_t RecordID;
uint32_t Space;
uint32_t LowerBound;
uint32_t Size;
bool operator==(const ResourceBinding &RHS) const {
- return std::tie(UniqueID, Space, LowerBound, Size) ==
- std::tie(RHS.UniqueID, RHS.Space, RHS.LowerBound, RHS.Size);
+ return std::tie(RecordID, Space, LowerBound, Size) ==
+ std::tie(RHS.RecordID, RHS.Space, RHS.LowerBound, RHS.Size);
}
bool operator!=(const ResourceBinding &RHS) const {
return !(*this == RHS);
@@ -128,9 +129,9 @@ class ResourceInfo {
bool isFeedback() const;
bool isMultiSample() const;
- void bind(uint32_t UniqueID, uint32_t Space, uint32_t LowerBound,
+ void bind(uint32_t RecordID, uint32_t Space, uint32_t LowerBound,
uint32_t Size) {
- Binding.UniqueID = UniqueID;
+ Binding.RecordID = RecordID;
Binding.Space = Space;
Binding.LowerBound = LowerBound;
Binding.Size = Size;
@@ -215,6 +216,8 @@ class ResourceInfo {
ResourceBinding getBinding() const { return Binding; }
std::pair<uint32_t, uint32_t> getAnnotateProps() const;
+
+ void print(raw_ostream &OS) const;
};
} // namespace dxil
diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index 904801e6e9e95..c9102aa3dd972 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -20,6 +20,16 @@ def int_dx_flattened_thread_id_in_group : Intrinsic<[llvm_i32_ty], [], [IntrNoMe
def int_dx_create_handle : ClangBuiltin<"__builtin_hlsl_create_handle">,
Intrinsic<[ llvm_ptr_ty ], [llvm_i8_ty], [IntrWillReturn]>;
+// Create resource handle given binding information. Returns a `target("dx.")`
+// type appropriate for the kind of resource given a register space ID, lower
+// bound and range size of the binding, as well as an index and an indicator
+// whether that index may be non-uniform.
+def int_dx_handle_fromBinding
+ : DefaultAttrsIntrinsic<
+ [llvm_any_ty],
+ [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i1_ty],
+ [IntrNoMem]>;
+
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/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index 9941a55d46d64..1b5b051c9db29 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -8,9 +8,14 @@
#include "llvm/Analysis/DXILResource.h"
#include "llvm/ADT/APInt.h"
+#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicsDirectX.h"
#include "llvm/IR/Metadata.h"
+#include "llvm/IR/Module.h"
#include "llvm/InitializePasses.h"
#define DEBUG_TYPE "dxil-resource"
@@ -18,6 +23,131 @@
using namespace llvm;
using namespace dxil;
+static StringRef getResourceClassName(ResourceClass RC) {
+ switch (RC) {
+ case ResourceClass::SRV:
+ return "SRV";
+ case ResourceClass::UAV:
+ return "UAV";
+ case ResourceClass::CBuffer:
+ return "CBuffer";
+ case ResourceClass::Sampler:
+ return "Sampler";
+ }
+ llvm_unreachable("Unhandled ResourceClass");
+}
+
+static StringRef getResourceKindName(ResourceKind RK) {
+ switch (RK) {
+ case ResourceKind::Texture1D:
+ return "Texture1D";
+ case ResourceKind::Texture2D:
+ return "Texture2D";
+ case ResourceKind::Texture2DMS:
+ return "Texture2DMS";
+ case ResourceKind::Texture3D:
+ return "Texture3D";
+ case ResourceKind::TextureCube:
+ return "TextureCube";
+ case ResourceKind::Texture1DArray:
+ return "Texture1DArray";
+ case ResourceKind::Texture2DArray:
+ return "Texture2DArray";
+ case ResourceKind::Texture2DMSArray:
+ return "Texture2DMSArray";
+ case ResourceKind::TextureCubeArray:
+ return "TextureCubeArray";
+ case ResourceKind::TypedBuffer:
+ return "TypedBuffer";
+ case ResourceKind::RawBuffer:
+ return "RawBuffer";
+ case ResourceKind::StructuredBuffer:
+ return "StructuredBuffer";
+ case ResourceKind::CBuffer:
+ return "CBuffer";
+ case ResourceKind::Sampler:
+ return "Sampler";
+ case ResourceKind::TBuffer:
+ return "TBuffer";
+ case ResourceKind::RTAccelerationStructure:
+ return "RTAccelerationStructure";
+ case ResourceKind::FeedbackTexture2D:
+ return "FeedbackTexture2D";
+ case ResourceKind::FeedbackTexture2DArray:
+ return "FeedbackTexture2DArray";
+ case ResourceKind::NumEntries:
+ case ResourceKind::Invalid:
+ return "<invalid>";
+ }
+ llvm_unreachable("Unhandled ResourceKind");
+}
+
+static StringRef getElementTypeName(ElementType ET) {
+ switch (ET) {
+ case ElementType::I1:
+ return "i1";
+ case ElementType::I16:
+ return "i16";
+ case ElementType::U16:
+ return "u16";
+ case ElementType::I32:
+ return "i32";
+ case ElementType::U32:
+ return "u32";
+ case ElementType::I64:
+ return "i64";
+ case ElementType::U64:
+ return "u64";
+ case ElementType::F16:
+ return "f16";
+ case ElementType::F32:
+ return "f32";
+ case ElementType::F64:
+ return "f64";
+ case ElementType::SNormF16:
+ return "snorm_f16";
+ case ElementType::UNormF16:
+ return "unorm_f16";
+ case ElementType::SNormF32:
+ return "snorm_f32";
+ case ElementType::UNormF32:
+ return "unorm_f32";
+ case ElementType::SNormF64:
+ return "snorm_f64";
+ case ElementType::UNormF64:
+ return "unorm_f64";
+ case ElementType::PackedS8x32:
+ return "p32i8";
+ case ElementType::PackedU8x32:
+ return "p32u8";
+ case ElementType::Invalid:
+ return "<invalid>";
+ }
+ llvm_unreachable("Unhandled ElementType");
+}
+
+static StringRef getSamplerTypeName(SamplerType ST) {
+ switch (ST) {
+ case SamplerType::Default:
+ return "Default";
+ case SamplerType::Comparison:
+ return "Comparison";
+ case SamplerType::Mono:
+ return "Mono";
+ }
+ llvm_unreachable("Unhandled SamplerType");
+}
+
+static StringRef getSamplerFeedbackTypeName(SamplerFeedbackType SFT) {
+ switch (SFT) {
+ case SamplerFeedbackType::MinMip:
+ return "MinMip";
+ case SamplerFeedbackType::MipRegionUsed:
+ return "MipRegionUsed";
+ }
+ llvm_unreachable("Unhandled SamplerFeedbackType");
+}
+
bool ResourceInfo::isUAV() const { return RC == ResourceClass::UAV; }
bool ResourceInfo::isCBuffer() const { return RC == ResourceClass::CBuffer; }
@@ -240,7 +370,7 @@ MDTuple *ResourceInfo::getAsMetadata(LLVMContext &Ctx) const {
Constant::getIntegerValue(I1Ty, APInt(1, V)));
};
- MDVals.push_back(getIntMD(Binding.UniqueID));
+ MDVals.push_back(getIntMD(Binding.RecordID));
MDVals.push_back(ValueAsMetadata::get(Symbol));
MDVals.push_back(MDString::get(Ctx, Name));
MDVals.push_back(getIntMD(Binding.Space));
@@ -330,6 +460,248 @@ std::pair<uint32_t, uint32_t> ResourceInfo::getAnnotateProps() const {
return {Word0, Word1};
}
+void ResourceInfo::print(raw_ostream &OS) const {
+ OS << " Symbol: ";
+ Symbol->printAsOperand(OS);
+ OS << "\n";
+
+ OS << " Name: \"" << Name << "\"\n"
+ << " Binding:\n"
+ << " Record ID: " << Binding.RecordID << "\n"
+ << " Space: " << Binding.Space << "\n"
+ << " Lower Bound: " << Binding.LowerBound << "\n"
+ << " Size: " << Binding.Size << "\n"
+ << " Class: " << getResourceClassName(RC) << "\n"
+ << " Kind: " << getResourceKindName(Kind) << "\n";
+
+ if (isCBuffer()) {
+ OS << " CBuffer size: " << CBufferSize << "\n";
+ } else if (isSampler()) {
+ OS << " Sampler Type: " << getSamplerTypeName(SamplerTy) << "\n";
+ } else {
+ if (isUAV()) {
+ OS << " Globally Coherent: " << UAVFlags.GloballyCoherent << "\n"
+ << " HasCounter: " << UAVFlags.HasCounter << "\n"
+ << " IsROV: " << UAVFlags.IsROV << "\n";
+ }
+ if (isMultiSample())
+ OS << " Sample Count: " << MultiSample.Count << "\n";
+
+ if (isStruct()) {
+ OS << " Buffer Stride: " << Struct.Stride << "\n";
+ OS << " Alignment: " << Struct.AlignLog2 << "\n";
+ } else if (isTyped()) {
+ OS << " Element Type: " << getElementTypeName(Typed.ElementTy) << "\n"
+ << " Element Count: " << Typed.ElementCount << "\n";
+ } else if (isFeedback())
+ OS << " Feedback Type: " << getSamplerFeedbackTypeName(Feedback.Type)
+ << "\n";
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// ResourceMapper
+
+static dxil::ElementType toDXILElementType(Type *Ty, bool IsSigned) {
+ // TODO: Handle unorm, snorm, and packed.
+ Ty = Ty->getScalarType();
+
+ if (Ty->isIntegerTy()) {
+ switch (Ty->getIntegerBitWidth()) {
+ case 16:
+ return IsSigned ? ElementType::I16 : ElementType::U16;
+ case 32:
+ return IsSigned ? ElementType::I32 : ElementType::U32;
+ case 64:
+ return IsSigned ? ElementType::I64 : ElementType::U64;
+ case 1:
+ default:
+ return ElementType::Invalid;
+ }
+ } else if (Ty->isFloatTy()) {
+ return ElementType::F32;
+ } else if (Ty->isDoubleTy()) {
+ return ElementType::F64;
+ } else if (Ty->isHalfTy()) {
+ return ElementType::F16;
+ }
+
+ return ElementType::Invalid;
+}
+
+namespace {
+
+class ResourceMapper {
+ Module &M;
+ LLVMContext &Context;
+ DXILResourceMap &Resources;
+
+ // In DXC, Record ID is unique per resource type. Match that.
+ uint32_t NextUAV = 0;
+ uint32_t NextSRV = 0;
+ uint32_t NextCBuf = 0;
+ uint32_t NextSmp = 0;
+
+public:
+ ResourceMapper(Module &M,
+ MapVector<CallInst *, dxil::ResourceInfo> &Resources)
+ : M(M), Context(M.getContext()), Resources(Resources) {}
+
+ void diagnoseHandle(CallInst *CI, const Twine &Msg,
+ DiagnosticSeverity Severity = DS_Error) {
+ std::string S;
+ raw_string_ostream SS(S);
+ CI->printAsOperand(SS);
+ DiagnosticInfoUnsupported Diag(*CI->getFunction(), Msg + ": " + SS.str(),
+ CI->getDebugLoc(), Severity);
+ Context.diagnose(Diag);
+ }
+
+ ResourceInfo *mapBufferType(CallInst *CI, TargetExtType *HandleTy,
+ bool IsTyped) {
+ if (HandleTy->getNumTypeParameters() != 1 ||
+ HandleTy->getNumIntParameters() != (IsTyped ? 3 : 2)) {
+ diagnoseHandle(CI, Twine("Invalid buffer target type"));
+ return nullptr;
+ }
+
+ Type *ElTy = HandleTy->getTypeParameter(0);
+ unsigned IsWriteable = HandleTy->getIntParameter(0);
+ unsigned IsROV = HandleTy->getIntParameter(1);
+ bool IsSigned = IsTyped && HandleTy->getIntParameter(2);
+
+ ResourceClass RC = IsWriteable ? ResourceClass::UAV : ResourceClass::SRV;
+ ResourceKind Kind;
+ if (IsTyped)
+ Kind = ResourceKind::TypedBuffer;
+ else if (ElTy->isIntegerTy(8))
+ Kind = ResourceKind::RawBuffer;
+ else
+ Kind = ResourceKind::StructuredBuffer;
+
+ // TODO: We need to lower to a typed pointer, can we smuggle the type
+ // through?
+ Value *Symbol = UndefValue::get(PointerType::getUnqual(Context));
+ // TODO: We don't actually keep track of the name right now...
+ StringRef Name = "";
+
+ auto [It, Success] = Resources.try_emplace(CI, RC, Kind, Symbol, Name);
+ assert(Success && "Mapping the same CallInst again?");
+ (void)Success;
+ // We grab a pointer into the map's storage, which isn't generally safe.
+ // Since we're just using this to fill in the info the map won't mutate and
+ // the pointer stays valid for as long as we need it to.
+ ResourceInfo *RI = &(It->second);
+
+ if (RI->isUAV())
+ // TODO: We need analysis for GloballyCoherent and HasCounter
+ RI->setUAV(false, false, IsROV);
+
+ if (RI->isTyped()) {
+ dxil::ElementType ET = toDXILElementType(ElTy, IsSigned);
+ uint32_t Count = 1;
+ if (auto *VTy = dyn_cast<FixedVectorType>(ElTy))
+ Count = VTy->getNumElements();
+ RI->setTyped(ET, Count);
+ } else if (RI->isStruct()) {
+ const DataLayout &DL = M.getDataLayout();
+
+ // This mimics what DXC does. Notably, we only ever set the alignment if
+ // the type is actually a struct type.
+ uint32_t Stride = DL.getTypeAllocSize(ElTy);
+ MaybeAlign Alignment;
+ if (auto *STy = dyn_cast<StructType>(ElTy))
+ Alignment = DL.getStructLayout(STy)->getAlignment();
+ RI->setStruct(Stride, Alignment);
+ }
+
+ return RI;
+ }
+
+ ResourceInfo *mapHandleIntrin(CallInst *CI) {
+ FunctionType *FTy = CI->getFunctionType();
+ Type *RetTy = FTy->getReturnType();
+ auto *HandleTy = dyn_cast<TargetExtType>(RetTy);
+ if (!HandleTy) {
+ diagnoseHandle(CI, "dx.handle.fromBinding requires target type");
+ return nullptr;
+ }
+
+ StringRef TypeName = HandleTy->getName();
+ if (TypeName == "dx.TypedBuffer") {
+ return mapBufferType(CI, HandleTy, /*IsTyped=*/true);
+ } else if (TypeName == "dx.RawBuffer") {
+ return mapBufferType(CI, HandleTy, /*IsTyped=*/false);
+ } else if (TypeName == "dx.CBuffer") {
+ // TODO: implement
+ diagnoseHandle(CI, "dx.CBuffer handles are not implemented yet");
+ return nullptr;
+ } else if (TypeName == "dx.Sampler") {
+ // TODO: implement
+ diagnoseHandle(CI, "dx.Sampler handles are not implemented yet");
+ return nullptr;
+ } else if (TypeName == "dx.Texture") {
+ // TODO: implement
+ diagnoseHandle(CI, "dx.Texture handles are not implemented yet");
+ return nullptr;
+ }
+
+ diagnoseHandle(CI, "Invalid target(dx) type");
+ return nullptr;
+ }
+
+ ResourceInfo *mapHandleFromBinding(CallInst *CI) {
+ assert(CI->getIntrinsicID() == Intrinsic::dx_handle_fromBinding &&
+ "Must be dx.handle.fromBinding intrinsic");
+
+ ResourceInfo *RI = mapHandleIntrin(CI);
+ if (!RI)
+ return nullptr;
+
+ uint32_t NextID;
+ if (RI->isCBuffer())
+ NextID = NextCBuf++;
+ else if (RI->isSampler())
+ NextID = NextSmp++;
+ else if (RI->isUAV())
+ NextID = NextUAV++;
+ else
+ NextID = NextSRV++;
+
+ uint32_t Space = cast<ConstantInt>(CI->getArgOperand(0))->getZExtValue();
+ uint32_t LowerBound =
+ cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
+ uint32_t Size = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
+
+ RI->bind(NextID, Space, LowerBound, Size);
+
+ return RI;
+ }
+
+ void mapResources() {
+ for (Function &F : M.functions()) {
+ if (!F.isDeclaration())
+ continue;
+ LLVM_DEBUG(dbgs() << "Function: " << F.getName() << "\n");
+ Intrinsic::ID ID = F.getIntrinsicID();
+ switch (ID) {
+ default:
+ // TODO: handle `dx.op` functions.
+ continue;
+ case Intrinsic::dx_handle_fromBinding:
+ for (User *U : F.users()) {
+ LLVM_DEBUG(dbgs() << " Visiting: " << *U << "\n");
+ if (CallInst *CI = dyn_cast<CallInst>(U))
+ mapHandleFromBinding(CI);
+ }
+ break;
+ }
+ }
+ }
+};
+
+} // namespace
+
//===----------------------------------------------------------------------===//
// DXILResourceAnalysis and DXILResourcePrinterPass
@@ -339,6 +711,7 @@ AnalysisKey DXILResourceAnalysis::Key;
DXILResourceMap DXILResourceAnalysis::run(Module &M,
ModuleAnalysisManager &AM) {
DXILResourceMap Data;
+ ResourceMapper(M, Data).mapResources();
return Data;
}
@@ -351,7 +724,7 @@ PreservedAnalyses DXILResourcePrinterPass::run(Module &M,
OS << "Binding for ";
Handle->print(OS);
OS << "\n";
- // TODO: Info.print(OS);
+ Info.print(OS);
OS << "\n";
}
@@ -373,6 +746,7 @@ void DXILResourceWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
bool DXILResourceWrapperPass::runOnModule(Module &M) {
ResourceMap.reset(new DXILResourceMap());
+ ResourceMapper(M, *ResourceMap).mapResources();
return false;
}
@@ -387,7 +761,7 @@ void DXILResourceWrapperPass::print(raw_ostream &OS, const Module *) const {
OS << "Binding for ";
Handle->print(OS);
OS << "\n";
- // TODO: Info.print(OS);
+ Info.print(OS);
OS << "\n";
}
}
diff --git a/llvm/test/Analysis/DXILResource/buffer-frombinding.ll b/llvm/test/Analysis/DXILResource/buffer-frombinding.ll
new file mode 100644
index 0000000000000..4349adb8ef8eb
--- /dev/null
+++ b/llvm/test/Analysis/DXILResource/buffer-frombinding.ll
@@ -0,0 +1,126 @@
+; RUN: opt -S -disable-output -passes="print<dxil-resource>" < %s 2>&1 | FileCheck %s
+
+ at G = external constant <4 x float>, align 4
+
+define void @test_typedbuffer() {
+ ; RWBuffer<float4> Buf : register(u5, space3)
+ %typed0 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
+ @llvm.dx.handle.fromBinding.tdx.TypedBuffer_f32_1_0(
+ i32 3, i32 5, i32 1, i32 0, i1 false)
+ ; CHECK: Binding for %typed0
+ ; CHECK: Symbol: ptr undef
+ ; CHECK: Name: ""
+ ; CHECK: Binding:
+ ; CHECK: Record ID: 0
+ ; CHECK: Space: 3
+ ; CHECK: Lower Bound: 5
+ ; CHECK: Size: 1
+ ; CHECK: Class: UAV
+ ; CHECK: Kind: TypedBuffer
+ ; CHECK: Globally Coherent: 0
+ ; CHECK: HasCounter: 0
+ ; CHECK: IsROV: 0
+ ; CHECK: Element Type: f32
+ ; CHECK: Element Count: 4
+
+ ; RWBuffer<int> Buf : register(u7, space2)
+ %typed1 = call target("dx.TypedBuffer", i32, 1, 0, 1)
+ @llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_1_0t(
+ i32 2, i32 7, i32 1, i32 0, i1 false)
+ ; CHECK: Binding for %typed1
+ ; CHECK: Symbol: ptr undef
+ ; CHECK: Name: ""
+ ; CHECK: Binding:
+ ; CHECK: Record ID: 1
+ ; CHECK: Space: 2
+ ; CHECK: Lower Bound: 7
+ ; CHECK: Size: 1
+ ; CHECK: Class: UAV
+ ; CHECK: Kind: TypedBuffer
+ ; CHECK: Globally Coherent: 0
+ ; CHECK: HasCounter: 0
+ ; CHECK: IsROV: 0
+ ; CHECK: Element Type: i32
+ ; CHECK: Element Count: 1
+
+ ; 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_0t(
+ i32 2, i32 7, i32 24, i32 0, i1 false)
+ ; CHECK: Binding for %typed2
+ ; CHECK: Symbol: ptr undef
+ ; CHECK: Name: ""
+ ; CHECK: Binding:
+ ; CHECK: Record ID: 0
+ ; CHECK: Space: 2
+ ; CHECK: Lower Bound: 7
+ ; CHECK: Size: 24
+ ; CHECK: Class: SRV
+ ; CHECK: Kind: TypedBuffer
+ ; CHECK: Element Type: u32
+ ; CHECK: Element Count: 4
+
+ ret void
+}
+
+define void @test_structbuffer() {
+ ; 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 0, i1 false)
+ ; CHECK: Binding for %struct0
+ ; CHECK: Symbol: ptr undef
+ ; CHECK: Name: ""
+ ; CHECK: Binding:
+ ; CHECK: Record ID: 1
+ ; CHECK: Space: 4
+ ; CHECK: Lower Bound: 2
+ ; CHECK: Size: 1
+ ; CHECK: Class: SRV
+ ; CHECK: Kind: StructuredBuffer
+ ; CHECK: Buffer Stride: 32
+ ; CHECK: Alignment: 4
+
+ ret void
+}
+
+define void @test_bytebuffer() {
+ ; 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 0, i1 false)
+ ; CHECK: Binding for %byteaddr0
+ ; CHECK: Symbol: ptr undef
+ ; CHECK: Name: ""
+ ; CHECK: Binding:
+ ; CHECK: Record ID: 2
+ ; CHECK: Space: 1
+ ; CHECK: Lower Bound: 8
+ ; CHECK: Size: 1
+ ; CHECK: Class: SRV
+ ; CHECK: Kind: RawBuffer
+
+ ret void
+}
+
+; Note: We need declarations for each handle.fromBinding in the same
+; order a...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/104517
More information about the llvm-commits
mailing list