From b8ef7b390a923400bac9a68e0c603cedc513a4af Mon Sep 17 00:00:00 2001 From: Icohedron Date: Fri, 18 Apr 2025 00:01:14 +0000 Subject: [PATCH] Implement Max64UAVs shader flag analysis --- llvm/lib/Target/DirectX/DXILShaderFlags.cpp | 10 ++++ .../ShaderFlags/max-64-uavs-array-sm6_5.ll | 33 ++++++++++ .../ShaderFlags/max-64-uavs-array-sm6_6.ll | 33 ++++++++++ .../DirectX/ShaderFlags/max-64-uavs.ll | 60 +++++++++++++++++++ 4 files changed, 136 insertions(+) create mode 100644 llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs-array-sm6_5.ll create mode 100644 llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs-array-sm6_6.ll create mode 100644 llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs.ll diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp index 1331b0d1d852b..282b9dcf6de2b 100644 --- a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp +++ b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp @@ -255,6 +255,16 @@ void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM, EntryFunProps.Entry->getContext().diagnose(DiagnosticInfoUnsupported( *(EntryFunProps.Entry), "Inconsistent optnone attribute ")); } + + // Set the Max64UAVs flag if the number of UAVs is > 8 + uint32_t NumUAVs = 0; + for (auto &UAV : DRM.uavs()) + if (MMDI.DXILVersion < VersionTuple(1, 6)) + NumUAVs++; + else // MMDI.DXILVersion >= VersionTuple(1, 6) + NumUAVs += UAV.getBinding().Size; + if (NumUAVs > 8) + CombinedSFMask.Max64UAVs = true; } void ComputedShaderFlags::print(raw_ostream &OS) const { diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs-array-sm6_5.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs-array-sm6_5.ll new file mode 100644 index 0000000000000..5b978d67866be --- /dev/null +++ b/llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs-array-sm6_5.ll @@ -0,0 +1,33 @@ +; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s + +; This test makes sure that resource arrays only add 1 to the count of the +; number of UAVs for setting the shader flag '64 UAV slots' when the shader +; model version is < 6.6 + +; Note: there is no feature flag here (only a module flag), so we don't have an +; object test. + +target triple = "dxil-pc-shadermodel6.5-library" + +; CHECK: Combined Shader Flags for Module +; CHECK-NEXT: Shader Flags Value: 0x00000000 + +; CHECK-NOT: Note: shader requires additional functionality: +; CHECK-NOT: 64 UAV slots + +; CHECK: Function test : 0x00000000 +define void @test() "hlsl.export" { + ; RWBuffer Buf : register(u0, space0) + %buf0 = call target("dx.TypedBuffer", float, 1, 0, 1) + @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t( + i32 0, i32 0, i32 1, i32 0, i1 false) + + ; RWBuffer Buf[8] : register(u1, space0) + %buf1 = call target("dx.TypedBuffer", float, 1, 0, 1) + @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t( + i32 0, i32 1, i32 8, i32 0, i1 false) + ret void +} + +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"dx.resmayalias", i32 1} diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs-array-sm6_6.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs-array-sm6_6.ll new file mode 100644 index 0000000000000..4b901a78e6ea4 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs-array-sm6_6.ll @@ -0,0 +1,33 @@ +; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s + +; This test makes sure that resource arrays sizes are accounted for when +; counting the number of UAVs for setting the shader flag '64 UAV slots' when +; the shader model version is >= 6.6 + +; Note: there is no feature flag here (only a module flag), so we don't have an +; object test. + +target triple = "dxil-pc-shadermodel6.6-library" + +; CHECK: Combined Shader Flags for Module +; CHECK-NEXT: Shader Flags Value: 0x00008000 + +; CHECK: Note: shader requires additional functionality: +; CHECK: 64 UAV slots + +; CHECK: Function test : 0x00000000 +define void @test() "hlsl.export" { + ; RWBuffer Buf : register(u0, space0) + %buf0 = call target("dx.TypedBuffer", float, 1, 0, 1) + @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t( + i32 0, i32 0, i32 1, i32 0, i1 false) + + ; RWBuffer Buf[8] : register(u1, space0) + %buf1 = call target("dx.TypedBuffer", float, 1, 0, 1) + @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t( + i32 0, i32 1, i32 8, i32 0, i1 false) + ret void +} + +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"dx.resmayalias", i32 1} diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs.ll new file mode 100644 index 0000000000000..c002ff2851452 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs.ll @@ -0,0 +1,60 @@ +; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s + +; This test makes sure that the shader flag '64 UAV slots' is set when there are +; more than 8 UAVs in the module. + +; Note: there is no feature flag here (only a module flag), so we don't have an +; object test. + +target triple = "dxil-pc-shadermodel6.7-library" + +; CHECK: Combined Shader Flags for Module +; CHECK-NEXT: Shader Flags Value: 0x00008000 + +; CHECK: Note: shader requires additional functionality: +; CHECK: 64 UAV slots + +; Note: 64 UAV slots does not get set per-function +; CHECK: Function test : 0x00000000 +define void @test() "hlsl.export" { + ; RWBuffer Buf : register(u0, space0) + %buf0 = call target("dx.TypedBuffer", float, 1, 0, 1) + @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t( + i32 0, i32 0, i32 1, i32 0, i1 false) + ; RWBuffer Buf : register(u1, space0) + %buf1 = call target("dx.TypedBuffer", float, 1, 0, 1) + @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t( + i32 0, i32 1, i32 1, i32 0, i1 false) + ; RWBuffer Buf : register(u2, space0) + %buf2 = call target("dx.TypedBuffer", float, 1, 0, 1) + @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t( + i32 0, i32 2, i32 1, i32 0, i1 false) + ; RWBuffer Buf : register(u3, space0) + %buf3 = call target("dx.TypedBuffer", float, 1, 0, 1) + @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t( + i32 0, i32 3, i32 1, i32 0, i1 false) + ; RWBuffer Buf : register(u4, space0) + %buf4 = call target("dx.TypedBuffer", float, 1, 0, 1) + @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t( + i32 0, i32 4, i32 1, i32 0, i1 false) + ; RWBuffer Buf : register(u5, space0) + %buf5 = call target("dx.TypedBuffer", float, 1, 0, 1) + @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t( + i32 0, i32 5, i32 1, i32 0, i1 false) + ; RWBuffer Buf : register(u6, space0) + %buf6 = call target("dx.TypedBuffer", float, 1, 0, 1) + @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t( + i32 0, i32 6, i32 1, i32 0, i1 false) + ; RWBuffer Buf : register(u7, space0) + %buf7 = call target("dx.TypedBuffer", float, 1, 0, 1) + @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t( + i32 0, i32 7, i32 1, i32 0, i1 false) + ; RWBuffer Buf : register(u8, space0) + %buf8 = call target("dx.TypedBuffer", float, 1, 0, 1) + @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t( + i32 0, i32 8, i32 1, i32 0, i1 false) + ret void +} + +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"dx.resmayalias", i32 1}