Skip to content

[DirectX] Set function-level flag Int64Ops in DXIL Shader Flags Analysis #129089

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Mar 18, 2025

Conversation

Icohedron
Copy link
Contributor

Fixes #114562

@llvmbot
Copy link
Member

llvmbot commented Feb 27, 2025

@llvm/pr-subscribers-backend-directx

Author: Deric Cheung (Icohedron)

Changes

Fixes #114562


Full diff: https://github.com/llvm/llvm-project/pull/129089.diff

4 Files Affected:

  • (modified) llvm/lib/Target/DirectX/DXILShaderFlags.cpp (+12)
  • (modified) llvm/test/CodeGen/DirectX/ShaderFlags/double-extensions.ll (+6-5)
  • (added) llvm/test/CodeGen/DirectX/ShaderFlags/int64ops.ll (+30)
  • (modified) llvm/test/CodeGen/DirectX/ShaderFlags/propagate-function-flags-test.ll (+6-5)
diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
index e1cf516758663..7740baa9b904d 100644
--- a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
+++ b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
@@ -99,6 +99,18 @@ void ModuleShaderFlags::updateFunctionFlags(ComputedShaderFlags &CSF,
     }
   }
 
+  if (!CSF.Int64Ops)
+    CSF.Int64Ops = I.getType()->isIntegerTy() && I.getType()->getScalarSizeInBits() == 64;
+
+  if (!CSF.Int64Ops) {
+    for (const Value *Op : I.operands()) {
+      if (Op->getType()->isIntegerTy() && Op->getType()->getScalarSizeInBits() == 64) {
+        CSF.Int64Ops = true;
+        break;
+      }
+    }
+  }
+
   if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
     switch (II->getIntrinsicID()) {
     default:
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/double-extensions.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/double-extensions.ll
index d6df67626be5a..dd8ea5f5b1aec 100644
--- a/llvm/test/CodeGen/DirectX/ShaderFlags/double-extensions.ll
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/double-extensions.ll
@@ -3,16 +3,17 @@
 target triple = "dxil-pc-shadermodel6.7-library"
 
 ; CHECK: ; Combined Shader Flags for Module
-; CHECK-NEXT: ; Shader Flags Value: 0x00000044
+; CHECK-NEXT: ; Shader Flags Value: 0x00100044
 
 ; CHECK: ; Note: shader requires additional functionality:
 ; CHECK-NEXT: ;       Double-precision floating point
 ; CHECK-NEXT: ;       Double-precision extensions for 11.1
+; CHECK-NEXT: ;       64-Bit integer
 ; CHECK-NEXT: ; Note: extra DXIL module flags:
 ; CHECK-NEXT: ;
 ; CHECK-NEXT: ; Shader Flags for Module Functions
 
-;CHECK: ; Function top_level : 0x00000044
+;CHECK: ; Function top_level : 0x00100044
 define double @top_level() #0 {
   %r = call double @test_uitofp_i64(i64 5)
   ret double %r
@@ -25,13 +26,13 @@ define double @test_fdiv_double(double %a, double %b) #0 {
   ret double %res
 }
 
-; CHECK: ; Function test_uitofp_i64 : 0x00000044
+; CHECK: ; Function test_uitofp_i64 : 0x00100044
 define double @test_uitofp_i64(i64 %a) #0 {
   %r = uitofp i64 %a to double
   ret double %r
 }
 
-; CHECK: ; Function test_sitofp_i64 : 0x00000044
+; CHECK: ; Function test_sitofp_i64 : 0x00100044
 define double @test_sitofp_i64(i64 %a) #0 {
   %r = sitofp i64 %a to double
   ret double %r
@@ -43,7 +44,7 @@ define i32 @test_fptoui_i32(double %a) #0 {
   ret i32 %r
 }
 
-; CHECK: ; Function test_fptosi_i64 : 0x00000044
+; CHECK: ; Function test_fptosi_i64 : 0x00100044
 define i64 @test_fptosi_i64(double %a) #0 {
   %r = fptosi double %a to i64
   ret i64 %r
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/int64ops.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/int64ops.ll
new file mode 100644
index 0000000000000..320c775e7130e
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/int64ops.ll
@@ -0,0 +1,30 @@
+; 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
+
+target triple = "dxil-pc-shadermodel6.7-library"
+
+;CHECK: ; Combined Shader Flags for Module
+;CHECK-NEXT: ; Shader Flags Value: 0x00100000
+;CHECK-NEXT: ;
+;CHECK-NEXT: ; Note: shader requires additional functionality:
+;CHECK-NEXT: ;       64-Bit integer
+;CHECK-NEXT: ; Note: extra DXIL module flags:
+;CHECK-NEXT: ;
+;CHECK-NEXT: ; Shader Flags for Module Functions
+;CHECK-NEXT: ; Function add : 0x00100000
+
+define i64 @add(i64 %a, i64 %b) #0 {
+  %sum = add i64 %a, %b
+  ret i64 %sum
+}
+
+attributes #0 = { convergent norecurse nounwind "hlsl.export"}
+
+; DXC: - Name:            SFI0
+; DXC-NEXT:     Size:            8
+; DXC-NEXT:     Flags:
+; DXC-NOT:   {{[A-Za-z]+: +true}}
+; DXC:            Int64Ops:        true
+; DXC-NOT:   {{[A-Za-z]+: +true}}
+; DXC:       NextUnusedBit:   false
+; DXC: ...
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/propagate-function-flags-test.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/propagate-function-flags-test.ll
index e7a2cf4d5b20f..8dee842e85e44 100644
--- a/llvm/test/CodeGen/DirectX/ShaderFlags/propagate-function-flags-test.ll
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/propagate-function-flags-test.ll
@@ -3,11 +3,12 @@
 target triple = "dxil-pc-shadermodel6.7-library"
 
 ; CHECK: ; Combined Shader Flags for Module
