-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[DXIL] Remove incompatible metadata types when preparing DXIL. #136386
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
Conversation
@llvm/pr-subscribers-hlsl @llvm/pr-subscribers-backend-directx Author: Joshua Batista (bob80905) ChangesThis PR introduces a Metadata Node Kind whitelist. The purpose is to prevent newer Metadata Node Kinds to be used and inserted into the outputted DXIL module. The Github DXC validator doesn't support these newer Metadata Node Kinds, so we need to filter them out.
that loops up to and including the last metadata node kind that should be disallowed in the current context. I believe this code shows that there are no other metadata nodes to be allowed, setting aside the explicit list shown in The accompanying test would add the loop.llvm.mustprogress metadata node kind, but thanks to the whitelist, filters it out, and so the whitelist is proven to work. Full diff: https://github.com/llvm/llvm-project/pull/136386.diff 2 Files Affected:
diff --git a/clang/test/CodeGenHLSL/metadata-stripping.hlsl b/clang/test/CodeGenHLSL/metadata-stripping.hlsl
new file mode 100644
index 0000000000000..0178f5efe4c01
--- /dev/null
+++ b/clang/test/CodeGenHLSL/metadata-stripping.hlsl
@@ -0,0 +1,13 @@
+// RUN: %clang --driver-mode=dxc -T cs_6_0 -Fo x.dxil %s | FileCheck %s
+// CHECK-NOT: llvm.loop.mustprogress
+
+StructuredBuffer<uint4> X : register(t0);
+StructuredBuffer<float4> In : register(t1);
+RWStructuredBuffer<float4> Out : register(u0);
+
+[numthreads(1, 1, 1)]
+void main(uint3 dispatch_thread_id : SV_DispatchThreadID) {
+ for (uint I = 0; I < X[dispatch_thread_id].x; ++I) {
+ Out[dispatch_thread_id] = In[dispatch_thread_id];
+ }
+}
diff --git a/llvm/lib/Target/DirectX/DXILPrepare.cpp b/llvm/lib/Target/DirectX/DXILPrepare.cpp
index de97de209048b..c54a5ac5c1227 100644
--- a/llvm/lib/Target/DirectX/DXILPrepare.cpp
+++ b/llvm/lib/Target/DirectX/DXILPrepare.cpp
@@ -189,6 +189,26 @@ class DXILPrepareModule : public ModulePass {
for (auto &BB : F) {
IRBuilder<> Builder(&BB);
for (auto &I : make_early_inc_range(BB)) {
+
+ // TODO: Audit this list - is it enough? Too much?
+ static unsigned DXILCompatibleMDs[] = {
+ LLVMContext::MD_dbg,
+ LLVMContext::MD_tbaa,
+ LLVMContext::MD_prof,
+ LLVMContext::MD_fpmath,
+ LLVMContext::MD_range,
+ LLVMContext::MD_tbaa_struct,
+ LLVMContext::MD_invariant_load,
+ LLVMContext::MD_alias_scope,
+ LLVMContext::MD_noalias,
+ LLVMContext::MD_nontemporal,
+ LLVMContext::MD_mem_parallel_loop_access,
+ LLVMContext::MD_nonnull,
+ LLVMContext::MD_dereferenceable,
+ LLVMContext::MD_dereferenceable_or_null,
+ };
+ I.dropUnknownNonDebugMetadata(DXILCompatibleMDs);
+
if (I.getOpcode() == Instruction::FNeg) {
Builder.SetInsertPoint(&I);
Value *In = I.getOperand(0);
|
@llvm/pr-subscribers-clang Author: Joshua Batista (bob80905) ChangesThis PR introduces a Metadata Node Kind whitelist. The purpose is to prevent newer Metadata Node Kinds to be used and inserted into the outputted DXIL module. The Github DXC validator doesn't support these newer Metadata Node Kinds, so we need to filter them out.
that loops up to and including the last metadata node kind that should be disallowed in the current context. I believe this code shows that there are no other metadata nodes to be allowed, setting aside the explicit list shown in The accompanying test would add the loop.llvm.mustprogress metadata node kind, but thanks to the whitelist, filters it out, and so the whitelist is proven to work. Full diff: https://github.com/llvm/llvm-project/pull/136386.diff 2 Files Affected:
diff --git a/clang/test/CodeGenHLSL/metadata-stripping.hlsl b/clang/test/CodeGenHLSL/metadata-stripping.hlsl
new file mode 100644
index 0000000000000..0178f5efe4c01
--- /dev/null
+++ b/clang/test/CodeGenHLSL/metadata-stripping.hlsl
@@ -0,0 +1,13 @@
+// RUN: %clang --driver-mode=dxc -T cs_6_0 -Fo x.dxil %s | FileCheck %s
+// CHECK-NOT: llvm.loop.mustprogress
+
+StructuredBuffer<uint4> X : register(t0);
+StructuredBuffer<float4> In : register(t1);
+RWStructuredBuffer<float4> Out : register(u0);
+
+[numthreads(1, 1, 1)]
+void main(uint3 dispatch_thread_id : SV_DispatchThreadID) {
+ for (uint I = 0; I < X[dispatch_thread_id].x; ++I) {
+ Out[dispatch_thread_id] = In[dispatch_thread_id];
+ }
+}
diff --git a/llvm/lib/Target/DirectX/DXILPrepare.cpp b/llvm/lib/Target/DirectX/DXILPrepare.cpp
index de97de209048b..c54a5ac5c1227 100644
--- a/llvm/lib/Target/DirectX/DXILPrepare.cpp
+++ b/llvm/lib/Target/DirectX/DXILPrepare.cpp
@@ -189,6 +189,26 @@ class DXILPrepareModule : public ModulePass {
for (auto &BB : F) {
IRBuilder<> Builder(&BB);
for (auto &I : make_early_inc_range(BB)) {
+
+ // TODO: Audit this list - is it enough? Too much?
+ static unsigned DXILCompatibleMDs[] = {
+ LLVMContext::MD_dbg,
+ LLVMContext::MD_tbaa,
+ LLVMContext::MD_prof,
+ LLVMContext::MD_fpmath,
+ LLVMContext::MD_range,
+ LLVMContext::MD_tbaa_struct,
+ LLVMContext::MD_invariant_load,
+ LLVMContext::MD_alias_scope,
+ LLVMContext::MD_noalias,
+ LLVMContext::MD_nontemporal,
+ LLVMContext::MD_mem_parallel_loop_access,
+ LLVMContext::MD_nonnull,
+ LLVMContext::MD_dereferenceable,
+ LLVMContext::MD_dereferenceable_or_null,
+ };
+ I.dropUnknownNonDebugMetadata(DXILCompatibleMDs);
+
if (I.getOpcode() == Instruction::FNeg) {
Builder.SetInsertPoint(&I);
Value *In = I.getOperand(0);
|
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.
This looks pretty good, but the test needs to also cover the positive cases. We should show that dx.nonuniform and MD_range, for example, are not removed. This can probably be done in the same test file unless you think it's worthwhile to split it up.
Created a new issue to improve range metadata validation here: |
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.
Description / commit message needs to be updated to match how this ended up, but otherwise this is looking pretty good. A couple of minor comments inline.
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.
Looks good
@@ -189,6 +201,9 @@ class DXILPrepareModule : public ModulePass { | |||
for (auto &BB : F) { | |||
IRBuilder<> Builder(&BB); | |||
for (auto &I : make_early_inc_range(BB)) { | |||
|
|||
I.dropUnknownNonDebugMetadata(DXILCompatibleMDs); | |||
|
|||
if (I.getOpcode() == Instruction::FNeg) { |
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.
DXILPrepare has a bunch of overlap with the legalization pass. Seems like MetaData might not be able to move because legalization is a function level pass and this is a module level one, but at a minimum it seems like FNeg -> FSub should move.
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 agree. I think DXILPrepare should do things like translate attributes and metadata, insert no-op bitcasts to appease the bitcode writer, and that sort of thing. Replacing ops with their equivalents should squarely be a part of legalization, not here.
I've filed #137685
…136386) This PR introduces a Metadata Node Kind allowlist. The purpose is to prevent newer Metadata Node Kinds to be used and inserted into the outputted DXIL module. Only the metadata kinds that are accepted in the DXIL Validator are on the allowlist. The Github DXC validator doesn't support these newer Metadata Node Kinds, so we need to filter them out. We introduce this restrictive allowlist into LLVM and strip all metadata that isn't found in the list. The accompanying test would add the `llvm.loop.mustprogress` metadata node kind, but thanks to the allowlist, filters it out, and so the whitelist is proven to work. The test also has two separate metadata kinds that are on the allowlist, and remain after the DXIL Prepare pass.
…136386) This PR introduces a Metadata Node Kind allowlist. The purpose is to prevent newer Metadata Node Kinds to be used and inserted into the outputted DXIL module. Only the metadata kinds that are accepted in the DXIL Validator are on the allowlist. The Github DXC validator doesn't support these newer Metadata Node Kinds, so we need to filter them out. We introduce this restrictive allowlist into LLVM and strip all metadata that isn't found in the list. The accompanying test would add the `llvm.loop.mustprogress` metadata node kind, but thanks to the allowlist, filters it out, and so the whitelist is proven to work. The test also has two separate metadata kinds that are on the allowlist, and remain after the DXIL Prepare pass.
…136386) This PR introduces a Metadata Node Kind allowlist. The purpose is to prevent newer Metadata Node Kinds to be used and inserted into the outputted DXIL module. Only the metadata kinds that are accepted in the DXIL Validator are on the allowlist. The Github DXC validator doesn't support these newer Metadata Node Kinds, so we need to filter them out. We introduce this restrictive allowlist into LLVM and strip all metadata that isn't found in the list. The accompanying test would add the `llvm.loop.mustprogress` metadata node kind, but thanks to the allowlist, filters it out, and so the whitelist is proven to work. The test also has two separate metadata kinds that are on the allowlist, and remain after the DXIL Prepare pass.
…136386) This PR introduces a Metadata Node Kind allowlist. The purpose is to prevent newer Metadata Node Kinds to be used and inserted into the outputted DXIL module. Only the metadata kinds that are accepted in the DXIL Validator are on the allowlist. The Github DXC validator doesn't support these newer Metadata Node Kinds, so we need to filter them out. We introduce this restrictive allowlist into LLVM and strip all metadata that isn't found in the list. The accompanying test would add the `llvm.loop.mustprogress` metadata node kind, but thanks to the allowlist, filters it out, and so the whitelist is proven to work. The test also has two separate metadata kinds that are on the allowlist, and remain after the DXIL Prepare pass.
…136386) This PR introduces a Metadata Node Kind allowlist. The purpose is to prevent newer Metadata Node Kinds to be used and inserted into the outputted DXIL module. Only the metadata kinds that are accepted in the DXIL Validator are on the allowlist. The Github DXC validator doesn't support these newer Metadata Node Kinds, so we need to filter them out. We introduce this restrictive allowlist into LLVM and strip all metadata that isn't found in the list. The accompanying test would add the `llvm.loop.mustprogress` metadata node kind, but thanks to the allowlist, filters it out, and so the whitelist is proven to work. The test also has two separate metadata kinds that are on the allowlist, and remain after the DXIL Prepare pass.
This PR introduces a Metadata Node Kind allowlist. The purpose is to prevent newer Metadata Node Kinds to be used and inserted into the outputted DXIL module. Only the metadata kinds that are accepted in the DXIL Validator are on the allowlist. The Github DXC validator doesn't support these newer Metadata Node Kinds, so we need to filter them out.
We introduce this restrictive allowlist into LLVM and strip all metadata that isn't found in the list.
The accompanying test would add the
llvm.loop.mustprogress
metadata node kind, but thanks to the allowlist, filters it out, and so the whitelist is proven to work.The test also has two separate metadata kinds that are on the allowlist, and remain after the DXIL Prepare pass.