[llvm] [DirectX] Set shader feature flags MinimumPrecision and NativeLowPrecision (PR #139623)

Deric C. via llvm-commits llvm-commits at lists.llvm.org
Tue May 13 11:45:38 PDT 2025


https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/139623

>From 2039fa7a08f488f0029e31d0402447da0b142634 Mon Sep 17 00:00:00 2001
From: Icohedron <cheung.deric at gmail.com>
Date: Mon, 12 May 2025 20:58:36 +0000
Subject: [PATCH 1/4] Set shader feature flags MinimumPrecision and
 NativeLowPrecision

---
 llvm/lib/Target/DirectX/DXILShaderFlags.cpp   |  8 ++++++++
 .../DirectX/ShaderFlags/low-precision.ll      | 20 ++++++++++++++++---
 .../ShaderFlags/use-native-low-precision-0.ll | 18 +++++++++++++----
 .../ShaderFlags/use-native-low-precision-1.ll | 19 +++++++++++++++---
 4 files changed, 55 insertions(+), 10 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
index b50a9b5d6051c..36f909ffa6ef5 100644
--- a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
+++ b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
@@ -296,6 +296,14 @@ void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM,
   if (NumUAVs > 8)
     CombinedSFMask.Max64UAVs = true;
 
+  // Set the Shader Feature Info flags related to low-precision datatypes
+  if (CombinedSFMask.LowPrecisionPresent) {
+    if (CombinedSFMask.UseNativeLowPrecision)
+      CombinedSFMask.NativeLowPrecision = true;
+    else
+      CombinedSFMask.MinimumPrecision = true;
+  }
+
   CombinedSFMask.UAVsAtEveryStage = hasUAVsAtEveryStage(DRM, MMDI);
 }
 
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/low-precision.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/low-precision.ll
index 561e09bb1e9dc..bccc14d2b38cb 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: ;
 ;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/use-native-low-precision-0.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/use-native-low-precision-0.ll
index c537a01482f39..e4d55d3d89013 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,6 +11,7 @@ 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
@@ -16,22 +19,29 @@ target triple = "dxil-pc-shadermodel6.7-library"
 ;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..6ee592de087a6 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,6 +11,7 @@ target triple = "dxil-pc-shadermodel6.7-library"
 ;CHECK-NEXT: ; Shader Flags Value: 0x00800020
 ;CHECK-NEXT: ;
 ;CHECK-NEXT: ; Note: shader requires additional functionality:
+;CHECK-NEXT: ;       Use native low precision
 ;CHECK-NEXT: ; Note: extra DXIL module flags:
 ;CHECK-NEXT: ;       Low-precision data types
 ;CHECK-NEXT: ;       Use native low precision
@@ -13,7 +19,7 @@ target triple = "dxil-pc-shadermodel6.7-library"
 ;CHECK-NEXT: ; Shader Flags for Module Functions
 
 ;CHECK-LABEL: ; Function add_i16 : 0x00800020
-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
 }
@@ -22,16 +28,23 @@ define i16 @add_i16(i16 %a, i16 %b) {
 ; 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) {
+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) {
+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: ...

>From aa824aca6fe81c2a3528edd41a8db932087aa667 Mon Sep 17 00:00:00 2001
From: Icohedron <cheung.deric at gmail.com>
Date: Tue, 13 May 2025 17:40:29 +0000
Subject: [PATCH 2/4] Refactor flags related to low precision data types and
 combine the NativeLowPrecision module and feature flags

---
 .../BinaryFormat/DXContainerConstants.def     |  3 +-
 llvm/lib/Target/DirectX/DXILShaderFlags.cpp   | 35 +++++++++----------
 llvm/lib/Target/DirectX/DXILShaderFlags.h     |  1 +
 .../ShaderFlags/use-native-low-precision-1.ll |  9 +++--
 4 files changed, 23 insertions(+), 25 deletions(-)

diff --git a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
index 1645018aebedb..ed259524570a1 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, 23, NativeLowPrecision, "Use native low precision")
 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")
@@ -117,7 +117,6 @@ 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( 8,  AllResourcesBound, "All resources bound for the duration of shader execution")
-DXIL_MODULE_FLAG(23,  UseNativeLowPrecision, "Use native low precision")
 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 36f909ffa6ef5..dd9cd8849525f 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 (NativeLowPrecisionAvailable)
+      CSF.NativeLowPrecision = true;
+    else
+      CSF.MinimumPrecision = true;
+  }
+
   if (!CSF.Int64Ops)
     CSF.Int64Ops = I.getType()->isIntegerTy(64);
 
@@ -206,14 +213,21 @@ 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.
+  // The command line option -res-may-alias will set the dx.resmayalias module
+  // flag to 1 and disable the ability to set the ResMayNotAlias flag
   if (auto *RMA = mdconst::extract_or_null<ConstantInt>(
           M.getModuleFlag("dx.resmayalias")))
     if (RMA->getValue() != 0)
       CanSetResMayNotAlias = false;
 
