-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[DirectX] Implement UseNativeLowPrecision shader flag analysis #134288
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
[DirectX] Implement UseNativeLowPrecision shader flag analysis #134288
Conversation
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-codegen Author: Deric C. (Icohedron) ChangesFixes #112267 Full diff: https://github.com/llvm/llvm-project/pull/134288.diff 4 Files Affected:
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 3b1810b62a2cd..ca5f180d2a64c 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -282,10 +282,13 @@ void CGHLSLRuntime::addHLSLBufferLayoutType(const RecordType *StructType,
void CGHLSLRuntime::finishCodeGen() {
auto &TargetOpts = CGM.getTarget().getTargetOpts();
+ auto &LangOpts = CGM.getLangOpts();
llvm::Module &M = CGM.getModule();
Triple T(M.getTargetTriple());
if (T.getArch() == Triple::ArchType::dxil)
addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
+ if (LangOpts.NativeHalfType)
+ M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.nativelowprec", 1);
generateGlobalCtorDtorCalls();
}
diff --git a/clang/test/CodeGenHLSL/enable-16bit-types.hlsl b/clang/test/CodeGenHLSL/enable-16bit-types.hlsl
new file mode 100644
index 0000000000000..7da66a3ed863b
--- /dev/null
+++ b/clang/test/CodeGenHLSL/enable-16bit-types.hlsl
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fnative-half-type -finclude-default-header -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=FLAG
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=NOFLAG
+
+// NOTE: -enable-16bit-types is a DXCFlag that aliases -fnative-half-type
+
+// FLAG-DAG: ![[NLP:.*]] = !{i32 1, !"dx.nativelowprec", i32 1}
+// FLAG-DAG: !llvm.module.flags = !{{{.*}}![[NLP]]{{.*}}}
+
+// NOFLAG-NOT: dx.nativelowprec
diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
index babf495220393..437d1402ccedc 100644
--- a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
+++ b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
@@ -188,6 +188,12 @@ void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM,
continue;
}
+ // Set UseNativeLowPrecision using dx.nativelowprec module metadata
+ if (auto *NativeLowPrec = mdconst::extract_or_null<ConstantInt>(
+ M.getModuleFlag("dx.nativelowprec")))
+ if (NativeLowPrec->getValue() != 0)
+ SCCSF.UseNativeLowPrecision = true;
+
ComputedShaderFlags CSF;
for (const auto &BB : *F)
for (const auto &I : BB)
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/use-native-low-precision.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/use-native-low-precision.ll
new file mode 100644
index 0000000000000..95c916b169cdf
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/use-native-low-precision.ll
@@ -0,0 +1,45 @@
+; 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: 0x00800020
+;CHECK-NEXT: ;
+;CHECK-NEXT: ; Note: shader requires additional functionality:
+;CHECK-NEXT: ; Note: extra DXIL module flags:
+;CHECK-NEXT: ; D3D11_1_SB_GLOBAL_FLAG_ENABLE_MINIMUM_PRECISION
+;CHECK-NEXT: ; Native 16bit types enabled
+;CHECK-NEXT: ;
+;CHECK-NEXT: ; Shader Flags for Module Functions
+
+;CHECK-LABEL: ; Function add_i16 : 0x00800020
+define i16 @add_i16(i16 %a, i16 %b) #0 {
+ %sum = add i16 %a, %b
+ ret i16 %sum
+}
+
+; NOTE: The flag for native low precision is set for every function in the
+; module regardless of whether or not the function uses low precision data
+; types. This matches the behavior in DXC
+;CHECK-LABEL: ; Function add_i32 : 0x00800000
+define i32 @add_i32(i32 %a, i32 %b) #0 {
+ %sum = add i32 %a, %b
+ ret i32 %sum
+}
+
+;CHECK-LABEL: ; Function add_half : 0x00800020
+define half @add_half(half %a, half %b) #0 {
+ %sum = fadd half %a, %b
+ ret half %sum
+}
+
+attributes #0 = { convergent norecurse nounwind "hlsl.export" }
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"dx.nativelowprec", i32 1}
+
+; DXC: - Name: SFI0
+; DXC-NEXT: Size: 8
+; DXC-NOT: Flags:
+; DXC: ...
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assuming -fnative-half-type
can be directly used as an alias to enable-16bit-types
in DXC, this LGTM. Just some nits otherwise
llvm/test/CodeGen/DirectX/ShaderFlags/use-native-low-precision.ll
Outdated
Show resolved
Hide resolved
llvm/test/CodeGen/DirectX/ShaderFlags/use-native-low-precision.ll
Outdated
Show resolved
Hide resolved
@@ -0,0 +1,9 @@ | |||
// RUN: %clang_cc1 -fnative-half-type -finclude-default-header -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=FLAG |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: For future cleanup and test organization could we move the Shader Flag tests into their own directory like the Builtins have their own directory? Not asking for this PR.
// Set UseNativeLowPrecision using dx.nativelowprec module metadata | ||
if (auto *NativeLowPrec = mdconst::extract_or_null<ConstantInt>( | ||
M.getModuleFlag("dx.nativelowprec"))) | ||
if (MMDI.DXILVersion >= VersionTuple(1, 2) && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I know the frontend likely has checks to confirm SM 6.2 or greater for this flag. If the backend is dxil-pc-shadermodel6.1 what would happen in a test case like use-native-low-precision.ll
? Would we just expect to not see !0 = !{i32 1, !"dx.nativelowprec", i32 1}
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The frontend is what is adding !0 = !{i32 1, !"dx.nativelowprec", i32 1}
, so we wouldn't see it in the module.
If it is manually added to a module that is SM 6.1 or older, then it should have no effect on the shader flags.
Should I add a test for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My concern was if the validator would allow the dxil if it was less than sm 6.2 and we saw nativelowprec
set. The backend would be our last place to catch that and avoid the validator complaining.
If that isn't a concern then I don't think we need a test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the validator interprets any module metadata flag named "dx.nativelowpres", so it would just be ignored if it is present in the DXIL even when the SM is lower than 6.2.
Codgen looks right. The only changes I want to see are around testing. |
…134288) Fixes llvm#112267 Implement the shader flag analysis to set the UseNativeLowPrecision DXIL module flag. The flag is only able to be set when the command-line flag `-enable-16bit-types` is passed to clang-dxc, or equivalently `-fnative-half-type` is passed to clang. When the command-line flag is passed, a module metadata flag called "dx.nativelowprec" is set to 1. The DXILShaderFlags shader flags analysis checks that the module metadata flag "dx.nativelowprec" is set to 1 and the DXIL Version is 1.2 or greater before setting the UseNativeLowPrecision DXIL module flag.
…134288) Fixes llvm#112267 Implement the shader flag analysis to set the UseNativeLowPrecision DXIL module flag. The flag is only able to be set when the command-line flag `-enable-16bit-types` is passed to clang-dxc, or equivalently `-fnative-half-type` is passed to clang. When the command-line flag is passed, a module metadata flag called "dx.nativelowprec" is set to 1. The DXILShaderFlags shader flags analysis checks that the module metadata flag "dx.nativelowprec" is set to 1 and the DXIL Version is 1.2 or greater before setting the UseNativeLowPrecision DXIL module flag.
Fixes #112267
Implement the shader flag analysis to set the UseNativeLowPrecision DXIL module flag.
The flag is only able to be set when the command-line flag
-enable-16bit-types
is passed to clang-dxc, or equivalently-fnative-half-type
is passed to clang.When the command-line flag is passed, a module metadata flag called "dx.nativelowprec" is set to 1.
The DXILShaderFlags shader flags analysis checks that the module metadata flag "dx.nativelowprec" is set to 1 and the DXIL Version is 1.2 or greater before setting the UseNativeLowPrecision DXIL module flag.