[clang] [llvm] [DXIL] Remove incompatible metadata types when preparing DXIL. (PR #136386)
Joshua Batista via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 28 10:46:24 PDT 2025
https://github.com/bob80905 updated https://github.com/llvm/llvm-project/pull/136386
>From c1a89d6896edd29ff345dd8fdc30cd040f3760f3 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Fri, 18 Apr 2025 16:06:18 -0700
Subject: [PATCH 1/8] add md node type filter, and test
---
.../test/CodeGenHLSL/metadata-stripping.hlsl | 13 ++++++++++++
llvm/lib/Target/DirectX/DXILPrepare.cpp | 20 +++++++++++++++++++
2 files changed, 33 insertions(+)
create mode 100644 clang/test/CodeGenHLSL/metadata-stripping.hlsl
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);
>From 0399c6fdf33a1314a70089cdaf1529f2ab641b5a Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Wed, 23 Apr 2025 21:37:40 -0700
Subject: [PATCH 2/8] add dxil prepare pass
---
.../CodeGen/DirectX/metadata-stripping.ll | 109 ++++++++++++++++++
1 file changed, 109 insertions(+)
create mode 100644 llvm/test/CodeGen/DirectX/metadata-stripping.ll
diff --git a/llvm/test/CodeGen/DirectX/metadata-stripping.ll b/llvm/test/CodeGen/DirectX/metadata-stripping.ll
new file mode 100644
index 0000000000000..92cc500d5cab7
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/metadata-stripping.ll
@@ -0,0 +1,109 @@
+; RUN: opt -S --dxil-prepare %s | FileCheck %s
+
+source_filename = "C:\\Users\\jbatista\\Desktop\\particle_life.hlsl"
+target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxilv1.0-unknown-shadermodel6.0-compute"
+
+%StructuredBuffer = type { <4 x i32> }
+%StructuredBuffer.1 = type { <4 x float> }
+%RWStructuredBuffer = type { <4 x float> }
+%dx.types.Handle = type { ptr }
+%dx.types.ResRet.i32 = type { i32, i32, i32, i32, i32 }
+%dx.types.ResRet.f32 = type { float, float, float, float, i32 }
+
+ at 0 = external constant %StructuredBuffer
+ at 1 = external constant %StructuredBuffer.1
+ at 2 = external constant %RWStructuredBuffer
+
+; Function Attrs: noinline nounwind memory(readwrite, inaccessiblemem: none)
+define void @main() local_unnamed_addr #0 {
+entry:
+ %_ZL1X_h.i.i3 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 0, i1 false) #1
+ %0 = call i32 @dx.op.threadId.i32(i32 93, i32 0) #2
+ %1 = call %dx.types.ResRet.i32 @dx.op.bufferLoad.i32(i32 68, %dx.types.Handle %_ZL1X_h.i.i3, i32 %0, i32 0) #1
+ %2 = extractvalue %dx.types.ResRet.i32 %1, 0
+ %cmp.i1.not = icmp eq i32 %2, 0
+ br i1 %cmp.i1.not, label %_Z4mainDv3_j.exit, label %for.body.i.lr.ph
+
+for.body.i.lr.ph: ; preds = %entry
+ %_ZL3Out_h.i.i5 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 0, i1 false) #1
+ %_ZL2In_h.i.i4 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 1, i32 1, i1 false) #1
+ %3 = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle %_ZL2In_h.i.i4, i32 %0, i32 0) #1
+ %4 = extractvalue %dx.types.ResRet.f32 %3, 0
+ %5 = extractvalue %dx.types.ResRet.f32 %3, 1
+ %6 = extractvalue %dx.types.ResRet.f32 %3, 2
+ %7 = extractvalue %dx.types.ResRet.f32 %3, 3
+ br label %for.body.i
+
+for.body.i: ; preds = %for.body.i.lr.ph, %for.body.i
+ %I.0.i2 = phi i32 [ 0, %for.body.i.lr.ph ], [ %inc.i, %for.body.i ]
+ call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %_ZL3Out_h.i.i5, i32 %0, i32 0, float %4, float %5, float %6, float %7, i8 15)
+ %inc.i = add nuw i32 %I.0.i2, 1
+ %8 = call %dx.types.ResRet.i32 @dx.op.bufferLoad.i32(i32 68, %dx.types.Handle %_ZL1X_h.i.i3, i32 %0, i32 0) #1
+ %9 = extractvalue %dx.types.ResRet.i32 %8, 0
+ ; CHECK: %cmp.i = icmp ult i32 %inc.i, %9
+ ; CHECK-NEXT: br i1 %cmp.i, label %for.body.i, label %_Z4mainDv3_j.exit
+ %cmp.i = icmp ult i32 %inc.i, %9
+ br i1 %cmp.i, label %for.body.i, label %_Z4mainDv3_j.exit, !llvm.loop !16
+
+_Z4mainDv3_j.exit: ; preds = %for.body.i, %entry
+ ret void
+
+; uselistorder directives
+ uselistorder %dx.types.Handle %_ZL1X_h.i.i3, { 1, 0 }
+ uselistorder i32 %0, { 3, 0, 1, 2 }
+ uselistorder label %for.body.i, { 1, 0 }
+ }
+
+declare %dx.types.Handle @dx.op.createHandle(i32, i8, i32, i32, i1)
+
+declare i32 @dx.op.threadId.i32(i32, i32)
+
+declare %dx.types.ResRet.i32 @dx.op.bufferLoad.i32(i32, %dx.types.Handle, i32, i32)
+
+declare %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32, %dx.types.Handle, i32, i32)
+
+declare void @dx.op.bufferStore.f32(i32, %dx.types.Handle, i32, i32, float, float, float, float, i8)
+
+; uselistorder directives
+uselistorder i32 57, { 1, 0, 2 }
+uselistorder i32 0, { 3, 0, 10, 1, 5, 6, 9, 2, 4, 7, 8 }
+uselistorder i1 false, { 1, 0, 2 }
+uselistorder i32 68, { 2, 0, 1 }
+uselistorder i32 1, { 2, 0, 1 }
+uselistorder ptr @dx.op.createHandle, { 2, 0, 1 }
+
+attributes #0 = { noinline nounwind memory(readwrite, inaccessiblemem: none) }
+attributes #1 = { memory(read) }
+attributes #2 = { memory(none) }
+
+!dx.valver = !{!0}
+!llvm.ident = !{!1}
+!dx.shaderModel = !{!2}
+!dx.version = !{!3}
+!dx.resources = !{!4}
+!dx.entryPoints = !{!11}
+!llvm.module.flags = !{!14, !15}
+
+!0 = !{i32 1, i32 8}
+!1 = !{!"clang version 21.0.0git (https://github.com/llvm/llvm-project.git 9ed4c705ac1c5c8797f328694f6cd22fbcdae03b)"}
+!2 = !{!"cs", i32 6, i32 0}
+!3 = !{i32 1, i32 0}
+!4 = !{!5, !9, null, null}
+!5 = !{!6, !8}
+!6 = !{i32 0, ptr @0, !"", i32 0, i32 0, i32 1, i32 12, i32 0, !7}
+!7 = !{i32 1, i32 16}
+!8 = !{i32 1, ptr @1, !"", i32 0, i32 1, i32 1, i32 12, i32 0, !7}
+!9 = !{!10}
+!10 = !{i32 0, ptr @2, !"", i32 0, i32 0, i32 1, i32 12, i1 false, i1 false, i1 false, !7}
+!11 = !{ptr @main, !"main", null, !4, !12}
+!12 = !{i32 0, i64 16, i32 4, !13}
+!13 = !{i32 1, i32 1, i32 1}
+!14 = !{i32 1, !"wchar_size", i32 4}
+; CHECK: !15 = !{i32 2, !"frame-pointer", i32 2}
+; this next line checks that nothing comes after the above check line.
+; No more metadata should be necessary after !15, the rest should be removed.
+; CHECK-NOT: .
+!15 = !{i32 2, !"frame-pointer", i32 2}
+!16 = distinct !{!16, !17}
+!17 = !{!"llvm.loop.mustprogress"}
>From 19de1553bf2f9b08f7d9d544c06cfb40423aaba7 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Wed, 23 Apr 2025 21:40:01 -0700
Subject: [PATCH 3/8] remove hlsl file
---
clang/test/CodeGenHLSL/metadata-stripping.hlsl | 13 -------------
1 file changed, 13 deletions(-)
delete mode 100644 clang/test/CodeGenHLSL/metadata-stripping.hlsl
diff --git a/clang/test/CodeGenHLSL/metadata-stripping.hlsl b/clang/test/CodeGenHLSL/metadata-stripping.hlsl
deleted file mode 100644
index 0178f5efe4c01..0000000000000
--- a/clang/test/CodeGenHLSL/metadata-stripping.hlsl
+++ /dev/null
@@ -1,13 +0,0 @@
-// 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];
- }
-}
>From 416084c9fbd09039b651e88106489cff6429438a Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Thu, 24 Apr 2025 17:44:29 -0700
Subject: [PATCH 4/8] drop tbaa and memparallelloopaccess, add 3 dx mds,
simplify test
---
llvm/lib/Target/DirectX/DXILPrepare.cpp | 41 +++++++++++--------
.../CodeGen/DirectX/metadata-stripping.ll | 41 +++----------------
2 files changed, 30 insertions(+), 52 deletions(-)
diff --git a/llvm/lib/Target/DirectX/DXILPrepare.cpp b/llvm/lib/Target/DirectX/DXILPrepare.cpp
index c54a5ac5c1227..492477ed26e10 100644
--- a/llvm/lib/Target/DirectX/DXILPrepare.cpp
+++ b/llvm/lib/Target/DirectX/DXILPrepare.cpp
@@ -161,6 +161,26 @@ class DXILPrepareModule : public ModulePass {
Builder.getPtrTy(PtrTy->getAddressSpace())));
}
+ static llvm::SmallVector<unsigned> getCompatibleInstructionMDs(Module &M) {
+ llvm::SmallVector<unsigned, 16> ret = {
+ M.getMDKindID("dx.nonuniform"),
+ M.getMDKindID("dx.controlflow.hints"),
+ M.getMDKindID("dx.precise"),
+ 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_nonnull,
+ LLVMContext::MD_dereferenceable,
+ LLVMContext::MD_dereferenceable_or_null};
+
+ return ret;
+ }
+
public:
bool runOnModule(Module &M) override {
PointerTypeMap PointerTypes = PointerTypeAnalysis::run(M);
@@ -176,6 +196,10 @@ class DXILPrepareModule : public ModulePass {
VersionTuple ValVer = MetadataInfo.ValidatorVersion;
bool SkipValidation = ValVer.getMajor() == 0 && ValVer.getMinor() == 0;
+ // construct whitelist of valid metadata node kinds
+ llvm::SmallVector<unsigned> DXILCompatibleMDs =
+ getCompatibleInstructionMDs(M);
+
for (auto &F : M.functions()) {
F.removeFnAttrs(AttrMask);
F.removeRetAttrs(AttrMask);
@@ -190,23 +214,6 @@ class DXILPrepareModule : public ModulePass {
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) {
diff --git a/llvm/test/CodeGen/DirectX/metadata-stripping.ll b/llvm/test/CodeGen/DirectX/metadata-stripping.ll
index 92cc500d5cab7..5a1881e694fb1 100644
--- a/llvm/test/CodeGen/DirectX/metadata-stripping.ll
+++ b/llvm/test/CodeGen/DirectX/metadata-stripping.ll
@@ -17,41 +17,18 @@ target triple = "dxilv1.0-unknown-shadermodel6.0-compute"
; Function Attrs: noinline nounwind memory(readwrite, inaccessiblemem: none)
define void @main() local_unnamed_addr #0 {
-entry:
- %_ZL1X_h.i.i3 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 0, i1 false) #1
- %0 = call i32 @dx.op.threadId.i32(i32 93, i32 0) #2
- %1 = call %dx.types.ResRet.i32 @dx.op.bufferLoad.i32(i32 68, %dx.types.Handle %_ZL1X_h.i.i3, i32 %0, i32 0) #1
- %2 = extractvalue %dx.types.ResRet.i32 %1, 0
- %cmp.i1.not = icmp eq i32 %2, 0
- br i1 %cmp.i1.not, label %_Z4mainDv3_j.exit, label %for.body.i.lr.ph
-
-for.body.i.lr.ph: ; preds = %entry
- %_ZL3Out_h.i.i5 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 0, i1 false) #1
- %_ZL2In_h.i.i4 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 1, i32 1, i1 false) #1
- %3 = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle %_ZL2In_h.i.i4, i32 %0, i32 0) #1
- %4 = extractvalue %dx.types.ResRet.f32 %3, 0
- %5 = extractvalue %dx.types.ResRet.f32 %3, 1
- %6 = extractvalue %dx.types.ResRet.f32 %3, 2
- %7 = extractvalue %dx.types.ResRet.f32 %3, 3
- br label %for.body.i
-
-for.body.i: ; preds = %for.body.i.lr.ph, %for.body.i
- %I.0.i2 = phi i32 [ 0, %for.body.i.lr.ph ], [ %inc.i, %for.body.i ]
- call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %_ZL3Out_h.i.i5, i32 %0, i32 0, float %4, float %5, float %6, float %7, i8 15)
- %inc.i = add nuw i32 %I.0.i2, 1
- %8 = call %dx.types.ResRet.i32 @dx.op.bufferLoad.i32(i32 68, %dx.types.Handle %_ZL1X_h.i.i3, i32 %0, i32 0) #1
- %9 = extractvalue %dx.types.ResRet.i32 %8, 0
- ; CHECK: %cmp.i = icmp ult i32 %inc.i, %9
- ; CHECK-NEXT: br i1 %cmp.i, label %for.body.i, label %_Z4mainDv3_j.exit
- %cmp.i = icmp ult i32 %inc.i, %9
+entry:
+ %cmp.i1.not = icmp eq i32 1, 0
+ br i1 %cmp.i1.not, label %_Z4mainDv3_j.exit, label %for.body.i
+
+for.body.i: ; preds = %entry
+ %cmp.i = icmp ult i32 1, 2
br i1 %cmp.i, label %for.body.i, label %_Z4mainDv3_j.exit, !llvm.loop !16
_Z4mainDv3_j.exit: ; preds = %for.body.i, %entry
ret void
; uselistorder directives
- uselistorder %dx.types.Handle %_ZL1X_h.i.i3, { 1, 0 }
- uselistorder i32 %0, { 3, 0, 1, 2 }
uselistorder label %for.body.i, { 1, 0 }
}
@@ -66,12 +43,6 @@ declare %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32, %dx.types.Handle, i32, i
declare void @dx.op.bufferStore.f32(i32, %dx.types.Handle, i32, i32, float, float, float, float, i8)
; uselistorder directives
-uselistorder i32 57, { 1, 0, 2 }
-uselistorder i32 0, { 3, 0, 10, 1, 5, 6, 9, 2, 4, 7, 8 }
-uselistorder i1 false, { 1, 0, 2 }
-uselistorder i32 68, { 2, 0, 1 }
-uselistorder i32 1, { 2, 0, 1 }
-uselistorder ptr @dx.op.createHandle, { 2, 0, 1 }
attributes #0 = { noinline nounwind memory(readwrite, inaccessiblemem: none) }
attributes #1 = { memory(read) }
>From 84ad1d4bd23d80c1add9eaffa8783c8c77d22d52 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Fri, 25 Apr 2025 12:36:19 -0700
Subject: [PATCH 5/8] prune whitelist
---
llvm/lib/Target/DirectX/DXILPrepare.cpp | 17 +++--------------
1 file changed, 3 insertions(+), 14 deletions(-)
diff --git a/llvm/lib/Target/DirectX/DXILPrepare.cpp b/llvm/lib/Target/DirectX/DXILPrepare.cpp
index 492477ed26e10..649a328fe77dd 100644
--- a/llvm/lib/Target/DirectX/DXILPrepare.cpp
+++ b/llvm/lib/Target/DirectX/DXILPrepare.cpp
@@ -163,20 +163,9 @@ class DXILPrepareModule : public ModulePass {
static llvm::SmallVector<unsigned> getCompatibleInstructionMDs(Module &M) {
llvm::SmallVector<unsigned, 16> ret = {
- M.getMDKindID("dx.nonuniform"),
- M.getMDKindID("dx.controlflow.hints"),
- M.getMDKindID("dx.precise"),
- 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_nonnull,
- LLVMContext::MD_dereferenceable,
- LLVMContext::MD_dereferenceable_or_null};
+ M.getMDKindID("dx.nonuniform"), M.getMDKindID("dx.controlflow.hints"),
+ M.getMDKindID("dx.precise"), LLVMContext::MD_range,
+ LLVMContext::MD_alias_scope, LLVMContext::MD_noalias};
return ret;
}
>From fb2932e70e2220dfb56f7e37fb400d8d5a96f035 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Fri, 25 Apr 2025 15:19:11 -0700
Subject: [PATCH 6/8] address Justin
---
llvm/lib/Target/DirectX/DXILPrepare.cpp | 17 ++--
.../CodeGen/DirectX/metadata-stripping.ll | 93 ++++++-------------
2 files changed, 34 insertions(+), 76 deletions(-)
diff --git a/llvm/lib/Target/DirectX/DXILPrepare.cpp b/llvm/lib/Target/DirectX/DXILPrepare.cpp
index 649a328fe77dd..27b797635817b 100644
--- a/llvm/lib/Target/DirectX/DXILPrepare.cpp
+++ b/llvm/lib/Target/DirectX/DXILPrepare.cpp
@@ -161,13 +161,13 @@ class DXILPrepareModule : public ModulePass {
Builder.getPtrTy(PtrTy->getAddressSpace())));
}
- static llvm::SmallVector<unsigned> getCompatibleInstructionMDs(Module &M) {
- llvm::SmallVector<unsigned, 16> ret = {
- M.getMDKindID("dx.nonuniform"), M.getMDKindID("dx.controlflow.hints"),
- M.getMDKindID("dx.precise"), LLVMContext::MD_range,
- LLVMContext::MD_alias_scope, LLVMContext::MD_noalias};
-
- return ret;
+ static std::array<unsigned, 6> getCompatibleInstructionMDs(llvm::Module &M) {
+ return {M.getMDKindID("dx.nonuniform"),
+ M.getMDKindID("dx.controlflow.hints"),
+ M.getMDKindID("dx.precise"),
+ llvm::LLVMContext::MD_range,
+ llvm::LLVMContext::MD_alias_scope,
+ llvm::LLVMContext::MD_noalias};
}
public:
@@ -186,8 +186,7 @@ class DXILPrepareModule : public ModulePass {
bool SkipValidation = ValVer.getMajor() == 0 && ValVer.getMinor() == 0;
// construct whitelist of valid metadata node kinds
- llvm::SmallVector<unsigned> DXILCompatibleMDs =
- getCompatibleInstructionMDs(M);
+ std::array<unsigned, 6> DXILCompatibleMDs = getCompatibleInstructionMDs(M);
for (auto &F : M.functions()) {
F.removeFnAttrs(AttrMask);
diff --git a/llvm/test/CodeGen/DirectX/metadata-stripping.ll b/llvm/test/CodeGen/DirectX/metadata-stripping.ll
index 5a1881e694fb1..199e7dbc2d09a 100644
--- a/llvm/test/CodeGen/DirectX/metadata-stripping.ll
+++ b/llvm/test/CodeGen/DirectX/metadata-stripping.ll
@@ -1,80 +1,39 @@
; RUN: opt -S --dxil-prepare %s | FileCheck %s
-source_filename = "C:\\Users\\jbatista\\Desktop\\particle_life.hlsl"
-target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
-target triple = "dxilv1.0-unknown-shadermodel6.0-compute"
-
-%StructuredBuffer = type { <4 x i32> }
-%StructuredBuffer.1 = type { <4 x float> }
-%RWStructuredBuffer = type { <4 x float> }
-%dx.types.Handle = type { ptr }
-%dx.types.ResRet.i32 = type { i32, i32, i32, i32, i32 }
-%dx.types.ResRet.f32 = type { float, float, float, float, i32 }
+; This test tests the whitelist inside of DxilPrepare.cpp.
+; It ensures that certain metadata nodes are removed that aren't
+; in the whitelist, and that certain nodes may remain that
+; are on the whitelist.
- at 0 = external constant %StructuredBuffer
- at 1 = external constant %StructuredBuffer.1
- at 2 = external constant %RWStructuredBuffer
+target triple = "dxilv1.0-unknown-shadermodel6.0-compute"
; Function Attrs: noinline nounwind memory(readwrite, inaccessiblemem: none)
-define void @main() local_unnamed_addr #0 {
+define void @main(i32* %ptr) {
entry:
- %cmp.i1.not = icmp eq i32 1, 0
+ ; metadata ID changes to 0 once the current !0 and !1 are removed
+ ; since they aren't in the whitelist. range needs a payload.
+ ; CHECK: %val = load i32, ptr %ptr, align 4, !range !0
+ %val = load i32, ptr %ptr, align 4, !range !2
+
+ ; dx.nonuniform is a valid metadata node kind on the whitelist,
+ ; so give it a bogus payload and ensure it sticks around
+ ; CHECK-next: %cmp.i1.not = icmp eq i32 1, 0, !dx.nonuniform !0
+ %cmp.i1.not = icmp eq i32 1, 0, !dx.nonuniform !2
br i1 %cmp.i1.not, label %_Z4mainDv3_j.exit, label %for.body.i
for.body.i: ; preds = %entry
%cmp.i = icmp ult i32 1, 2
- br i1 %cmp.i, label %for.body.i, label %_Z4mainDv3_j.exit, !llvm.loop !16
+ br i1 %cmp.i, label %for.body.i, label %_Z4mainDv3_j.exit, !llvm.loop !0
_Z4mainDv3_j.exit: ; preds = %for.body.i, %entry
ret void
-
-; uselistorder directives
- uselistorder label %for.body.i, { 1, 0 }
- }
-
-declare %dx.types.Handle @dx.op.createHandle(i32, i8, i32, i32, i1)
-
-declare i32 @dx.op.threadId.i32(i32, i32)
-
-declare %dx.types.ResRet.i32 @dx.op.bufferLoad.i32(i32, %dx.types.Handle, i32, i32)
-
-declare %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32, %dx.types.Handle, i32, i32)
-
-declare void @dx.op.bufferStore.f32(i32, %dx.types.Handle, i32, i32, float, float, float, float, i8)
-
-; uselistorder directives
-
-attributes #0 = { noinline nounwind memory(readwrite, inaccessiblemem: none) }
-attributes #1 = { memory(read) }
-attributes #2 = { memory(none) }
-
-!dx.valver = !{!0}
-!llvm.ident = !{!1}
-!dx.shaderModel = !{!2}
-!dx.version = !{!3}
-!dx.resources = !{!4}
-!dx.entryPoints = !{!11}
-!llvm.module.flags = !{!14, !15}
-
-!0 = !{i32 1, i32 8}
-!1 = !{!"clang version 21.0.0git (https://github.com/llvm/llvm-project.git 9ed4c705ac1c5c8797f328694f6cd22fbcdae03b)"}
-!2 = !{!"cs", i32 6, i32 0}
-!3 = !{i32 1, i32 0}
-!4 = !{!5, !9, null, null}
-!5 = !{!6, !8}
-!6 = !{i32 0, ptr @0, !"", i32 0, i32 0, i32 1, i32 12, i32 0, !7}
-!7 = !{i32 1, i32 16}
-!8 = !{i32 1, ptr @1, !"", i32 0, i32 1, i32 1, i32 12, i32 0, !7}
-!9 = !{!10}
-!10 = !{i32 0, ptr @2, !"", i32 0, i32 0, i32 1, i32 12, i1 false, i1 false, i1 false, !7}
-!11 = !{ptr @main, !"main", null, !4, !12}
-!12 = !{i32 0, i64 16, i32 4, !13}
-!13 = !{i32 1, i32 1, i32 1}
-!14 = !{i32 1, !"wchar_size", i32 4}
-; CHECK: !15 = !{i32 2, !"frame-pointer", i32 2}
-; this next line checks that nothing comes after the above check line.
-; No more metadata should be necessary after !15, the rest should be removed.
-; CHECK-NOT: .
-!15 = !{i32 2, !"frame-pointer", i32 2}
-!16 = distinct !{!16, !17}
-!17 = !{!"llvm.loop.mustprogress"}
+}
+
+; CHECK: !0 = !{i32 1, i32 5}
+; this next check line checks that nothing comes after the above check line.
+; No more metadata should be necessary, the rest (the current 0 and 1)
+; should be removed.
+; CHECK-NOT: !{!"llvm.loop.mustprogress"}
+!0 = distinct !{!0, !1}
+!1 = !{!"llvm.loop.mustprogress"}
+!2 = !{i32 1, i32 5}
>From b18f0936749aa144b299c36a5879c5513c90bc6d Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Mon, 28 Apr 2025 09:58:08 -0700
Subject: [PATCH 7/8] remove nonuniform test, patternmatch vars, simplify test
description
---
.../test/CodeGen/DirectX/metadata-stripping.ll | 18 ++++--------------
1 file changed, 4 insertions(+), 14 deletions(-)
diff --git a/llvm/test/CodeGen/DirectX/metadata-stripping.ll b/llvm/test/CodeGen/DirectX/metadata-stripping.ll
index 199e7dbc2d09a..a6c4c2eb5ddc0 100644
--- a/llvm/test/CodeGen/DirectX/metadata-stripping.ll
+++ b/llvm/test/CodeGen/DirectX/metadata-stripping.ll
@@ -1,9 +1,6 @@
; RUN: opt -S --dxil-prepare %s | FileCheck %s
-; This test tests the whitelist inside of DxilPrepare.cpp.
-; It ensures that certain metadata nodes are removed that aren't
-; in the whitelist, and that certain nodes may remain that
-; are on the whitelist.
+; Test that only metadata nodes that are valid in DXIL are allowed through
target triple = "dxilv1.0-unknown-shadermodel6.0-compute"
@@ -12,24 +9,17 @@ define void @main(i32* %ptr) {
entry:
; metadata ID changes to 0 once the current !0 and !1 are removed
; since they aren't in the whitelist. range needs a payload.
- ; CHECK: %val = load i32, ptr %ptr, align 4, !range !0
+ ; CHECK: %val = load i32, ptr %ptr, align 4, !range [[RANGEMD:![0-9]+]]
%val = load i32, ptr %ptr, align 4, !range !2
- ; dx.nonuniform is a valid metadata node kind on the whitelist,
- ; so give it a bogus payload and ensure it sticks around
- ; CHECK-next: %cmp.i1.not = icmp eq i32 1, 0, !dx.nonuniform !0
- %cmp.i1.not = icmp eq i32 1, 0, !dx.nonuniform !2
- br i1 %cmp.i1.not, label %_Z4mainDv3_j.exit, label %for.body.i
-
-for.body.i: ; preds = %entry
%cmp.i = icmp ult i32 1, 2
- br i1 %cmp.i, label %for.body.i, label %_Z4mainDv3_j.exit, !llvm.loop !0
+ br i1 %cmp.i, label %_Z4mainDv3_j.exit, label %_Z4mainDv3_j.exit, !llvm.loop !0
_Z4mainDv3_j.exit: ; preds = %for.body.i, %entry
ret void
}
-; CHECK: !0 = !{i32 1, i32 5}
+; CHECK: [[RANGEMD]] = !{i32 1, i32 5}
; this next check line checks that nothing comes after the above check line.
; No more metadata should be necessary, the rest (the current 0 and 1)
; should be removed.
>From 58683b60015d4c5e01b84514666eb2e0ddfab88b Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Mon, 28 Apr 2025 10:46:02 -0700
Subject: [PATCH 8/8] address Justin
---
llvm/lib/Target/DirectX/DXILPrepare.cpp | 2 +-
llvm/test/CodeGen/DirectX/metadata-stripping.ll | 9 ++++++---
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/DirectX/DXILPrepare.cpp b/llvm/lib/Target/DirectX/DXILPrepare.cpp
index 27b797635817b..e9a05a7b90aca 100644
--- a/llvm/lib/Target/DirectX/DXILPrepare.cpp
+++ b/llvm/lib/Target/DirectX/DXILPrepare.cpp
@@ -185,7 +185,7 @@ class DXILPrepareModule : public ModulePass {
VersionTuple ValVer = MetadataInfo.ValidatorVersion;
bool SkipValidation = ValVer.getMajor() == 0 && ValVer.getMinor() == 0;
- // construct whitelist of valid metadata node kinds
+ // construct allowlist of valid metadata node kinds
std::array<unsigned, 6> DXILCompatibleMDs = getCompatibleInstructionMDs(M);
for (auto &F : M.functions()) {
diff --git a/llvm/test/CodeGen/DirectX/metadata-stripping.ll b/llvm/test/CodeGen/DirectX/metadata-stripping.ll
index a6c4c2eb5ddc0..22e78eaeea2a4 100644
--- a/llvm/test/CodeGen/DirectX/metadata-stripping.ll
+++ b/llvm/test/CodeGen/DirectX/metadata-stripping.ll
@@ -8,22 +8,25 @@ target triple = "dxilv1.0-unknown-shadermodel6.0-compute"
define void @main(i32* %ptr) {
entry:
; metadata ID changes to 0 once the current !0 and !1 are removed
- ; since they aren't in the whitelist. range needs a payload.
+ ; since they aren't in the allowlist. range needs a payload.
; CHECK: %val = load i32, ptr %ptr, align 4, !range [[RANGEMD:![0-9]+]]
%val = load i32, ptr %ptr, align 4, !range !2
%cmp.i = icmp ult i32 1, 2
+ ; Ensure that the !llvm.loop metadata node gets dropped.
+ ; CHECK: br i1 %cmp.i, label %_Z4mainDv3_j.exit, label %_Z4mainDv3_j.exit{{$}}
br i1 %cmp.i, label %_Z4mainDv3_j.exit, label %_Z4mainDv3_j.exit, !llvm.loop !0
_Z4mainDv3_j.exit: ; preds = %for.body.i, %entry
ret void
}
-; CHECK: [[RANGEMD]] = !{i32 1, i32 5}
-; this next check line checks that nothing comes after the above check line.
+; These next check lines check that only the range metadata remains
; No more metadata should be necessary, the rest (the current 0 and 1)
; should be removed.
; CHECK-NOT: !{!"llvm.loop.mustprogress"}
+; CHECK: [[RANGEMD]] = !{i32 1, i32 5}
+; CHECK-NOT: !{!"llvm.loop.mustprogress"}
!0 = distinct !{!0, !1}
!1 = !{!"llvm.loop.mustprogress"}
!2 = !{i32 1, i32 5}
More information about the cfe-commits
mailing list