[llvm] [DirectX] Implement Shader Flag Analysis for `UAVsAtEveryStage` (PR #137085)
Deric C. via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 24 08:50:32 PDT 2025
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/137085
>From 8342b32585317036bf075bf884dd6b813eddd029 Mon Sep 17 00:00:00 2001
From: Icohedron <cheung.deric at gmail.com>
Date: Wed, 23 Apr 2025 21:06:22 +0000
Subject: [PATCH 1/2] Implement UAVsAtEveryStage shader flag
---
llvm/lib/Target/DirectX/DXILShaderFlags.cpp | 20 ++++++++++
.../ShaderFlags/max-64-uavs-array-sm6_5.ll | 5 +++
.../ShaderFlags/max-64-uavs-array-sm6_6.ll | 5 +++
.../DirectX/ShaderFlags/max-64-uavs.ll | 5 +++
.../DirectX/ShaderFlags/res-may-alias-0.ll | 5 +++
.../DirectX/ShaderFlags/res-may-alias-1.ll | 6 ++-
.../res-may-not-alias-shadermodel6.6.ll | 5 +++
.../res-may-not-alias-shadermodel6.7.ll | 5 +++
.../res-may-not-alias-shadermodel6.8.ll | 5 +++
.../typed-uav-load-additional-formats.ll | 5 +++
.../uavs-at-every-stage-lib-valver1.7.ll | 39 ++++++++++++++++++
.../uavs-at-every-stage-lib-valver1.8.ll | 29 ++++++++++++++
.../ShaderFlags/uavs-at-every-stage-vs.ll | 40 +++++++++++++++++++
13 files changed, 173 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/CodeGen/DirectX/ShaderFlags/uavs-at-every-stage-lib-valver1.7.ll
create mode 100644 llvm/test/CodeGen/DirectX/ShaderFlags/uavs-at-every-stage-lib-valver1.8.ll
create mode 100644 llvm/test/CodeGen/DirectX/ShaderFlags/uavs-at-every-stage-vs.ll
diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
index 282b9dcf6de2b..aa140330c61bb 100644
--- a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
+++ b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
@@ -265,6 +265,26 @@ void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM,
NumUAVs += UAV.getBinding().Size;
if (NumUAVs > 8)
CombinedSFMask.Max64UAVs = true;
+
+ // Set UAVsAtEveryStage flag based on the presence of UAVs, the shader
+ // model version, and the shader environment
+ if (!DRM.uavs().empty()) {
+ if (MMDI.ValidatorVersion < VersionTuple(1, 8))
+ CombinedSFMask.UAVsAtEveryStage =
+ MMDI.ShaderProfile != Triple::EnvironmentType::Compute &&
+ MMDI.ShaderProfile != Triple::EnvironmentType::Pixel;
+ else // MMDI.ValidatorVersion >= VersionTuple(1, 8)
+ switch (MMDI.ShaderProfile) {
+ default:
+ break;
+ case Triple::EnvironmentType::Vertex:
+ case Triple::EnvironmentType::Hull:
+ case Triple::EnvironmentType::Domain:
+ case Triple::EnvironmentType::Geometry:
+ CombinedSFMask.UAVsAtEveryStage = true;
+ break;
+ }
+ }
}
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
index 5b978d67866be..b476cab236cb3 100644
--- 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
@@ -29,5 +29,10 @@ define void @test() "hlsl.export" {
ret void
}
+; Set dx.valver and dx.resmayalias to prevent flags ResMayNotAlias and
+; UAVsAtEveryStage from being set, as to not distract from the flag that is
+; actually being tested
!llvm.module.flags = !{!0}
+!dx.valver = !{!1}
!0 = !{i32 1, !"dx.resmayalias", i32 1}
+!1 = !{i32 1, i32 8}
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
index 4b901a78e6ea4..6c2b82a85188e 100644
--- 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
@@ -29,5 +29,10 @@ define void @test() "hlsl.export" {
ret void
}
+; Set dx.valver and dx.resmayalias to prevent flags ResMayNotAlias and
+; UAVsAtEveryStage from being set, as to not distract from the flag that is
+; actually being tested
!llvm.module.flags = !{!0}
+!dx.valver = !{!1}
!0 = !{i32 1, !"dx.resmayalias", i32 1}
+!1 = !{i32 1, i32 8}
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs.ll
index c002ff2851452..9045f75ef33c1 100644
--- a/llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs.ll
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs.ll
@@ -56,5 +56,10 @@ define void @test() "hlsl.export" {
ret void
}
+; Set dx.valver and dx.resmayalias to prevent flags ResMayNotAlias and
+; UAVsAtEveryStage from being set, as to not distract from the flag that is
+; actually being tested
!llvm.module.flags = !{!0}
+!dx.valver = !{!1}
!0 = !{i32 1, !"dx.resmayalias", i32 1}
+!1 = !{i32 1, i32 8}
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-alias-0.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-alias-0.ll
index d15b5c7b61984..6996ccc59c204 100644
--- a/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-alias-0.ll
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-alias-0.ll
@@ -40,4 +40,9 @@ define float @loadSRV() #0 {
; But if it does, ensure that it has no effect.
!0 = !{i32 1, !"dx.resmayalias", i32 0}
+; Set dx.valver to prevent the flag UAVsAtEveryStage from being set, as to not
+; distract from the flag that is actually being tested
+!dx.valver = !{!1}
+!1 = !{i32 1, i32 8}
+
attributes #0 = { convergent norecurse nounwind "hlsl.export"}
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-alias-1.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-alias-1.ll
index edd3250a2db0d..c4f9ab498bddf 100644
--- a/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-alias-1.ll
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-alias-1.ll
@@ -35,7 +35,11 @@ define float @loadSRV() #0 {
}
!llvm.module.flags = !{!0}
-
!0 = !{i32 1, !"dx.resmayalias", i32 1}
+; Set dx.valver to prevent the flag UAVsAtEveryStage from being set, as to not
+; distract from the flag that is actually being tested
+!dx.valver = !{!1}
+!1 = !{i32 1, i32 8}
+
attributes #0 = { convergent norecurse nounwind "hlsl.export"}
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-shadermodel6.6.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-shadermodel6.6.ll
index da7c4c619790c..e2f1155b26063 100644
--- a/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-shadermodel6.6.ll
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-shadermodel6.6.ll
@@ -34,4 +34,9 @@ define float @loadSRV() #0 {
ret float %val
}
+; Set dx.valver to prevent the flag UAVsAtEveryStage from being set, as to not
+; distract from the flag that is actually being tested
+!dx.valver = !{!0}
+!0 = !{i32 1, i32 8}
+
attributes #0 = { convergent norecurse nounwind "hlsl.export"}
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-shadermodel6.7.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-shadermodel6.7.ll
index 87a76162f734e..c6358473ff2e4 100644
--- a/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-shadermodel6.7.ll
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-shadermodel6.7.ll
@@ -35,4 +35,9 @@ define float @loadSRV() #0 {
ret float %val
}
+; Set dx.valver to prevent the flag UAVsAtEveryStage from being set, as to not
+; distract from the flag that is actually being tested
+!dx.valver = !{!0}
+!0 = !{i32 1, i32 8}
+
attributes #0 = { convergent norecurse nounwind "hlsl.export"}
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-shadermodel6.8.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-shadermodel6.8.ll
index a309d8ecea56c..10eb7a878e5c4 100644
--- a/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-shadermodel6.8.ll
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-shadermodel6.8.ll
@@ -35,4 +35,9 @@ define float @loadSRV() #0 {
ret float %val
}
+; Set dx.valver to prevent the flag UAVsAtEveryStage from being set, as to not
+; distract from the flag that is actually being tested
+!dx.valver = !{!0}
+!0 = !{i32 1, i32 8}
+
attributes #0 = { convergent norecurse nounwind "hlsl.export"}
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/typed-uav-load-additional-formats.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/typed-uav-load-additional-formats.ll
index 1bb8a4d78eb16..dd42bb73e9bdd 100644
--- a/llvm/test/CodeGen/DirectX/ShaderFlags/typed-uav-load-additional-formats.ll
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/typed-uav-load-additional-formats.ll
@@ -43,8 +43,13 @@ define void @noload(<4 x float> %val) #0 {
ret void
}
+; Set dx.valver and dx.resmayalias to prevent flags ResMayNotAlias and
+; UAVsAtEveryStage from being set, as to not distract from the flag that is
+; actually being tested
!llvm.module.flags = !{!0}
+!dx.valver = !{!1}
!0 = !{i32 1, !"dx.resmayalias", i32 1}
+!1 = !{i32 1, i32 8}
attributes #0 = { convergent norecurse nounwind "hlsl.export"}
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/uavs-at-every-stage-lib-valver1.7.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/uavs-at-every-stage-lib-valver1.7.ll
new file mode 100644
index 0000000000000..5db3b32deee62
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/uavs-at-every-stage-lib-valver1.7.ll
@@ -0,0 +1,39 @@
+; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
+; RUN: llc %s --filetype=obj -o - | obj2yaml | FileCheck %s --check-prefix=DXC
+
+; This test ensures that a library shader with a UAV gets the module and
+; shader feature flag UAVsAtEveryStage when the DXIL validator version is < 1.8
+
+target triple = "dxil-pc-shadermodel6.5-library"
+
+; CHECK: Combined Shader Flags for Module
+; CHECK-NEXT: Shader Flags Value: 0x00010000
+
+; CHECK: Note: shader requires additional functionality:
+; CHECK: UAVs at every shader stage
+
+; 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)
+ ret void
+}
+
+!dx.valver = !{!1}
+!1 = !{i32 1, i32 7}
+
+; Set dx.resmayalias to prevent the shader flag ResMayNotAlias from being set,
+; as to not distract from the shader flag that is actually being tested
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"dx.resmayalias", i32 1}
+
+; DXC: - Name: SFI0
+; DXC-NEXT: Size: 8
+; DXC-NEXT: Flags:
+; DXC-NOT: {{[A-Za-z]+: +true}}
+; DXC: UAVsAtEveryStage: true
+; DXC-NOT: {{[A-Za-z]+: +true}}
+; DXC: NextUnusedBit: false
+; DXC: ...
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/uavs-at-every-stage-lib-valver1.8.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/uavs-at-every-stage-lib-valver1.8.ll
new file mode 100644
index 0000000000000..98c2e833f4aee
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/uavs-at-every-stage-lib-valver1.8.ll
@@ -0,0 +1,29 @@
+; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
+
+; This test ensures that a library shader with a UAV does not get the module and
+; shader feature flag UAVsAtEveryStage when the DXIL validator version is >= 1.8
+
+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: UAVs at every shader stage
+
+; 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)
+ ret void
+}
+
+!dx.valver = !{!1}
+!1 = !{i32 1, i32 8}
+
+; Set dx.resmayalias to prevent the shader flag ResMayNotAlias from being set,
+; as to not distract from the shader flag that is actually being tested
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"dx.resmayalias", i32 1}
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/uavs-at-every-stage-vs.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/uavs-at-every-stage-vs.ll
new file mode 100644
index 0000000000000..4aeddf08f6a8b
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/uavs-at-every-stage-vs.ll
@@ -0,0 +1,40 @@
+; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
+; TODO: Remove this comment and add 'RUN' to the line below once vertex shaders are supported by llc
+; llc %s --filetype=obj -o - | obj2yaml | FileCheck %s --check-prefix=DXC
+
+; This test ensures that a Vertex shader with a UAV gets the module and
+; shader feature flag UAVsAtEveryStage
+
+target triple = "dxil-pc-shadermodel6.5-vertex"
+
+; CHECK: Combined Shader Flags for Module
+; CHECK-NEXT: Shader Flags Value: 0x00010000
+
+; CHECK: Note: shader requires additional functionality:
+; CHECK: UAVs at every shader stage
+
+; 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)
+ ret void
+}
+
+!dx.valver = !{!1}
+!1 = !{i32 1, i32 8}
+
+; Set dx.resmayalias to prevent the shader flag ResMayNotAlias from being set,
+; as to not distract from the shader flag that is actually being tested
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"dx.resmayalias", i32 1}
+
+; DXC: - Name: SFI0
+; DXC-NEXT: Size: 8
+; DXC-NEXT: Flags:
+; DXC-NOT: {{[A-Za-z]+: +true}}
+; DXC-NEXT: UAVsAtEveryStage: true
+; DXC-NOT: {{[A-Za-z]+: +true}}
+; DXC: NextUnusedBit: false
+; DXC: ...
>From 1f11675d444e81e4d7d3e194a2d6259dbc516341 Mon Sep 17 00:00:00 2001
From: Icohedron <cheung.deric at gmail.com>
Date: Thu, 24 Apr 2025 15:45:10 +0000
Subject: [PATCH 2/2] Change vertex shader test function name and remove
hlsl.export from it
---
.../CodeGen/DirectX/ShaderFlags/uavs-at-every-stage-vs.ll | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/uavs-at-every-stage-vs.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/uavs-at-every-stage-vs.ll
index 4aeddf08f6a8b..f0a9d0762d999 100644
--- a/llvm/test/CodeGen/DirectX/ShaderFlags/uavs-at-every-stage-vs.ll
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/uavs-at-every-stage-vs.ll
@@ -13,8 +13,8 @@ target triple = "dxil-pc-shadermodel6.5-vertex"
; CHECK: Note: shader requires additional functionality:
; CHECK: UAVs at every shader stage
-; CHECK: Function test : 0x00000000
-define void @test() "hlsl.export" {
+; CHECK: Function VSMain : 0x00000000
+define void @VSMain() {
; RWBuffer<float> Buf : register(u0, space0)
%buf0 = call target("dx.TypedBuffer", float, 1, 0, 1)
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0t(
More information about the llvm-commits
mailing list