[llvm-branch-commits] [clang] [llvm] [DirectX] Validate registers are bound to root signature (PR #146785)

Finn Plummer via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Jul 10 10:51:39 PDT 2025


================
@@ -0,0 +1,160 @@
+; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 
+
+; CHECK: error: register cbuffer (space=665, register=3) is not defined in Root Signature
+; CHECK: error: register srv (space=0, register=0) is not defined in Root Signature
+; CHECK: error: register uav (space=0, register=4294967295) is not defined in Root Signature
+
+;
+; Resource Bindings:
+;
+; Name                                 Type  Format         Dim      ID      HLSL Bind     Count
+; ------------------------------ ---------- ------- ----------- ------- -------------- ---------
+; In                                texture  struct         r/o      T0             t0         1
+; Out                                   UAV  struct         r/w      U0             u0         1
+; UAV3                                  UAV     f32         buf      U1             u1         1
+; UAV1                                  UAV     f32         buf      U2             u2         1
+; UAV                                   UAV     f32         buf      U3    u4294967295         1
+; CB                                cbuffer      NA          NA     CB0   cb3,space665         1
+;
+; ModuleID = '../clang/test/SemaHLSL/RootSignature-Validation-Fail.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.5-unknown-shadermodel6.5-compute"
+
+%__cblayout_CB = type <{ float }>
+%"StructuredBuffer<int32_t>" = type { i32 }
+%"RWStructuredBuffer<int32_t>" = type { i32 }
+%"RWBuffer<float>" = type { float }
+%CBuffer.CB = type { float }
+
+ at CB.cb = local_unnamed_addr global target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) poison
+ at CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1
+ at .str = private unnamed_addr constant [3 x i8] c"In\00", align 1
+ at .str.2 = private unnamed_addr constant [4 x i8] c"Out\00", align 1
+ at .str.4 = private unnamed_addr constant [4 x i8] c"UAV\00", align 1
+ at .str.6 = private unnamed_addr constant [5 x i8] c"UAV1\00", align 1
+ at .str.10 = private unnamed_addr constant [5 x i8] c"UAV3\00", align 1
+ at In = external constant %"StructuredBuffer<int32_t>"
+ at Out = external constant %"RWStructuredBuffer<int32_t>"
+ at UAV3 = external constant %"RWBuffer<float>"
+ at UAV1 = external constant %"RWBuffer<float>"
+ at UAV = external constant %"RWBuffer<float>"
+ at CB = external constant %CBuffer.CB
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
+declare target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(i32, i32, i32, i32, i1, ptr) #0
+
+; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none)
+define void @CSMain() local_unnamed_addr #1 {
+entry:
+  %CB.cb_h.i.i = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(i32 665, i32 3, i32 1, i32 0, i1 false, ptr nonnull @CB.str)
+  store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) %CB.cb_h.i.i, ptr @CB.cb, align 4
+  %0 = tail call target("dx.RawBuffer", i32, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @.str)
+  %1 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_1_0t(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @.str.2)
+  %2 = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 -1, i32 1, i32 0, i1 false, ptr nonnull @.str.4)
+  %3 = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 2, i32 1, i32 0, i1 false, ptr nonnull @.str.6)
+  %4 = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 1, i32 1, i32 0, i1 false, ptr @.str.10)
+  %5 = tail call i32 @llvm.dx.group.id(i32 0)
+  %6 = call { float, float, float, float } @llvm.dx.resource.load.cbufferrow.4.f32.f32.f32.f32.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) %CB.cb_h.i.i, i32 0)
+  %7 = extractvalue { float, float, float, float } %6, 0
+  %conv.i = uitofp i32 %5 to float
+  %add.i = fadd reassoc nnan ninf nsz arcp afn float %7, %conv.i
+  %8 = call { i32, i1 } @llvm.dx.resource.load.rawbuffer.i32.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0) %0, i32 0, i32 0)
+  %9 = extractvalue { i32, i1 } %8, 0
+  %conv1.i = sitofp i32 %9 to float
+  %add2.i = fadd reassoc nnan ninf nsz arcp afn float %add.i, %conv1.i
+  %10 = call { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0) %2, i32 0)
+  %11 = extractvalue { float, i1 } %10, 0
+  %add4.i = fadd reassoc nnan ninf nsz arcp afn float %add2.i, %11
+  %12 = call { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0) %3, i32 0)
+  %13 = extractvalue { float, i1 } %12, 0
+  %add6.i = fadd reassoc nnan ninf nsz arcp afn float %add4.i, %13
+  %14 = call { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0) %4, i32 0)
+  %15 = extractvalue { float, i1 } %14, 0
+  %add8.i = fadd reassoc nnan ninf nsz arcp afn float %add6.i, %15
+  %conv9.i = fptosi float %add8.i to i32
+  call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_i32_1_0t.i32(target("dx.RawBuffer", i32, 1, 0) %1, i32 0, i32 0, i32 %conv9.i)
+  ret void
+}
+
+; Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
+declare i32 @llvm.dx.group.id(i32) #2
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
+declare target("dx.RawBuffer", i32, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_0_0t(i32, i32, i32, i32, i1, ptr) #0
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
+declare target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_1_0t(i32, i32, i32, i32, i1, ptr) #0
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
+declare target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32, i32, i32, i32, i1, ptr) #0
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
+declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_1_0t(target("dx.RawBuffer", i32, 1, 0), i32) #0
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
+declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0), i32) #0
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
+declare ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0), i32) #0
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read)
+declare { i32, i1 } @llvm.dx.resource.load.rawbuffer.i32.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0), i32, i32) #3
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read)
+declare { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0), i32) #3
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(write)
+declare void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_i32_1_0t.i32(target("dx.RawBuffer", i32, 1, 0), i32, i32, i32) #4
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read)
+declare { float, float, float, float } @llvm.dx.resource.load.cbufferrow.4.f32.f32.f32.f32.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)), i32) #3
+
+; uselistorder directives
+uselistorder ptr @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t, { 2, 1, 0 }
+uselistorder ptr @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t, { 2, 1, 0 }
+
+attributes #0 = { mustprogress nocallback nofree nosync nounwind willreturn memory(none) }
+attributes #1 = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none) "approx-func-fp-math"="false" "frame-pointer"="all" "hlsl.numthreads"="8,8,1" "hlsl.shader"="compute" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+attributes #2 = { mustprogress nofree nosync nounwind willreturn memory(none) }
+attributes #3 = { nocallback nofree nosync nounwind willreturn memory(read) }
+attributes #4 = { nocallback nofree nosync nounwind willreturn memory(write) }
+
+!dx.rootsignatures = !{!0}
+!llvm.module.flags = !{!9, !10}
+!dx.valver = !{!11}
+!llvm.ident = !{!12}
+!dx.shaderModel = !{!13}
+!dx.version = !{!14}
+!dx.resources = !{!15}
+!dx.entryPoints = !{!27}
+
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2, !3, !5, !7}
+!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4}
+!3 = !{!"DescriptorTable", i32 1, !4}
+!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4}
+!5 = !{!"DescriptorTable", i32 0, !6}
+!6 = !{!"Sampler", i32 2, i32 0, i32 0, i32 -1, i32 0}
----------------
inbelic wrote:

For clarity, by related code I mean that we remove it from the test case, not the source code.

https://github.com/llvm/llvm-project/pull/146785


More information about the llvm-branch-commits mailing list