Author: Helena Kotas Date: 2026-06-08T19:05:26-07:00 New Revision: 7ed2f70f6c5b3849017f0eb38c521cc5d42040a2
URL: https://github.com/llvm/llvm-project/commit/7ed2f70f6c5b3849017f0eb38c521cc5d42040a2 DIFF: https://github.com/llvm/llvm-project/commit/7ed2f70f6c5b3849017f0eb38c521cc5d42040a2.diff LOG: [HLSL] Set visibility of cbuffer global variables to internal (#200312) Global variables for all resources except `cbuffer` are already emitted with internal linkage (since #166844). This change adds internal linkage to the `cbuffer` handle globals as well. One problem is that the `cbuffer` handle globals appears unused between Clang CodeGen and `{DXIL|SPIRV}CBufferAccess` pass, which replaces individual `cbuffer` constant globals with accesses through the `cbuffer` handle globals. Before this pass runs, the unused globals could get optimized away in `GlobalOptPass` with `-O3`. To solve this, the `cbuffer` handle globals are added to the `@llvm.compiler.used` list to make sure they stay in the module until the `{DXIL|SPRIV}CBufferAccess` pass, which then removes them from the list. Added: llvm/test/CodeGen/DirectX/cbuffer_global_elim.ll llvm/test/CodeGen/SPIRV/cbuffer_global_elim.ll Modified: clang/lib/CodeGen/CGHLSLRuntime.cpp clang/test/CodeGenHLSL/ArrayAssignable.hlsl clang/test/CodeGenHLSL/ArrayAssignable.logicalptr.hlsl clang/test/CodeGenHLSL/cbuffer-matrix-layout-keyword.hlsl clang/test/CodeGenHLSL/resources/cbuffer-empty-struct-array.hlsl clang/test/CodeGenHLSL/resources/cbuffer.hlsl clang/test/CodeGenHLSL/resources/cbuffer_and_namespaces.hlsl clang/test/CodeGenHLSL/resources/cbuffer_with_packoffset.hlsl clang/test/CodeGenHLSL/resources/cbuffer_with_static_global_and_function.hlsl clang/test/CodeGenHLSL/resources/default_cbuffer.hlsl clang/test/CodeGenHLSL/resources/default_cbuffer_with_layout.hlsl llvm/include/llvm/Frontend/HLSL/CBuffer.h llvm/lib/Frontend/HLSL/CBuffer.cpp llvm/lib/Target/DirectX/DXILCBufferAccess.cpp llvm/lib/Target/SPIRV/SPIRVCBufferAccess.cpp Removed: ################################################################################ diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index 33d76cbda494a..262a2d8dabf5d 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -45,6 +45,7 @@ #include "llvm/Support/Alignment.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormatVariadic.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" #include <cstdint> #include <optional> @@ -531,11 +532,18 @@ void CGHLSLRuntime::addBuffer(const HLSLBufferDecl *BufDecl) { llvm::Type *LayoutTy = convertHLSLSpecificType(ResHandleTy, OffsetInfo); llvm::GlobalVariable *BufGV = new GlobalVariable( LayoutTy, /*isConstant*/ false, - GlobalValue::LinkageTypes::ExternalLinkage, PoisonValue::get(LayoutTy), + GlobalValue::LinkageTypes::InternalLinkage, PoisonValue::get(LayoutTy), llvm::formatv("{0}{1}", BufDecl->getName(), BufDecl->isCBuffer() ? ".cb" : ".tb"), GlobalValue::NotThreadLocal); - CGM.getModule().insertGlobalVariable(BufGV); + + llvm::Module &M = CGM.getModule(); + M.insertGlobalVariable(BufGV); + + // Add the global variable to the compiler used list so it does not + // get optimized away by GlobalOptPass before it reaches + // {DXIL|SPIRV}CBufferAccess pass. + llvm::appendToCompilerUsed(M, {BufGV}); // Add globals for constant buffer elements and create metadata nodes emitBufferGlobalsAndMetadata(BufDecl, BufGV, OffsetInfo); diff --git a/clang/test/CodeGenHLSL/ArrayAssignable.hlsl b/clang/test/CodeGenHLSL/ArrayAssignable.hlsl index 36d44b26d81bb..2ff42120a3d18 100644 --- a/clang/test/CodeGenHLSL/ArrayAssignable.hlsl +++ b/clang/test/CodeGenHLSL/ArrayAssignable.hlsl @@ -7,7 +7,7 @@ struct S { // CHECK: [[CBLayout:%.*]] = type <{ <{ [1 x <{ float, target("dx.Padding", 12) }>], float }>, target("dx.Padding", 12), [2 x <4 x i32>], <{ [1 x <{ <{ [1 x <{ i32, target("dx.Padding", 12) }>], i32 }>, target("dx.Padding", 12) }>], <{ [1 x <{ i32, target("dx.Padding", 12) }>], i32 }> }>, target("dx.Padding", 12), <{ [1 x <{ %S, target("dx.Padding", 8) }>], %S }> }> -// CHECK: @CBArrays.cb = global target("dx.CBuffer", [[CBLayout]]) +// CHECK: @CBArrays.cb = internal global target("dx.CBuffer", [[CBLayout]]) // CHECK: @c1 = external hidden addrspace(2) global <{ [1 x <{ float, target("dx.Padding", 12) }>], float }>, align 4 // CHECK: @c2 = external hidden addrspace(2) global [2 x <4 x i32>], align 4 // CHECK: @c3 = external hidden addrspace(2) global <{ [1 x <{ <{ [1 x <{ i32, target("dx.Padding", 12) }>], i32 }>, target("dx.Padding", 12) }>], <{ [1 x <{ i32, target("dx.Padding", 12) }>], i32 }> }>, align 4 diff --git a/clang/test/CodeGenHLSL/ArrayAssignable.logicalptr.hlsl b/clang/test/CodeGenHLSL/ArrayAssignable.logicalptr.hlsl index e5fa7e62f739d..cda023b16f891 100644 --- a/clang/test/CodeGenHLSL/ArrayAssignable.logicalptr.hlsl +++ b/clang/test/CodeGenHLSL/ArrayAssignable.logicalptr.hlsl @@ -15,14 +15,14 @@ cbuffer CBArrays : register(b0) { } // CHECK-DXIL: [[CBLayout:%.*]] = type <{ <{ [1 x <{ float, target("dx.Padding", 12) }>], float }>, target("dx.Padding", 12), [2 x <4 x i32>], <{ [1 x <{ <{ [1 x <{ i32, target("dx.Padding", 12) }>], i32 }>, target("dx.Padding", 12) }>], <{ [1 x <{ i32, target("dx.Padding", 12) }>], i32 }> }>, target("dx.Padding", 12), <{ [1 x <{ %S, target("dx.Padding", 8) }>], %S }> }> -// CHECK-DXIL: @CBArrays.cb = global target("dx.CBuffer", [[CBLayout]]) +// CHECK-DXIL: @CBArrays.cb = internal global target("dx.CBuffer", [[CBLayout]]) // CHECK-DXIL: @c1 = external hidden addrspace(2) global <{ [1 x <{ float, target("dx.Padding", 12) }>], float }>, align 4 // CHECK-DXIL: @c2 = external hidden addrspace(2) global [2 x <4 x i32>], align 4 // CHECK-DXIL: @c3 = external hidden addrspace(2) global <{ [1 x <{ <{ [1 x <{ i32, target("dx.Padding", 12) }>], i32 }>, target("dx.Padding", 12) }>], <{ [1 x <{ i32, target("dx.Padding", 12) }>], i32 }> }>, align 4 // CHECK-DXIL: @c4 = external hidden addrspace(2) global <{ [1 x <{ %S, target("dx.Padding", 8) }>], %S }>, align 1 // CHECK-SPIR: [[CBLayout:%.*]] = type <{ <{ [1 x <{ float, target("spirv.Padding", 12) }>], float }>, target("spirv.Padding", 12), [2 x <4 x i32>], <{ [1 x <{ <{ [1 x <{ i32, target("spirv.Padding", 12) }>], i32 }>, target("spirv.Padding", 12) }>], <{ [1 x <{ i32, target("spirv.Padding", 12) }>], i32 }> }>, target("spirv.Padding", 12), <{ [1 x <{ %S, target("spirv.Padding", 8) }>], %S }> }> -// CHECK-SPIR: @CBArrays.cb = global target("spirv.VulkanBuffer", %__cblayout_CBArrays, 2, 0) poison +// CHECK-SPIR: @CBArrays.cb = internal global target("spirv.VulkanBuffer", %__cblayout_CBArrays, 2, 0) poison // CHECK-SPIR: @c1 = external hidden addrspace(12) global <{ [1 x <{ float, target("spirv.Padding", 12) }>], float }>, align 4 // CHECK-SPIR: @c2 = external hidden addrspace(12) global [2 x <4 x i32>], align 4 // CHECK-SPIR: @c3 = external hidden addrspace(12) global <{ [1 x <{ <{ [1 x <{ i32, target("spirv.Padding", 12) }>], i32 }>, target("spirv.Padding", 12) }>], <{ [1 x <{ i32, target("spirv.Padding", 12) }>], i32 }> }>, align 4 diff --git a/clang/test/CodeGenHLSL/cbuffer-matrix-layout-keyword.hlsl b/clang/test/CodeGenHLSL/cbuffer-matrix-layout-keyword.hlsl index 66f64b2bbe967..8027df5d8c27b 100644 --- a/clang/test/CodeGenHLSL/cbuffer-matrix-layout-keyword.hlsl +++ b/clang/test/CodeGenHLSL/cbuffer-matrix-layout-keyword.hlsl @@ -9,9 +9,9 @@ // { [2 x { <2 x float>, pad(8) }], <2 x float> } // CHECK: %__cblayout_CB_CM = type <{ <{ [2 x <{ <2 x float>, target("dx.Padding", 8) }>], <2 x float> }> }> -// CHECK: @CB_RM.cb = global target("dx.CBuffer", %__cblayout_CB_RM) +// CHECK: @CB_RM.cb = internal global target("dx.CBuffer", %__cblayout_CB_RM) // CHECK: @rm = external hidden addrspace(2) global <{ [1 x <{ <3 x float>, target("dx.Padding", 4) }>], <3 x float> }>, align 4 -// CHECK: @CB_CM.cb = global target("dx.CBuffer", %__cblayout_CB_CM) +// CHECK: @CB_CM.cb = internal global target("dx.CBuffer", %__cblayout_CB_CM) // CHECK: @cm = external hidden addrspace(2) global <{ [2 x <{ <2 x float>, target("dx.Padding", 8) }>], <2 x float> }>, align 4 cbuffer CB_RM { diff --git a/clang/test/CodeGenHLSL/resources/cbuffer-empty-struct-array.hlsl b/clang/test/CodeGenHLSL/resources/cbuffer-empty-struct-array.hlsl index 72939cab07ac5..2184f8fe7cda6 100644 --- a/clang/test/CodeGenHLSL/resources/cbuffer-empty-struct-array.hlsl +++ b/clang/test/CodeGenHLSL/resources/cbuffer-empty-struct-array.hlsl @@ -42,19 +42,19 @@ int4x4 n; void main() { } -// CHECK-NOT: @CB.cb = global target("dx.CBuffer", %__cblayout_CB) +// CHECK-NOT: @CB.cb = internal global target("dx.CBuffer", %__cblayout_CB) // CHECK-NOT: @a = external hidden addrspace(2) global // CHECK-NOT: @b = external hidden addrspace(2) global // CHECK-NOT: @c = external hidden addrspace(2) global -// CHECK-NOT: @"$Globals.cb" = global target("dx.CBuffer", +// CHECK-NOT: @"$Globals.cb" = internal global target("dx.CBuffer", -// CHECK2: @CB.cb = global target("dx.CBuffer", %__cblayout_CB) +// CHECK2: @CB.cb = internal global target("dx.CBuffer", %__cblayout_CB) // CHECK-NOT: @a = external hidden addrspace(2) global // CHECK-NOT: @c = external hidden addrspace(2) global // CHECK2: @i = external hidden addrspace(2) global i32 // CHECK2: @v = external hidden addrspace(2) global <2 x float>, align 4 // CHECK2: @m = external hidden addrspace(2) global [4 x <4 x i32>], align 4 -// CHECK2: @"$Globals.cb" = global target("dx.CBuffer", +// CHECK2: @"$Globals.cb" = internal global target("dx.CBuffer", // CHECK-NOT: @b = external hidden addrspace(2) global // CHECK2: @j = external hidden addrspace(2) global i32 // CHECK2: @w = external hidden addrspace(2) global <2 x float>, align 4 diff --git a/clang/test/CodeGenHLSL/resources/cbuffer.hlsl b/clang/test/CodeGenHLSL/resources/cbuffer.hlsl index ef9c63a9c8a41..39e0f468a1b69 100644 --- a/clang/test/CodeGenHLSL/resources/cbuffer.hlsl +++ b/clang/test/CodeGenHLSL/resources/cbuffer.hlsl @@ -130,7 +130,7 @@ cbuffer CBScalars : register(b1, space5) { int64_t a8; } -// CHECK: @CBScalars.cb = global target("dx.CBuffer", %__cblayout_CBScalars) +// CHECK: @CBScalars.cb = internal global target("dx.CBuffer", %__cblayout_CBScalars) // CHECK: @a1 = external hidden addrspace(2) global float, align 4 // CHECK: @a2 = external hidden addrspace(2) global double, align 8 // CHECK: @a3 = external hidden addrspace(2) global half, align 2 @@ -152,7 +152,7 @@ cbuffer CBVectors { // FIXME: add a bool vectors after llvm-project/llvm#91639 is added } -// CHECK: @CBVectors.cb = global target("dx.CBuffer", %__cblayout_CBVectors) +// CHECK: @CBVectors.cb = internal global target("dx.CBuffer", %__cblayout_CBVectors) // CHECK: @b1 = external hidden addrspace(2) global <3 x float>, align 4 // CHECK: @b2 = external hidden addrspace(2) global <3 x double>, align 8 // CHECK: @b3 = external hidden addrspace(2) global <2 x half>, align 2 @@ -173,7 +173,7 @@ cbuffer CBArrays : register(b2) { bool c8[4]; } -// CHECK: @CBArrays.cb = global target("dx.CBuffer", %__cblayout_CBArrays) +// CHECK: @CBArrays.cb = internal global target("dx.CBuffer", %__cblayout_CBArrays) // CHECK: @c1 = external hidden addrspace(2) global <{ [2 x <{ float, target("dx.Padding", 12) }>], float }>, align 4 // CHECK: @c2 = external hidden addrspace(2) global <{ [1 x <{ <3 x double>, target("dx.Padding", 8) }>], <3 x double> }>, align 8 // CHECK: @c3 = external hidden addrspace(2) global <{ [1 x <{ <{ [1 x <{ half, target("dx.Padding", 14) }>], half }>, target("dx.Padding", 14) }>], <{ [1 x <{ half, target("dx.Padding", 14) }>], half }> }>, align 2 @@ -193,7 +193,7 @@ cbuffer CBTypedefArray : register(space2) { T2 t2[2]; } -// CHECK: @CBTypedefArray.cb = global target("dx.CBuffer", %__cblayout_CBTypedefArray) +// CHECK: @CBTypedefArray.cb = internal global target("dx.CBuffer", %__cblayout_CBTypedefArray) // CHECK: @t1 = external hidden addrspace(2) global [2 x [2 x <4 x i32>]], align 4 // CHECK: @t2 = external hidden addrspace(2) global [2 x [2 x <4 x i32>]], align 4 // CHECK: @CBTypedefArray.str = private unnamed_addr constant [15 x i8] c"CBTypedefArray\00", align 1 @@ -217,7 +217,7 @@ struct D { Empty es; }; -// CHECK: @CBStructs.cb = global target("dx.CBuffer", %__cblayout_CBStructs) +// CHECK: @CBStructs.cb = internal global target("dx.CBuffer", %__cblayout_CBStructs) // CHECK: @a = external hidden addrspace(2) global %A, align 1 // CHECK: @b = external hidden addrspace(2) global %B, align 1 // CHECK: @c = external hidden addrspace(2) global %C, align 1 @@ -257,7 +257,7 @@ cbuffer CBClasses { K ka[10]; }; -// CHECK: @CBClasses.cb = global target("dx.CBuffer", %__cblayout_CBClasses) +// CHECK: @CBClasses.cb = internal global target("dx.CBuffer", %__cblayout_CBClasses) // CHECK: @k = external hidden addrspace(2) global %K, align 1 // CHECK: @l = external hidden addrspace(2) global %L, align 1 // CHECK: @m = external hidden addrspace(2) global %M, align 1 @@ -268,7 +268,7 @@ struct Test { float a, b; }; -// CHECK: @CBMix.cb = global target("dx.CBuffer", %__cblayout_CBMix) +// CHECK: @CBMix.cb = internal global target("dx.CBuffer", %__cblayout_CBMix) // CHECK: @test = external hidden addrspace(2) global <{ [1 x <{ %Test, target("dx.Padding", 8) }>], %Test }>, align 1 // CHECK: @f1 = external hidden addrspace(2) global float, align 4 // CHECK: @f2 = external hidden addrspace(2) global <{ [2 x <{ <{ [1 x <{ <2 x float>, target("dx.Padding", 8) }>], <2 x float> }>, target("dx.Padding", 8) }>], <{ [1 x <{ <2 x float>, target("dx.Padding", 8) }>], <2 x float> }> }>, align 4 @@ -294,7 +294,7 @@ cbuffer CBMix { uint16_t f9; }; -// CHECK: @CB_A.cb = global target("dx.CBuffer", %__cblayout_CB_A) +// CHECK: @CB_A.cb = internal global target("dx.CBuffer", %__cblayout_CB_A) cbuffer CB_A { double B0[2]; @@ -308,7 +308,7 @@ cbuffer CB_A { half3 B8; } -// CHECK: @CB_B.cb = global target("dx.CBuffer", %__cblayout_CB_B) +// CHECK: @CB_B.cb = internal global target("dx.CBuffer", %__cblayout_CB_B) cbuffer CB_B { double3 B9[3]; half3 B10; @@ -343,7 +343,7 @@ struct G { half C3; }; -// CHECK: @CB_C.cb = global target("dx.CBuffer", %__cblayout_CB_C) +// CHECK: @CB_C.cb = internal global target("dx.CBuffer", %__cblayout_CB_C) cbuffer CB_C { int D0; F D1; @@ -352,6 +352,10 @@ cbuffer CB_C { double D4; } +// CHECK: @llvm.compiler.used = appending global [10 x ptr] [ptr @CBScalars.cb, ptr @CBVectors.cb, +// CHECK-SAME: ptr @CBArrays.cb, ptr @CBTypedefArray.cb, ptr @CBStructs.cb, ptr @CBClasses.cb, +// CHECK-SAME: ptr @CBMix.cb, ptr @CB_A.cb, ptr @CB_B.cb, ptr @CB_C.cb], section "llvm.metadata" + // CHECK: define internal void @_init_buffer_CBScalars.cb() // CHECK-NEXT: entry: // CHECK-NEXT: %CBScalars.cb_h = call target("dx.CBuffer", %__cblayout_CBScalars) diff --git a/clang/test/CodeGenHLSL/resources/cbuffer_and_namespaces.hlsl b/clang/test/CodeGenHLSL/resources/cbuffer_and_namespaces.hlsl index 1fe0a68261c94..3f51b8d8dcb06 100644 --- a/clang/test/CodeGenHLSL/resources/cbuffer_and_namespaces.hlsl +++ b/clang/test/CodeGenHLSL/resources/cbuffer_and_namespaces.hlsl @@ -7,13 +7,13 @@ // CHECK: %"n0::n2::__cblayout_C" = type <{ float, target("dx.Padding", 12), %"n0::Foo" }> // CHECK: %"n0::Foo" = type <{ float }> -// CHECK: @A.cb = global target("dx.CBuffer", %"n0::n1::__cblayout_A") +// CHECK: @A.cb = internal global target("dx.CBuffer", %"n0::n1::__cblayout_A") // CHECK: @_ZN2n02n11aE = external hidden addrspace(2) global float, align 4 -// CHECK: @B.cb = global target("dx.CBuffer", %"n0::__cblayout_B") +// CHECK: @B.cb = internal global target("dx.CBuffer", %"n0::__cblayout_B") // CHECK: @_ZN2n01aE = external hidden addrspace(2) global float, align 4 -// CHECK: @C.cb = global target("dx.CBuffer", %"n0::n2::__cblayout_C") +// CHECK: @C.cb = internal global target("dx.CBuffer", %"n0::n2::__cblayout_C") // CHECK: @_ZN2n02n21aE = external hidden addrspace(2) global float, align 4 // CHECK: external hidden addrspace(2) global %"n0::Foo", align 1 diff --git a/clang/test/CodeGenHLSL/resources/cbuffer_with_packoffset.hlsl b/clang/test/CodeGenHLSL/resources/cbuffer_with_packoffset.hlsl index 818786c591189..ad8d619e9ac3b 100644 --- a/clang/test/CodeGenHLSL/resources/cbuffer_with_packoffset.hlsl +++ b/clang/test/CodeGenHLSL/resources/cbuffer_with_packoffset.hlsl @@ -16,7 +16,7 @@ // CHECK-SAME: float // CHECK-SAME: }> -// CHECK-DAG: @CB.cb = global target("dx.CBuffer", %__cblayout_CB) +// CHECK-DAG: @CB.cb = internal global target("dx.CBuffer", %__cblayout_CB) // CHECK-DAG: @a = external hidden addrspace(2) global float, align 4 // CHECK-DAG: @b = external hidden addrspace(2) global double, align 8 // CHECK-DAG: @c = external hidden addrspace(2) global <2 x i32>, align 4 @@ -28,7 +28,7 @@ cbuffer CB : register(b1, space3) { int2 c : packoffset(c5.z); } -// CHECK-DAG: @CB.cb.1 = global target("dx.CBuffer", %__cblayout_CB_1) +// CHECK-DAG: @CB.cb.1 = internal global target("dx.CBuffer", %__cblayout_CB_1) // CHECK-DAG: @x = external hidden addrspace(2) global float, align 4 // CHECK-DAG: @y = external hidden addrspace(2) global <2 x float>, align 4 diff --git a/clang/test/CodeGenHLSL/resources/cbuffer_with_static_global_and_function.hlsl b/clang/test/CodeGenHLSL/resources/cbuffer_with_static_global_and_function.hlsl index b8c7babb8d634..3d2739f01c1ba 100644 --- a/clang/test/CodeGenHLSL/resources/cbuffer_with_static_global_and_function.hlsl +++ b/clang/test/CodeGenHLSL/resources/cbuffer_with_static_global_and_function.hlsl @@ -2,7 +2,7 @@ // CHECK: %__cblayout_A = type <{ float }> -// CHECK: @A.cb = global target("dx.CBuffer", %__cblayout_A) +// CHECK: @A.cb = internal global target("dx.CBuffer", %__cblayout_A) // CHECK: @a = external hidden addrspace(2) global float, align 4 // CHECK-DAG: @_ZL1b = internal global float 3.000000e+00, align 4 // CHECK-NOT: @B.cb diff --git a/clang/test/CodeGenHLSL/resources/default_cbuffer.hlsl b/clang/test/CodeGenHLSL/resources/default_cbuffer.hlsl index 5333dad962195..6abc337ca869d 100644 --- a/clang/test/CodeGenHLSL/resources/default_cbuffer.hlsl +++ b/clang/test/CodeGenHLSL/resources/default_cbuffer.hlsl @@ -4,12 +4,12 @@ // CHECK: %"__cblayout_$Globals" = type <{ float, float, target("{{.*}}.Padding", 8), %__cblayout_S }> // CHECK: %__cblayout_S = type <{ float }> -// DXIL-DAG: @"$Globals.cb" = global target("dx.CBuffer", %"__cblayout_$Globals") +// DXIL-DAG: @"$Globals.cb" = internal global target("dx.CBuffer", %"__cblayout_$Globals") // DXIL-DAG: @a = external hidden addrspace(2) global float // DXIL-DAG: @g = external hidden addrspace(2) global float // DXIL-DAG: @h = external hidden addrspace(2) global %__cblayout_S, align 4 -// SPIRV-DAG: @"$Globals.cb" = global target("spirv.VulkanBuffer", %"__cblayout_$Globals", 2, 0) +// SPIRV-DAG: @"$Globals.cb" = internal global target("spirv.VulkanBuffer", %"__cblayout_$Globals", 2, 0) // SPIRV-DAG: @a = external hidden addrspace(12) global float // SPIRV-DAG: @g = external hidden addrspace(12) global float // SPIRV-DAG: @h = external hidden addrspace(12) global %__cblayout_S, align 8 diff --git a/clang/test/CodeGenHLSL/resources/default_cbuffer_with_layout.hlsl b/clang/test/CodeGenHLSL/resources/default_cbuffer_with_layout.hlsl index f3d85e57983b2..8bc2b8ee59fda 100644 --- a/clang/test/CodeGenHLSL/resources/default_cbuffer_with_layout.hlsl +++ b/clang/test/CodeGenHLSL/resources/default_cbuffer_with_layout.hlsl @@ -17,7 +17,7 @@ // CHECK: %S = type <{ <2 x float> }> -// CHECK-DAG: @"$Globals.cb" = global target("dx.CBuffer", %"__cblayout_$Globals") +// CHECK-DAG: @"$Globals.cb" = internal global target("dx.CBuffer", %"__cblayout_$Globals") // CHECK-DAG: @a = external hidden addrspace(2) global i32, align 4 // CHECK-DAG: @b = external hidden addrspace(2) global float, align 4 // CHECK-DAG: @c = external hidden addrspace(2) global <{ [3 x <{ double, target("dx.Padding", 8) }>], double }>, align 8 diff --git a/llvm/include/llvm/Frontend/HLSL/CBuffer.h b/llvm/include/llvm/Frontend/HLSL/CBuffer.h index f4e232ffe1745..e39b3f5c824f0 100644 --- a/llvm/include/llvm/Frontend/HLSL/CBuffer.h +++ b/llvm/include/llvm/Frontend/HLSL/CBuffer.h @@ -53,6 +53,7 @@ class CBufferMetadata { iterator begin() { return Mappings.begin(); } iterator end() { return Mappings.end(); } + void removeCBufferGlobalsFromUseList(Module &M); void eraseFromModule(); }; diff --git a/llvm/lib/Frontend/HLSL/CBuffer.cpp b/llvm/lib/Frontend/HLSL/CBuffer.cpp index 33d9b1a1b3102..b5377f666ee4f 100644 --- a/llvm/lib/Frontend/HLSL/CBuffer.cpp +++ b/llvm/lib/Frontend/HLSL/CBuffer.cpp @@ -11,6 +11,7 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" using namespace llvm; using namespace llvm::hlsl; @@ -71,6 +72,22 @@ CBufferMetadata::get(Module &M, llvm::function_ref<bool(Type *)> IsPadding) { return Result; } +void CBufferMetadata::removeCBufferGlobalsFromUseList(Module &M) { + + SmallPtrSet<GlobalVariable *, 8> CBGlobals; + for (const hlsl::CBufferMapping &Mapping : Mappings) + CBGlobals.insert(Mapping.Handle); + + llvm::removeFromUsedLists(M, [&](Constant *C) -> bool { + if (auto *GV = dyn_cast<GlobalVariable>(C)) + return CBGlobals.contains(GV); + return false; + }); + + for (GlobalVariable *HandleGV : CBGlobals) + HandleGV->removeDeadConstantUsers(); +} + void CBufferMetadata::eraseFromModule() { // Remove the cbs named metadata MD->eraseFromParent(); diff --git a/llvm/lib/Target/DirectX/DXILCBufferAccess.cpp b/llvm/lib/Target/DirectX/DXILCBufferAccess.cpp index 56245321a522a..cb4d8039a84c0 100644 --- a/llvm/lib/Target/DirectX/DXILCBufferAccess.cpp +++ b/llvm/lib/Target/DirectX/DXILCBufferAccess.cpp @@ -59,6 +59,7 @@ static bool replaceCBufferAccesses(Module &M) { for (const hlsl::CBufferMember &Member : Mapping.Members) replaceUsersOfGlobal(Member.GV, Mapping.Handle, Member.Offset); + CBufMD->removeCBufferGlobalsFromUseList(M); CBufMD->eraseFromModule(); return true; } diff --git a/llvm/lib/Target/SPIRV/SPIRVCBufferAccess.cpp b/llvm/lib/Target/SPIRV/SPIRVCBufferAccess.cpp index 227d8716d974a..2918834bd0a11 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCBufferAccess.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCBufferAccess.cpp @@ -101,6 +101,8 @@ static bool replaceCBufferAccesses(Module &M) { } } + CBufMD->removeCBufferGlobalsFromUseList(M); + // Now that all uses are replaced, clean up the globals and metadata. for (const hlsl::CBufferMapping &Mapping : *CBufMD) { for (const auto &Member : Mapping.Members) { diff --git a/llvm/test/CodeGen/DirectX/cbuffer_global_elim.ll b/llvm/test/CodeGen/DirectX/cbuffer_global_elim.ll new file mode 100644 index 0000000000000..64d0bd4e04fa3 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/cbuffer_global_elim.ll @@ -0,0 +1,38 @@ +; RUN: opt -S -passes='dxil-cbuffer-access' %s -o - | FileCheck %s --check-prefixes=CHECK +; RUN: llc %s -o - | FileCheck %s --check-prefixes=CHECK-LOWERED +; RUN: llc %s -O3 -o - | FileCheck %s --check-prefixes=CHECK-LOWERED + +target triple = "dxil-unknown-shadermodel6.6-compute" + +%__cblayout_CB = type <{ i32 }> [email protected] = internal global target("dx.CBuffer", %__cblayout_CB) poison +@i = external hidden local_unnamed_addr addrspace(2) global i32, align 4 + [email protected] = appending global [1 x ptr] [ptr @CB.cb], section "llvm.metadata" + +; Check that DXILCBufferAccessPass removes the cbuffer global from @llvm.compiler.used +; +; CHECK: @CB.cb = internal global target("dx.CBuffer", %__cblayout_CB) poison +; CHECK-NOT: @i +; CHECK-NOT: @llvm.compiler.used + +; Check that the cbuffer global is removed during lowering to DXIL +; +; CHECK-LOWERED-NOT: %__cblayout_CB = type <{ i32 }> +; CHECK-LOWERED-NOT: @CB.cb = internal global target("dx.CBuffer", %__cblayout_CB) poison + +define void @main() { +entry: + %cb_handle = tail call target("dx.CBuffer", %__cblayout_CB) @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_s___cblayout_CBst(i32 0, i32 0, i32 1, i32 0, ptr nonnull null) + store target("dx.CBuffer", %__cblayout_CB) %cb_handle, ptr @CB.cb, align 4 + %1 = load i32, ptr addrspace(2) @i, align 4 + ret void +} + +; CHECK-NOT: !hlsl.cbs + +!hlsl.cbs = !{!0} + +!0 = !{ptr @CB.cb, ptr addrspace(2) @i} +!1 = !{i32 1, i32 8} + diff --git a/llvm/test/CodeGen/SPIRV/cbuffer_global_elim.ll b/llvm/test/CodeGen/SPIRV/cbuffer_global_elim.ll new file mode 100644 index 0000000000000..faac15fa24bf9 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/cbuffer_global_elim.ll @@ -0,0 +1,36 @@ +; RUN: opt -S -passes='spirv-cbuffer-access' %s -o - | FileCheck %s +; RUN: llc %s -o - | FileCheck %s +; RUN: llc %s -O3 -o - | FileCheck %s + +target triple = "spirv-unknown-vulkan1.3-compute" + +%__cblayout_CB = type <{ i32 }> [email protected] = internal global target("spirv.VulkanBuffer", %__cblayout_CB, 2, 0) poison +@i = external hidden local_unnamed_addr addrspace(2) global i32, align 4 + [email protected] = appending global [1 x ptr] [ptr @CB.cb], section "llvm.metadata" + +; Check that SPRIVCBufferAccessPass removes the cbuffer global from @llvm.compiler.used +; and from the module. +; +; CHECK-NOT: @CB.cb = internal global target("spirv.VulkanBuffer", %__cblayout_CB, 2, 0) poison +; CHECK-NOT: @i +; CHECK-NOT: @llvm.compiler.used + +; Check that the cbuffer global is removed during lowering to DXIL +; +define void @main() { +entry: + %cb_handle = tail call target("spirv.VulkanBuffer", %__cblayout_CB, 2, 0) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_s___cblayout_CBs_2_0t(i32 0, i32 0, i32 1, i32 0, ptr nonnull null) + store target("spirv.VulkanBuffer", %__cblayout_CB, 2, 0) %cb_handle, ptr @CB.cb, align 4 + %1 = load i32, ptr addrspace(2) @i, align 4 + ret void +} + +; CHECK-NOT: !hlsl.cbs + +!hlsl.cbs = !{!0} + +!0 = !{ptr @CB.cb, ptr addrspace(2) @i} +!1 = !{i32 1, i32 8} + _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