+  // Set UseNativeLowPrecision using the dx.nativelowprec module flag set by
+  // the command line option -enable-16bit-types
+  if (auto *NativeLowPrec = mdconst::extract_or_null<ConstantInt>(
+          M.getModuleFlag("dx.nativelowprec")))
+    if (MMDI.ShaderModelVersion >= VersionTuple(6, 2) &&
+        NativeLowPrec->getValue() != 0)
+      NativeLowPrecisionAvailable = true;
+
   CallGraph CG(M);
 
   // Compute Shader Flags Mask for all functions using post-order visit of SCC
@@ -243,13 +257,6 @@ void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM,
       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)
@@ -296,14 +303,6 @@ void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM,
   if (NumUAVs > 8)
     CombinedSFMask.Max64UAVs = true;
 
-  // Set the Shader Feature Info flags related to low-precision datatypes
-  if (CombinedSFMask.LowPrecisionPresent) {
-    if (CombinedSFMask.UseNativeLowPrecision)
-      CombinedSFMask.NativeLowPrecision = true;
-    else
-      CombinedSFMask.MinimumPrecision = true;
-  }
-
   CombinedSFMask.UAVsAtEveryStage = hasUAVsAtEveryStage(DRM, MMDI);
 }
 
diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.h b/llvm/lib/Target/DirectX/DXILShaderFlags.h
index 0e0bd0036349e..5fa5cf48c16f8 100644
--- a/llvm/lib/Target/DirectX/DXILShaderFlags.h
+++ b/llvm/lib/Target/DirectX/DXILShaderFlags.h
@@ -92,6 +92,7 @@ struct ModuleShaderFlags {
 
 private:
   bool CanSetResMayNotAlias;
+  bool NativeLowPrecisionAvailable;
   /// 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/use-native-low-precision-1.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/use-native-low-precision-1.ll
index 6ee592de087a6..5cc15be48f4a9 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
@@ -14,7 +14,6 @@ target triple = "dxil-pc-shadermodel6.7-library"
 ;CHECK-NEXT: ;       Use native low precision
 ;CHECK-NEXT: ; Note: extra DXIL module flags:
 ;CHECK-NEXT: ;       Low-precision data types
-;CHECK-NEXT: ;       Use native low precision
 ;CHECK-NEXT: ;
 ;CHECK-NEXT: ; Shader Flags for Module Functions
 
@@ -24,10 +23,10 @@ define i16 @add_i16(i16 %a, i16 %b) "hlsl.export" {
   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
+; NOTE: In DXC, 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). However, this will not be the case for Clang
+;CHECK-LABEL: ; Function add_i32 : 0x00000000
 define i32 @add_i32(i32 %a, i32 %b) "hlsl.export" {
   %sum = add i32 %a, %b
   ret i32 %sum

>From 4cb533b474a7e6f7dc5fd207561a6e2cfb3b4b64 Mon Sep 17 00:00:00 2001
From: Icohedron <cheung.deric at gmail.com>
Date: Tue, 13 May 2025 17:51:22 +0000
Subject: [PATCH 3/4] Fix comment about the -enable-16bit-types flag

---
 llvm/lib/Target/DirectX/DXILShaderFlags.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
index dd9cd8849525f..11f3a1e4a8c18 100644
--- a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
+++ b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
@@ -220,8 +220,9 @@ void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM,
     if (RMA->getValue() != 0)
       CanSetResMayNotAlias = false;
 
-  // Set UseNativeLowPrecision using the dx.nativelowprec module flag set by
-  // the command line option -enable-16bit-types
+  // NativeLowPrecision 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
   if (auto *NativeLowPrec = mdconst::extract_or_null<ConstantInt>(
           M.getModuleFlag("dx.nativelowprec")))
     if (MMDI.ShaderModelVersion >= VersionTuple(6, 2) &&

>From 610f4357502b9edb29ea69ba37e80039374b3f30 Mon Sep 17 00:00:00 2001
From: Icohedron <cheung.deric at gmail.com>
Date: Tue, 13 May 2025 18:45:26 +0000
Subject: [PATCH 4/4] Set default value of NativeLowPrecisionAvailable to false

---
 llvm/lib/Target/DirectX/DXILShaderFlags.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
index 11f3a1e4a8c18..c359e3036b6cd 100644
--- a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
+++ b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
@@ -223,6 +223,7 @@ void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM,
   // NativeLowPrecision 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
+  NativeLowPrecisionAvailable = false;
   if (auto *NativeLowPrec = mdconst::extract_or_null<ConstantInt>(
           M.getModuleFlag("dx.nativelowprec")))
     if (MMDI.ShaderModelVersion >= VersionTuple(6, 2) &&



More information about the llvm-commits mailing list