-; CHECK-NEXT: ; Shader Flags Value: 0x00000044
+; CHECK-NEXT: ; Shader Flags Value: 0x00100044
 ; CHECK-NEXT: ;
 ; CHECK-NEXT: ; Note: shader requires additional functionality:
 ; CHECK-NEXT: ;       Double-precision floating point
 ; CHECK-NEXT: ;       Double-precision extensions for 11.1
+; CHECK-NEXT: ;       64-Bit integer
 ; CHECK-NEXT: ; Note: extra DXIL module flags:
 ; CHECK-NEXT: ;
 ; CHECK-NEXT: ; Shader Flags for Module Functions
@@ -55,13 +56,13 @@ define double @call_get_uitofp_flag(i32 noundef %0) local_unnamed_addr #0 {
   ret double %2
 }
 
-; CHECK: ; Function call_get_fptoui_flag : 0x00000044
+; CHECK: ; Function call_get_fptoui_flag : 0x00100044
 define double @call_get_fptoui_flag(double noundef %0) local_unnamed_addr #0 {
   %2 = tail call double @get_fptoui_flag(double noundef %0)
   ret double %2
 }
 
-; CHECK: ; Function get_fptoui_flag : 0x00000044
+; CHECK: ; Function get_fptoui_flag : 0x00100044
 define double @get_fptoui_flag(double noundef %0) local_unnamed_addr #0 {
   %2 = fcmp ugt double %0, 5.000000e+00
   br i1 %2, label %6, label %3
@@ -81,7 +82,7 @@ define double @get_fptoui_flag(double noundef %0) local_unnamed_addr #0 {
   ret double %10
 }
 
-; CHECK: ; Function get_sitofp_uitofp_flag : 0x00000044
+; CHECK: ; Function get_sitofp_uitofp_flag : 0x00100044
 define double @get_sitofp_uitofp_flag(i64 noundef %0) local_unnamed_addr #0 {
   %2 = icmp ult i64 %0, 6
   br i1 %2, label %3, label %7
@@ -154,7 +155,7 @@ define double @get_all_doubles_flags(i32 noundef %0) local_unnamed_addr #0 {
   ret double %4
 }
 
-; CHECK: ; Function main : 0x00000044
+; CHECK: ; Function main : 0x00100044
 define i32 @main() local_unnamed_addr #0 {
   %1 = tail call double @get_fptoui_flag(double noundef 1.000000e+00)
   %2 = tail call double @get_sitofp_fdiv_flag(i32 noundef 4)

@Icohedron Icohedron requested a review from bharadwajy February 27, 2025 17:54
Copy link
Contributor

@spall spall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code LGTM but once again don't understand the tests enough to comment on if they're sufficient.

@Icohedron
Copy link
Contributor Author

I am currently attempting to fix an issue in clang-dxc related to the implementation of this shader flag analysis that causes shader validation (dxv) to fail.

Take the following test called simple.hlsl:

RWBuffer<float4> In : register(u0, space0);
RWBuffer<float4> Out : register(u1, space4);

[numthreads(1,1,1)]
void main(uint GI : SV_GroupIndex) {
  Out[GI] = In[GI] * In[GI];
}

You can see that this test does not explicitly use any 64-bit integers.
Running the shell command: clang-dxc -T cs_6_0 simple.hlsl -Xclang -emit-llvm | opt -S -passes="print- dx-shader-flags" confirms that the Int64Ops shader flag is not set:

; Combined Shader Flags for Module
; Shader Flags Value: 0x00000000
;
; Shader Flags for Module Functions
; Function main : 0x00000000
;
; ModuleID = '<stdin>'
...

However, compiling the shader directly to dxil using clang-dxc will fail dxv validation due to mismatched DXIL module flags.

> clang-dxc -T cs_6_0 -Fo simple.dxil simple.hlsl
error: Flags must match usage.
note: Flags declared=1056768, actual=8192
Validation failed.

clang-dxc: error: dxv command failed with exit code 1 (use -v to see invocation)

For reference: 1056768 is 0x00102000, and 8192 is 0x00002000.
0x00100000 corresponds to the Int64Ops DXIL module flag
0x00002000 corresponds to the TypedUAVLoadAdditionalFormats DXIL module flag

@Icohedron
Copy link
Contributor Author

Icohedron commented Mar 4, 2025

For now, I pushed a change that makes the Int64Ops shader flags analysis ignore constant i64 indices of ExtractElement and InsertElement instructions that contain a value under UINT32_MAX. The produced DXIL should now pass validation by dxv, but I will not merge this PR until #129757 has been addressed.

@Icohedron Icohedron merged commit 1a95215 into llvm:main Mar 18, 2025
10 of 12 checks passed
@damyanp damyanp moved this to Closed in HLSL Support Apr 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Closed
Development

Successfully merging this pull request may close these issues.

[DirectX] Implement Shader Flags Analysis for Int64Ops
4 participants