[llvm] 80fa621 - [DirectX] Set shader feature flags MinimumPrecision and NativeLowPrecision, and refactor the logic for setting low-precision-related flags (#139623)
via llvm-commits
llvm-commits at lists.llvm.org
Wed May 14 10:37:31 PDT 2025
Author: Deric C.
Date: 2025-05-14T10:37:27-07:00
New Revision: 80fa6214821582511c687d00a484929530df1661
URL: https://github.com/llvm/llvm-project/commit/80fa6214821582511c687d00a484929530df1661
DIFF: https://github.com/llvm/llvm-project/commit/80fa6214821582511c687d00a484929530df1661.diff
LOG: [DirectX] Set shader feature flags MinimumPrecision and NativeLowPrecision, and refactor the logic for setting low-precision-related flags (#139623)
Fixes #138997 and does refactoring for low-precision-related flags.
The shader feature flags MinimumPrecision and NativeLowPrecision were
not being set, leading to validation errors.
This PR sets these shader feature flags [as in
DXC](https://github.com/microsoft/DirectXShaderCompiler/blob/377c4ca6d82adb83bf2eaf978a7040443848d6fd/lib/DXIL/DxilShaderFlags.cpp#L58-L63)
and adds tests for them.
This PR also performs some refactoring of low-precision-related flags to
make it less confusing.
- The `UseNativeLowPrecision` DXIL module flag has been renamed to
`NativeLowPrecisionMode` to imply that it is setting some execution
state which the module should be interpreted with
- The LLVM module flag `dx.nativelowprec` is now read only once and sets
a bool to be used by `updateFunctionFlags()` and for setting the DXIL
module flag `NativeLowPrecisionMode`
- The `MinimumPrecision`, `NativeLowPrecision`, and
`LowPrecisionPresent` shader feature flags are all set together under
`updateFunctionFlags()`
- Moved the logic for setting DXIL module flags `NativeLowPrecisionMode`
and `ResMayNotAlias` out of the per-function loop and placed it
alongside the logic for setting other DXIL module flags
(`DisableOptimizations`, `Max64UAVs`, and `UAVsAtEveryStage` flags)
---------
Co-authored-by: Justin Bogner <mail at justinbogner.com>
Added:
Modified:
llvm/include/llvm/BinaryFormat/DXContainerConstants.def
llvm/lib/Target/DirectX/DXILShaderFlags.cpp
llvm/lib/Target/DirectX/DXILShaderFlags.h
llvm/test/CodeGen/DirectX/ShaderFlags/low-precision.ll
llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-sm6.7.ll
llvm/test/CodeGen/DirectX/ShaderFlags/use-native-low-precision-0.ll
llvm/test/CodeGen/DirectX/ShaderFlags/use-native-low-precision-1.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
index 1645018aebedb..81d2c54b6e07c 100644
--- a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
+++ b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
@@ -34,7 +34,7 @@ SHADER_FEATURE_FLAG(14, 19, WaveOps, "Wave level operations")
SHADER_FEATURE_FLAG(15, 20, Int64Ops, "64-Bit integer")
SHADER_FEATURE_FLAG(16, 21, ViewID, "View Instancing")
SHADER_FEATURE_FLAG(17, 22, Barycentrics, "Barycentrics")
-SHADER_FEATURE_FLAG(18, -1, NativeLowPrecision, "Use native low precision")
+SHADER_FEATURE_FLAG(18, -1, NativeLowPrecision, "Native low-precision data types")
SHADER_FEATURE_FLAG(19, 24, ShadingRate, "Shading Rate")
SHADER_FEATURE_FLAG(20, 25, Raytracing_Tier_1_1, "Raytracing tier 1.1 features")
SHADER_FEATURE_FLAG(21, 26, SamplerFeedback, "Sampler feedback")
@@ -115,9 +115,9 @@ DXIL_MODULE_FLAG( 0, DisableOptimizations, "Disable shader optimizations")
DXIL_MODULE_FLAG( 1, DisableMathRefactoring, "Disable math refactoring")
DXIL_MODULE_FLAG( 3, ForceEarlyDepthStencil, "Force early depth-stencil test")
DXIL_MODULE_FLAG( 4, EnableRawAndStructuredBuffers, "Raw and structured buffers")
-DXIL_MODULE_FLAG( 5, LowPrecisionPresent, "Low-precision data types")
+DXIL_MODULE_FLAG( 5, LowPrecisionPresent, "Low-precision data types present")
DXIL_MODULE_FLAG( 8, AllResourcesBound, "All resources bound for the duration of shader execution")
-DXIL_MODULE_FLAG(23, UseNativeLowPrecision, "Use native low precision")
+DXIL_MODULE_FLAG(23, NativeLowPrecisionMode, "Enable native low-precision data types")
DXIL_MODULE_FLAG(33, ResMayNotAlias, "Any UAV may not alias any other UAV")
#undef DXIL_MODULE_FLAG
diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
index b50a9b5d6051c..8bdaf68e18e70 100644
--- a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
+++ b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
@@ -142,6 +142,13 @@ void ModuleShaderFlags::updateFunctionFlags(ComputedShaderFlags &CSF,
}
}
+ if (CSF.LowPrecisionPresent) {
+ if (CanSetNativeLowPrecisionMode)
+ CSF.NativeLowPrecision = true;
+ else
+ CSF.MinimumPrecision = true;
+ }
+
if (!CSF.Int64Ops)
CSF.Int64Ops = I.getType()->isIntegerTy(64);
@@ -206,13 +213,20 @@ void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM,
const ModuleMetadataInfo &MMDI) {
CanSetResMayNotAlias = MMDI.DXILVersion >= VersionTuple(1, 7);
-
- // Check if -res-may-alias was provided on the command line.
- // The command line option will set the dx.resmayalias module flag to 1.
- if (auto *RMA = mdconst::extract_or_null<ConstantInt>(
+ // The command line option -res-may-alias will set the dx.resmayalias module
+ // flag to 1, thereby disabling the ability to set the ResMayNotAlias flag
+ if (auto *ResMayAlias = mdconst::extract_or_null<ConstantInt>(
M.getModuleFlag("dx.resmayalias")))
- if (RMA->getValue() != 0)
- CanSetResMayNotAlias = false;
+ CanSetResMayNotAlias = !ResMayAlias->getValue().getBoolValue();
+
+ // NativeLowPrecisionMode can only be set when the command line option
+ // -enable-16bit-types is provided. This is indicated by the dx.nativelowprec
+ // module flag being set
+ CanSetNativeLowPrecisionMode = false;
+ if (auto *NativeLowPrec = mdconst::extract_or_null<ConstantInt>(
+ M.getModuleFlag("dx.nativelowprec")))
+ if (MMDI.ShaderModelVersion >= VersionTuple(6, 2))
+ CanSetNativeLowPrecisionMode = NativeLowPrec->getValue().getBoolValue();
CallGraph CG(M);
@@ -238,18 +252,6 @@ void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM,
continue;
}
- // Set ResMayNotAlias to true if DXIL validator version < 1.8 and there
- // are UAVs present globally.
- if (CanSetResMayNotAlias && MMDI.ValidatorVersion < VersionTuple(1, 8))
- SCCSF.ResMayNotAlias = !DRM.uavs().empty();
-
- // Set UseNativeLowPrecision using dx.nativelowprec module metadata
- if (auto *NativeLowPrec = mdconst::extract_or_null<ConstantInt>(
- M.getModuleFlag("dx.nativelowprec")))
- if (MMDI.ShaderModelVersion >= VersionTuple(6, 2) &&
- NativeLowPrec->getValue() != 0)
- SCCSF.UseNativeLowPrecision = true;
-
ComputedShaderFlags CSF;
for (const auto &BB : *F)
for (const auto &I : BB)
@@ -286,6 +288,17 @@ void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM,
*(EntryFunProps.Entry), "Inconsistent optnone attribute "));
}
+ // Set ResMayNotAlias to true if DXIL validator version < 1.8 and there
+ // are UAVs present globally.
+ if (CanSetResMayNotAlias && MMDI.ValidatorVersion < VersionTuple(1, 8))
+ CombinedSFMask.ResMayNotAlias = !DRM.uavs().empty();
+
+ // Set the module flag that enables native low-precision execution mode. This
+ // is needed even if the module does not use 16-bit types because a
+ // corresponding debug module may include 16-bit types, and tools that use the
+ // debug module may expect it to have the same flags as the original
+ CombinedSFMask.NativeLowPrecisionMode = CanSetNativeLowPrecisionMode;
+
// Set the Max64UAVs flag if the number of UAVs is > 8
uint32_t NumUAVs = 0;
for (auto &UAV : DRM.uavs())
diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.h b/llvm/lib/Target/DirectX/DXILShaderFlags.h
index 0e0bd0036349e..c4eef4e708cfd 100644
--- a/llvm/lib/Target/DirectX/DXILShaderFlags.h
+++ b/llvm/lib/Target/DirectX/DXILShaderFlags.h
@@ -91,7 +91,10 @@ struct ModuleShaderFlags {
const ComputedShaderFlags &getCombinedFlags() const { return CombinedSFMask; }
private:
- bool CanSetResMayNotAlias;
+ // Booleans set by module flags
+ bool CanSetResMayNotAlias; // dx.resmayalias
+ bool CanSetNativeLowPrecisionMode; // dx.nativelowprec
+
/// Map of Function-Shader Flag Mask pairs representing properties of each of
/// the functions in the module. Shader Flags of each function represent both
/// module-level and function-level flags
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/low-precision.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/low-precision.ll
index 561e09bb1e9dc..5ecac3980d044 100644
--- a/llvm/test/CodeGen/DirectX/ShaderFlags/low-precision.ll
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/low-precision.ll
@@ -1,4 +1,10 @@
; 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
+
+; Check that when the dx.nativelowprec module flag is not specified, the
+; module-level shader flag UseNativeLowPrecision is not set, and the
+; MinimumPrecision feature flag is set due to the presence of half and i16
+; without native low precision.
target triple = "dxil-pc-shadermodel6.7-library"
@@ -6,25 +12,33 @@ target triple = "dxil-pc-shadermodel6.7-library"
;CHECK-NEXT: ; Shader Flags Value: 0x00000020
;CHECK-NEXT: ;
;CHECK-NEXT: ; Note: shader requires additional functionality:
+;CHECK-NEXT: ; Minimum-precision data types
;CHECK-NEXT: ; Note: extra DXIL module flags:
-;CHECK-NEXT: ; Low-precision data types
+;CHECK-NEXT: ; Low-precision data types present
;CHECK-NEXT: ;
;CHECK-NEXT: ; Shader Flags for Module Functions
;CHECK-LABEL: ; Function add_i16 : 0x00000020
-define i16 @add_i16(i16 %a, i16 %b) {
+define i16 @add_i16(i16 %a, i16 %b) "hlsl.export" {
%sum = add i16 %a, %b
ret i16 %sum
}
;CHECK-LABEL: ; Function add_i32 : 0x00000000
-define i32 @add_i32(i32 %a, i32 %b) {
+define i32 @add_i32(i32 %a, i32 %b) "hlsl.export" {
%sum = add i32 %a, %b
ret i32 %sum
}
;CHECK-LABEL: ; Function add_half : 0x00000020
-define half @add_half(half %a, half %b) {
+define half @add_half(half %a, half %b) "hlsl.export" {
%sum = fadd half %a, %b
ret half %sum
}
+
+; DXC: - Name: SFI0
+; DXC-NEXT: Size: 8
+; DXC-NEXT: Flags:
+; DXC: MinimumPrecision: true
+; DXC: NativeLowPrecision: false
+; DXC: ...
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-sm6.7.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-sm6.7.ll
index 934319557a11f..fc6560e321b4b 100644
--- a/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-sm6.7.ll
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-sm6.7.ll
@@ -2,8 +2,8 @@
; This test checks to ensure the behavior of the DXIL shader flag analysis
; for the flag ResMayNotAlias is correct when the DXIL Version is >= 1.7 and the
-; DXIL Validator Version < 1.8. The ResMayNotAlias flag (0x20000000) should be
-; set on all functions if there are one or more UAVs present globally in the
+; DXIL Validator Version < 1.8. The ResMayNotAlias module flag (0x20000000)
+; should be set if there are one or more UAVs present globally in the
; module.
target triple = "dxil-pc-shadermodel6.7-library"
@@ -19,7 +19,7 @@ target triple = "dxil-pc-shadermodel6.7-library"
; CHECK: Any UAV may not alias any other UAV
;
-; CHECK: Function loadUAV : 0x200000000
+; CHECK: Function loadUAV : 0x00000000
define float @loadUAV() #0 {
%res = call target("dx.TypedBuffer", float, 1, 0, 0)
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false)
@@ -29,7 +29,7 @@ define float @loadUAV() #0 {
ret float %val
}
-; CHECK: Function loadSRV : 0x200000010
+; CHECK: Function loadSRV : 0x00000010
define float @loadSRV() #0 {
%res = tail call target("dx.RawBuffer", float, 0, 0)
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false)
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/use-native-low-precision-0.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/use-native-low-precision-0.ll
index c537a01482f39..2e68fe375a42c 100644
--- a/llvm/test/CodeGen/DirectX/ShaderFlags/use-native-low-precision-0.ll
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/use-native-low-precision-0.ll
@@ -1,7 +1,9 @@
; 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
; Check that when the dx.nativelowprec module flag is set to 0, the module-level
-; shader flag UseNativeLowPrecision is not set
+; shader flag UseNativeLowPrecision is not set, and the MinimumPrecision feature
+; flag is set due to the presence of half and i16 without native low precision.
target triple = "dxil-pc-shadermodel6.7-library"
@@ -9,29 +11,37 @@ target triple = "dxil-pc-shadermodel6.7-library"
;CHECK-NEXT: ; Shader Flags Value: 0x00000020
;CHECK-NEXT: ;
;CHECK-NEXT: ; Note: shader requires additional functionality:
+;CHECK-NEXT: ; Minimum-precision data types
;CHECK-NEXT: ; Note: extra DXIL module flags:
-;CHECK-NEXT: ; Low-precision data types
-;CHECK-NOT: ; Native 16bit types enabled
+;CHECK-NEXT: ; Low-precision data types present
+;CHECK-NOT: ; Enable native low-precision data types
;CHECK-NEXT: ;
;CHECK-NEXT: ; Shader Flags for Module Functions
;CHECK-LABEL: ; Function add_i16 : 0x00000020
-define i16 @add_i16(i16 %a, i16 %b) {
+define i16 @add_i16(i16 %a, i16 %b) "hlsl.export" {
%sum = add i16 %a, %b
ret i16 %sum
}
;CHECK-LABEL: ; Function add_i32 : 0x00000000
-define i32 @add_i32(i32 %a, i32 %b) {
+define i32 @add_i32(i32 %a, i32 %b) "hlsl.export" {
%sum = add i32 %a, %b
ret i32 %sum
}
;CHECK-LABEL: ; Function add_half : 0x00000020
-define half @add_half(half %a, half %b) {
+define half @add_half(half %a, half %b) "hlsl.export" {
%sum = fadd half %a, %b
ret half %sum
}
!llvm.module.flags = !{!0}
!0 = !{i32 1, !"dx.nativelowprec", i32 0}
+
+; DXC: - Name: SFI0
+; DXC-NEXT: Size: 8
+; DXC-NEXT: Flags:
+; DXC: MinimumPrecision: true
+; DXC: NativeLowPrecision: false
+; DXC: ...
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/use-native-low-precision-1.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/use-native-low-precision-1.ll
index 07c4b9064d666..cb3b486cebce5 100644
--- a/llvm/test/CodeGen/DirectX/ShaderFlags/use-native-low-precision-1.ll
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/use-native-low-precision-1.ll
@@ -1,4 +1,9 @@
; 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
+
+; Check that when the dx.nativelowprec module flag is set to 1, the module-level
+; shader flag UseNativeLowPrecision is set, and the NativeLowPrecision feature
+; flag is set
target triple = "dxil-pc-shadermodel6.7-library"
@@ -6,32 +11,37 @@ target triple = "dxil-pc-shadermodel6.7-library"
;CHECK-NEXT: ; Shader Flags Value: 0x00800020
;CHECK-NEXT: ;
;CHECK-NEXT: ; Note: shader requires additional functionality:
+;CHECK-NEXT: ; Native low-precision data types
;CHECK-NEXT: ; Note: extra DXIL module flags:
-;CHECK-NEXT: ; Low-precision data types
-;CHECK-NEXT: ; Use native low precision
+;CHECK-NEXT: ; Low-precision data types present
+;CHECK-NEXT: ; Enable native low-precision data types
;CHECK-NEXT: ;
;CHECK-NEXT: ; Shader Flags for Module Functions
-;CHECK-LABEL: ; Function add_i16 : 0x00800020
-define i16 @add_i16(i16 %a, i16 %b) {
+;CHECK-LABEL: ; Function add_i16 : 0x00000020
+define i16 @add_i16(i16 %a, i16 %b) "hlsl.export" {
%sum = add i16 %a, %b
ret i16 %sum
}
-; NOTE: The flag for native low precision (0x80000) is set for every function
-; in the module regardless of whether or not the function uses low precision
-; data types (flag 0x20). This matches the behavior in DXC
-;CHECK-LABEL: ; Function add_i32 : 0x00800000
-define i32 @add_i32(i32 %a, i32 %b) {
+;CHECK-LABEL: ; Function add_i32 : 0x00000000
+define i32 @add_i32(i32 %a, i32 %b) "hlsl.export" {
%sum = add i32 %a, %b
ret i32 %sum
}
-;CHECK-LABEL: ; Function add_half : 0x00800020
-define half @add_half(half %a, half %b) {
+;CHECK-LABEL: ; Function add_half : 0x00000020
+define half @add_half(half %a, half %b) "hlsl.export" {
%sum = fadd half %a, %b
ret half %sum
}
!llvm.module.flags = !{!0}
!0 = !{i32 1, !"dx.nativelowprec", i32 1}
+
+; DXC: - Name: SFI0
+; DXC-NEXT: Size: 8
+; DXC-NEXT: Flags:
+; DXC: MinimumPrecision: false
+; DXC: NativeLowPrecision: true
+; DXC: ...
More information about the llvm-commits
mailing list