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

Reply via email to