diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h index 9eac7faab6e0f..03deff63b8457 100644 --- a/llvm/include/llvm/Analysis/DXILResource.h +++ b/llvm/include/llvm/Analysis/DXILResource.h @@ -300,7 +300,7 @@ class ResourceTypeInfo { : ResourceTypeInfo(HandleTy, {}, dxil::ResourceKind::Invalid) {} TargetExtType *getHandleTy() const { return HandleTy; } - LLVM_ABI StructType *createElementStruct(); + LLVM_ABI StructType *createElementStruct(StringRef CBufferName = ""); // Conditions to check before accessing specific views. LLVM_ABI bool isUAV() const; diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp index db4a0d8a89e30..2da6468ec3dcf 100644 --- a/llvm/lib/Analysis/DXILResource.cpp +++ b/llvm/lib/Analysis/DXILResource.cpp @@ -64,7 +64,7 @@ static StringRef getResourceKindName(ResourceKind RK) { case ResourceKind::TextureCubeArray: return "TextureCubeArray"; case ResourceKind::TypedBuffer: - return "TypedBuffer"; + return "Buffer"; case ResourceKind::RawBuffer: return "RawBuffer"; case ResourceKind::StructuredBuffer: @@ -132,6 +132,44 @@ static StringRef getElementTypeName(ElementType ET) { llvm_unreachable("Unhandled ElementType"); } +static StringRef getElementTypeNameForTemplate(ElementType ET) { + switch (ET) { + case ElementType::I1: + return "bool"; + case ElementType::I16: + return "int16_t"; + case ElementType::U16: + return "uint16_t"; + case ElementType::I32: + return "int32_t"; + case ElementType::U32: + return "uint32_t"; + case ElementType::I64: + return "int64_t"; + case ElementType::U64: + return "uint32_t"; + case ElementType::F16: + case ElementType::SNormF16: + case ElementType::UNormF16: + return "half"; + case ElementType::F32: + case ElementType::SNormF32: + case ElementType::UNormF32: + return "float"; + case ElementType::F64: + case ElementType::SNormF64: + case ElementType::UNormF64: + return "double"; + case ElementType::PackedS8x32: + return "int8_t4_packed"; + case ElementType::PackedU8x32: + return "uint8_t4_packed"; + case ElementType::Invalid: + return ""; + } + llvm_unreachable("Unhandled ElementType"); +} + static StringRef getSamplerTypeName(SamplerType ST) { switch (ST) { case SamplerType::Default: @@ -219,12 +257,44 @@ ResourceTypeInfo::ResourceTypeInfo(TargetExtType *HandleTy, } static void formatTypeName(SmallString<64> &Dest, StringRef Name, - bool isWriteable, bool isROV) { - Dest = isWriteable ? (isROV ? "RasterizerOrdered" : "RW") : ""; - Dest += Name; + bool IsWriteable, bool IsROV, + Type *ContainedType = nullptr, + bool IsSigned = true) { + raw_svector_ostream DestStream(Dest); + if (IsWriteable) + DestStream << (IsROV ? "RasterizerOrdered" : "RW"); + DestStream << Name; + + if (!ContainedType) + return; + + StringRef ElementName; + ElementType ET = toDXILElementType(ContainedType, IsSigned); + if (ET != ElementType::Invalid) { + ElementName = getElementTypeNameForTemplate(ET); + } else { + assert(isa(ContainedType) && + "invalid element type for raw buffer"); + StructType *ST = cast(ContainedType); + if (!ST->hasName()) + return; + ElementName = ST->getStructName(); + } + + DestStream << "<" << ElementName; + if (const FixedVectorType *VTy = dyn_cast(ContainedType)) + DestStream << VTy->getNumElements(); + DestStream << ">"; +} + +static StructType *getOrCreateElementStruct(Type *ElemType, StringRef Name) { + StructType *Ty = StructType::getTypeByName(ElemType->getContext(), Name); + if (Ty && Ty->getNumElements() == 1 && Ty->getElementType(0) == ElemType) + return Ty; + return StructType::create(ElemType, Name); } -StructType *ResourceTypeInfo::createElementStruct() { +StructType *ResourceTypeInfo::createElementStruct(StringRef CBufferName) { SmallString<64> TypeName; switch (Kind) { @@ -237,51 +307,61 @@ StructType *ResourceTypeInfo::createElementStruct() { case ResourceKind::TextureCubeArray: { auto *RTy = cast(HandleTy); formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(), - RTy->isROV()); - return StructType::create(RTy->getResourceType(), TypeName); + RTy->isROV(), RTy->getResourceType(), RTy->isSigned()); + return getOrCreateElementStruct(RTy->getResourceType(), TypeName); } case ResourceKind::Texture2DMS: case ResourceKind::Texture2DMSArray: { auto *RTy = cast(HandleTy); formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(), - /*IsROV=*/false); - return StructType::create(RTy->getResourceType(), TypeName); + /*IsROV=*/false, RTy->getResourceType(), RTy->isSigned()); + return getOrCreateElementStruct(RTy->getResourceType(), TypeName); } case ResourceKind::TypedBuffer: { auto *RTy = cast(HandleTy); formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(), - RTy->isROV()); - return StructType::create(RTy->getResourceType(), TypeName); + RTy->isROV(), RTy->getResourceType(), RTy->isSigned()); + return getOrCreateElementStruct(RTy->getResourceType(), TypeName); } case ResourceKind::RawBuffer: { auto *RTy = cast(HandleTy); formatTypeName(TypeName, "ByteAddressBuffer", RTy->isWriteable(), RTy->isROV()); - return StructType::create(Type::getInt32Ty(HandleTy->getContext()), - TypeName); + return getOrCreateElementStruct(Type::getInt32Ty(HandleTy->getContext()), + TypeName); } case ResourceKind::StructuredBuffer: { auto *RTy = cast(HandleTy); + Type *Ty = RTy->getResourceType(); formatTypeName(TypeName, "StructuredBuffer", RTy->isWriteable(), - RTy->isROV()); - return StructType::create(RTy->getResourceType(), TypeName); + RTy->isROV(), RTy->getResourceType(), true); + return getOrCreateElementStruct(Ty, TypeName); } case ResourceKind::FeedbackTexture2D: case ResourceKind::FeedbackTexture2DArray: { auto *RTy = cast(HandleTy); TypeName = formatv("{0}<{1}>", getResourceKindName(Kind), llvm::to_underlying(RTy->getFeedbackType())); - return StructType::create(Type::getInt32Ty(HandleTy->getContext()), - TypeName); + return getOrCreateElementStruct(Type::getInt32Ty(HandleTy->getContext()), + TypeName); + } + case ResourceKind::CBuffer: { + auto *RTy = cast(HandleTy); + LayoutExtType *LayoutType = cast(RTy->getResourceType()); + StructType *Ty = cast(LayoutType->getWrappedType()); + SmallString<64> Name = getResourceKindName(Kind); + if (!CBufferName.empty()) { + Name.append("."); + Name.append(CBufferName); + } + return StructType::create(Ty->elements(), Name); } - case ResourceKind::CBuffer: - return StructType::create(HandleTy->getContext(), "cbuffer"); case ResourceKind::Sampler: { auto *RTy = cast(HandleTy); TypeName = formatv("SamplerState<{0}>", llvm::to_underlying(RTy->getSamplerType())); - return StructType::create(Type::getInt32Ty(HandleTy->getContext()), - TypeName); + return getOrCreateElementStruct(Type::getInt32Ty(HandleTy->getContext()), + TypeName); } case ResourceKind::TBuffer: case ResourceKind::RTAccelerationStructure: diff --git a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp index 625de759eb831..95d930d3e8614 100644 --- a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp +++ b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp @@ -79,7 +79,8 @@ static NamedMDNode *emitResourceMetadata(Module &M, DXILResourceMap &DRM, for (ResourceInfo &RI : DRM) if (!RI.hasSymbol()) - RI.createSymbol(M, DRTM[RI.getHandleTy()].createElementStruct()); + RI.createSymbol(M, + DRTM[RI.getHandleTy()].createElementStruct(RI.getName())); SmallVector SRVs, UAVs, CBufs, Smps; for (const ResourceInfo &RI : DRM.srvs()) diff --git a/llvm/test/Analysis/DXILResource/buffer-frombinding.ll b/llvm/test/Analysis/DXILResource/buffer-frombinding.ll index 6c8476617e693..2623e6f4d44f1 100644 --- a/llvm/test/Analysis/DXILResource/buffer-frombinding.ll +++ b/llvm/test/Analysis/DXILResource/buffer-frombinding.ll @@ -53,7 +53,7 @@ define void @test_typedbuffer() { ; CHECK: Lower Bound: 3 ; CHECK: Size: 24 ; CHECK: Class: SRV - ; CHECK: Kind: TypedBuffer + ; CHECK: Kind: Buffer ; CHECK: Element Type: u32 ; CHECK: Element Count: 4 @@ -70,7 +70,7 @@ define void @test_typedbuffer() { ; CHECK: Globally Coherent: 0 ; CHECK: Counter Direction: Unknown ; CHECK: Class: UAV - ; CHECK: Kind: TypedBuffer + ; CHECK: Kind: Buffer ; CHECK: IsROV: 0 ; CHECK: Element Type: i32 ; CHECK: Element Count: 1 @@ -89,7 +89,7 @@ define void @test_typedbuffer() { ; CHECK: Globally Coherent: 0 ; CHECK: Counter Direction: Decrement ; CHECK: Class: UAV - ; CHECK: Kind: TypedBuffer + ; CHECK: Kind: Buffer ; CHECK: IsROV: 0 ; CHECK: Element Type: f32 ; CHECK: Element Count: 4 @@ -112,7 +112,7 @@ define void @test_typedbuffer() { ; CHECK: Globally Coherent: 0 ; CHECK: Counter Direction: Increment ; CHECK: Class: UAV - ; CHECK: Kind: TypedBuffer + ; CHECK: Kind: Buffer ; CHECK: IsROV: 0 ; CHECK: Element Type: f32 ; CHECK: Element Count: 4 @@ -132,7 +132,7 @@ define void @test_typedbuffer() { ; CHECK: Globally Coherent: 0 ; CHECK: Counter Direction: Invalid ; CHECK: Class: UAV - ; CHECK: Kind: TypedBuffer + ; CHECK: Kind: Buffer ; CHECK: IsROV: 0 ; CHECK: Element Type: f32 ; CHECK: Element Count: 4 diff --git a/llvm/test/CodeGen/DirectX/Metadata/cbuffer-only.ll b/llvm/test/CodeGen/DirectX/Metadata/cbuffer-only.ll index 959150f4c2c6a..b88ac118b3568 100644 --- a/llvm/test/CodeGen/DirectX/Metadata/cbuffer-only.ll +++ b/llvm/test/CodeGen/DirectX/Metadata/cbuffer-only.ll @@ -9,11 +9,11 @@ target triple = "dxil-pc-shadermodel6.6-compute" define void @cbuffer_is_only_binding() { %cbuf = call target("dx.CBuffer", target("dx.Layout", {float}, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 1, i32 8, i32 1, i32 0, i1 false, ptr null) - ; CHECK: %cbuffer = type + ; CHECK: %CBuffer = type { float } ret void } -; CHECK: @[[CB0:.*]] = external constant %cbuffer +; CHECK: @[[CB0:.*]] = external constant %CBuffer ; CHECK: !{i32 0, ptr @[[CB0]], !"" diff --git a/llvm/test/CodeGen/DirectX/Metadata/cbuffer_metadata.ll b/llvm/test/CodeGen/DirectX/Metadata/cbuffer_metadata.ll index 7f878c9be63f2..2699d9ae6e8c1 100644 --- a/llvm/test/CodeGen/DirectX/Metadata/cbuffer_metadata.ll +++ b/llvm/test/CodeGen/DirectX/Metadata/cbuffer_metadata.ll @@ -66,9 +66,9 @@ define void @test() #0 { attributes #0 = { noinline nounwind "hlsl.shader"="compute" } -; CHECK: @CB1 = external constant %cbuffer -; CHECK: @CB2 = external constant %cbuffer.0 -; CHECK: @MyConstants = external constant %cbuffer.1 +; CHECK: @CB1 = external constant %CBuffer.CB1 +; CHECK: @CB2 = external constant %CBuffer.CB2 +; CHECK: @MyConstants = external constant %CBuffer.MyConstants ; CHECK: !dx.resources = !{[[ResList:[!][0-9]+]]} diff --git a/llvm/test/CodeGen/DirectX/Metadata/resource-symbols.ll b/llvm/test/CodeGen/DirectX/Metadata/resource-symbols.ll index f2edcb37513e9..440457b3d415e 100644 --- a/llvm/test/CodeGen/DirectX/Metadata/resource-symbols.ll +++ b/llvm/test/CodeGen/DirectX/Metadata/resource-symbols.ll @@ -11,22 +11,22 @@ define void @test() { ; Buffer %float4 = call target("dx.TypedBuffer", <4 x float>, 0, 0, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false, ptr @A.str) - ; CHECK: %TypedBuffer = type { <4 x float> } + ; CHECK: %"Buffer" = type { <4 x float> } ; Buffer %int = call target("dx.TypedBuffer", i32, 0, 0, 1) @llvm.dx.resource.handlefrombinding(i32 0, i32 1, i32 1, i32 0, i1 false, ptr null) - ; CHECK: %TypedBuffer.0 = type { i32 } + ; CHECK: %"Buffer" = type { i32 } ; Buffer %uint3 = call target("dx.TypedBuffer", <3 x i32>, 0, 0, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 2, i32 1, i32 0, i1 false, ptr null) - ; CHECK: %TypedBuffer.1 = type { <3 x i32> } + ; CHECK: %"Buffer" = type { <3 x i32> } ; StructuredBuffer %struct0 = call target("dx.RawBuffer", %struct.S, 0, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 10, i32 1, i32 0, i1 true, ptr @SB.str) - ; CHECK: %StructuredBuffer = type { %struct.S } + ; CHECK: %"StructuredBuffer" = type { %struct.S } ; ByteAddressBuffer %byteaddr = call target("dx.RawBuffer", i8, 0, 0) @@ -36,10 +36,10 @@ define void @test() { ret void } -; CHECK: @[[T0:.*]] = external constant %TypedBuffer -; CHECK-NEXT: @[[T1:.*]] = external constant %TypedBuffer.0 -; CHECK-NEXT: @[[T2:.*]] = external constant %TypedBuffer.1 -; CHECK-NEXT: @[[S0:.*]] = external constant %StructuredBuffer +; CHECK: @[[T0:.*]] = external constant %"Buffer" +; CHECK-NEXT: @[[T1:.*]] = external constant %"Buffer" +; CHECK-NEXT: @[[T2:.*]] = external constant %"Buffer" +; CHECK-NEXT: @[[S0:.*]] = external constant %"StructuredBuffer" ; CHECK-NEXT: @[[B0:.*]] = external constant %ByteAddressBuffer ; CHECK: !{i32 0, ptr @[[T0]], !"A" diff --git a/llvm/test/CodeGen/DirectX/Metadata/srv_metadata.ll b/llvm/test/CodeGen/DirectX/Metadata/srv_metadata.ll index 725bc97ae39d4..abab5c9fb1166 100644 --- a/llvm/test/CodeGen/DirectX/Metadata/srv_metadata.ll +++ b/llvm/test/CodeGen/DirectX/Metadata/srv_metadata.ll @@ -78,25 +78,24 @@ define void @test() #0 { attributes #0 = { noinline nounwind "hlsl.shader"="compute" } -; CHECK: %TypedBuffer = type { <4 x half> } -; CHECK: %TypedBuffer.0 = type { <2 x float> } -; CHECK: %TypedBuffer.1 = type { double } -; CHECK: %TypedBuffer.2 = type { <4 x i32> } +; CHECK: %"Buffer" = type { <4 x half> } +; CHECK: %"Buffer" = type { <2 x float> } +; CHECK: %"Buffer" = type { double } +; CHECK: %"Buffer" = type { <4 x i32> } ; CHECK: %ByteAddressBuffer = type { i32 } -; CHECK: %StructuredBuffer = type { i16 } -; CHECK: %TypedBuffer.3 = type { i64 } -; CHECK: %TypedBuffer.4 = type { <4 x float> } -; CHECK: %TypedBuffer.5 = type { i64 } - -; CHECK: @Zero = external constant %TypedBuffer -; CHECK: @One = external constant %TypedBuffer.0 -; CHECK: @Two = external constant %TypedBuffer.1 -; CHECK: @Three = external constant %TypedBuffer.2 +; CHECK: %"StructuredBuffer" = type { i16 } +; CHECK: %"Buffer" = type { i64 } +; CHECK: %"Buffer" = type { <4 x float> } + +; CHECK: @Zero = external constant %"Buffer" +; CHECK: @One = external constant %"Buffer" +; CHECK: @Two = external constant %"Buffer" +; CHECK: @Three = external constant %"Buffer" ; CHECK: @Four = external constant %ByteAddressBuffer -; CHECK: @Five = external constant %StructuredBuffer -; CHECK: @Six = external constant %TypedBuffer.3 -; CHECK: @Array = external constant %TypedBuffer.4 -; CHECK: @Seven = external constant %TypedBuffer.5 +; CHECK: @Five = external constant %"StructuredBuffer" +; CHECK: @Six = external constant %"Buffer" +; CHECK: @Array = external constant %"Buffer" +; CHECK: @Seven = external constant %"Buffer" ; CHECK: !dx.resources = !{[[ResList:[!][0-9]+]]} diff --git a/llvm/test/CodeGen/DirectX/Metadata/uav_metadata.ll b/llvm/test/CodeGen/DirectX/Metadata/uav_metadata.ll index bc589ef1752b6..9893f8b9ea4d7 100644 --- a/llvm/test/CodeGen/DirectX/Metadata/uav_metadata.ll +++ b/llvm/test/CodeGen/DirectX/Metadata/uav_metadata.ll @@ -85,7 +85,7 @@ define void @test() #0 { %Array_42_h = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0) @llvm.dx.resource.handlefrombinding(i32 3, i32 4, i32 100, i32 42, i1 false, ptr @Array.str) - ; Same buffer type as Nine + ; Same buffer type as Nine - should have the same type in metadata ; RWBuffer Ten : register(u2); %Ten_h = call target("dx.TypedBuffer", i64, 1, 0, 0) @llvm.dx.resource.handlefrombinding(i32 5, i32 22, i32 1, i32 0, i1 false, ptr @Ten.str) @@ -95,31 +95,30 @@ define void @test() #0 { attributes #0 = { noinline nounwind "hlsl.shader"="compute" } -; CHECK: %RWTypedBuffer = type { <4 x half> } -; CHECK: %RWTypedBuffer.0 = type { <2 x float> } -; CHECK: %RWTypedBuffer.1 = type { double } -; CHECK: %RWTypedBuffer.2 = type { <4 x i32> } +; CHECK: %"RWBuffer" = type { <4 x half> } +; CHECK: %"RWBuffer" = type { <2 x float> } +; CHECK: %"RWBuffer" = type { double } +; CHECK: %"RWBuffer" = type { <4 x i32> } ; CHECK: %RWByteAddressBuffer = type { i32 } -; CHECK: %RWStructuredBuffer = type { i16 } -; CHECK: %RasterizerOrderedTypedBuffer = type { <4 x i32> } -; CHECK: %RasterizerOrderedStructuredBuffer = type { <4 x i32> } +; CHECK: %"RWStructuredBuffer" = type { i16 } +; CHECK: %"RasterizerOrderedBuffer" = type { <4 x i32> } +; CHECK: %"RasterizerOrderedStructuredBuffer" = type { <4 x i32> } ; CHECK: %RasterizerOrderedByteAddressBuffer = type { i32 } -; CHECK: %RWTypedBuffer.3 = type { i64 } -; CHECK: %RWTypedBuffer.4 = type { <4 x float> } -; CHECK: %RWTypedBuffer.5 = type { i64 } - -; CHECK: @Zero = external constant %RWTypedBuffer -; CHECK: @One = external constant %RWTypedBuffer.0 -; CHECK: @Two = external constant %RWTypedBuffer.1 -; CHECK: @Three = external constant %RWTypedBuffer.2 +; CHECK: %"RWBuffer" = type { i64 } +; CHECK: %"RWBuffer" = type { <4 x float> } + +; CHECK: @Zero = external constant %"RWBuffer" +; CHECK: @One = external constant %"RWBuffer" +; CHECK: @Two = external constant %"RWBuffer" +; CHECK: @Three = external constant %"RWBuffer" ; CHECK: @Four = external constant %RWByteAddressBuffer -; CHECK: @Five = external constant %RWStructuredBuffer -; CHECK: @Six = external constant %RasterizerOrderedTypedBuffer -; CHECK: @Seven = external constant %RasterizerOrderedStructuredBuffer +; CHECK: @Five = external constant %"RWStructuredBuffer" +; CHECK: @Six = external constant %"RasterizerOrderedBuffer" +; CHECK: @Seven = external constant %"RasterizerOrderedStructuredBuffer" ; CHECK: @Eight = external constant %RasterizerOrderedByteAddressBuffer -; CHECK: @Nine = external constant %RWTypedBuffer.3 -; CHECK: @Array = external constant %RWTypedBuffer.4 -; CHECK: @Ten = external constant %RWTypedBuffer.5 +; CHECK: @Nine = external constant %"RWBuffer" +; CHECK: @Array = external constant %"RWBuffer" +; CHECK: @Ten = external constant %"RWBuffer" ; CHECK: !dx.resources = !{[[ResList:[!][0-9]+]]} diff --git a/llvm/unittests/Analysis/DXILResourceTest.cpp b/llvm/unittests/Analysis/DXILResourceTest.cpp index f6d6ddf9cbb2d..ee37fad04f389 100644 --- a/llvm/unittests/Analysis/DXILResourceTest.cpp +++ b/llvm/unittests/Analysis/DXILResourceTest.cpp @@ -367,10 +367,12 @@ TEST(DXILResource, AnnotationsAndMetadata) { // cbuffer cb0 { float4 g_X; float4 g_Y; } { - StructType *CBufType0 = + StructType *CBufStruct = StructType::create(Context, {Floatx4Ty, Floatx4Ty}, "cb0"); - ResourceTypeInfo RTI(llvm::TargetExtType::get(Context, "dx.CBuffer", - CBufType0, {/*Size=*/32})); + TargetExtType *CBufLayoutType = + llvm::TargetExtType::get(Context, "dx.Layout", CBufStruct, {32, 0, 16}); + ResourceTypeInfo RTI( + llvm::TargetExtType::get(Context, "dx.CBuffer", CBufLayoutType)); EXPECT_EQ(RTI.getResourceClass(), ResourceClass::CBuffer); EXPECT_EQ(RTI.getCBufferSize(DL), 32u); EXPECT_EQ(RTI.getResourceKind(), ResourceKind::CBuffer);