[llvm] [DirectX] Implement Max64UAVs shader flag analysis (PR #136229)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 17 17:15:50 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-directx
Author: Deric C. (Icohedron)
<details>
<summary>Changes</summary>
Fixes [#<!-- -->114553](https://github.com/llvm/llvm-project/issues/114553)
This implementation replicates the behavior of DXC in setting the `m_b64UAVs` flag: the `Max64UAVs` DXIL module flag is set in the presence of more than 8 UAVs in a DXIL module.
The behavior of how UAV (resource) arrays are counted differs based on Shader Model version:
- If Shader Model < 6.6, then a UAV array counts as a single UAV regardless of its range size
- if Shader Model >= 6.6, then a UAV array contributes its range size to the total number of UAVs
I initially thought the complete implementation of this analysis may be blocked by the resource arrays implementation, but it seems that it is not the case, as the `@<!-- -->llvm.dx.resource.handle*` already includes a range size argument.
---
Full diff: https://github.com/llvm/llvm-project/pull/136229.diff
4 Files Affected:
- (modified) llvm/lib/Target/DirectX/DXILShaderFlags.cpp (+10)
- (added) llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs-array-sm6_5.ll (+33)
- (added) llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs-array-sm6_6.ll (+33)
- (added) llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs.ll (+60)
``````````diff
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<float> 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<float> 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<float> 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<float> 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<float> 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<float> 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<float> 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<float> 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<float> 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<float> 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<float> 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<float> 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<float> 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}
``````````
</details>
https://github.com/llvm/llvm-project/pull/136229
More information about the llvm-commits
mailing list