https://github.com/s-perron updated 
https://github.com/llvm/llvm-project/pull/125718

>From 3ba76b95757a43002d8f799651d7846658011e37 Mon Sep 17 00:00:00 2001
From: Steven Perron <stevenper...@google.com>
Date: Tue, 4 Feb 2025 11:47:42 -0500
Subject: [PATCH 1/2] [HLSL] Fix resrouce wrapper declaration

The resource wrapper should have internal linkage because it cotains a
handle to the global resource, and it not the actual global.

Makeing this changed exposed that we were zeroinitializing the resouce,
which is a problem. The handle cannot be zeroinitialized.

Fixes https://github.com/llvm/llvm-project/issues/122767.
---
 clang/lib/CodeGen/CGHLSLRuntime.h                  |  2 ++
 clang/lib/CodeGen/CodeGenModule.cpp                | 10 +++++++++-
 .../builtins/ByteAddressBuffers-constructors.hlsl  |  6 +++---
 .../builtins/RWBuffer-constructor-opt.hlsl         | 14 +++-----------
 .../CodeGenHLSL/builtins/RWBuffer-constructor.hlsl |  2 +-
 .../builtins/StructuredBuffers-constructors.hlsl   | 10 +++++-----
 6 files changed, 23 insertions(+), 21 deletions(-)

diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index 8767a2ddceb96..0563d98b7dc59 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -137,6 +137,8 @@ class CGHLSLRuntime {
     llvm::StructType *LayoutStruct = nullptr;
   };
 
+  bool isResource(const VarDecl *D);
+
 protected:
   CodeGenModule &CGM;
 
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index 7924c32fcf633..5b11bc89cdb2e 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -5589,7 +5589,10 @@ void CodeGenModule::EmitGlobalVarDefinition(const 
VarDecl *D,
       if (D->getType()->isReferenceType())
         T = D->getType();
 
-      if (getLangOpts().CPlusPlus) {
+      if (getLangOpts().HLSL && getHLSLRuntime().isResource(D)) {
+        Init = llvm::UndefValue::get(getTypes().ConvertType(ASTTy));
+        NeedsGlobalCtor = true;
+      } else if (getLangOpts().CPlusPlus) {
         Init = EmitNullConstant(T);
         if (!IsDefinitionAvailableExternally)
           NeedsGlobalCtor = true;
@@ -5735,6 +5738,11 @@ void CodeGenModule::EmitGlobalVarDefinition(const 
VarDecl *D,
       !D->hasAttr<ConstInitAttr>())
     Linkage = llvm::GlobalValue::InternalLinkage;
 
+  // For HLSL resources, the GV is an internal wrapper containing a handle to
+  // external resource.
+  if (getLangOpts().HLSL && getHLSLRuntime().isResource(D))
+    Linkage = llvm::GlobalValue::InternalLinkage;
+
   GV->setLinkage(Linkage);
   if (D->hasAttr<DLLImportAttr>())
     GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
diff --git 
a/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl 
b/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl
index 7fc6f4bb05745..0e1ef3c70e7dd 100644
--- a/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl
@@ -11,9 +11,9 @@ RasterizerOrderedByteAddressBuffer Buffer2: register(u3, 
space4);
 // CHECK: "class.hlsl::RWByteAddressBuffer" = type { target("dx.RawBuffer", 
i8, 1, 0) }
 // CHECK: "class.hlsl::RasterizerOrderedByteAddressBuffer" = type { 
target("dx.RawBuffer", i8, 1, 1) }
 
-// CHECK: @Buffer0 = global %"class.hlsl::ByteAddressBuffer" zeroinitializer, 
align 4
-// CHECK: @Buffer1 = global %"class.hlsl::RWByteAddressBuffer" 
zeroinitializer, align 4
-// CHECK: @Buffer2 = global %"class.hlsl::RasterizerOrderedByteAddressBuffer" 
zeroinitializer, align 4
+// CHECK: @Buffer0 = internal global %"class.hlsl::ByteAddressBuffer" undef, 
align 4
+// CHECK: @Buffer1 = internal global %"class.hlsl::RWByteAddressBuffer" undef, 
align 4
+// CHECK: @Buffer2 = internal global 
%"class.hlsl::RasterizerOrderedByteAddressBuffer" undef, align 4
 
 // CHECK; define internal void @_init_resource_Buffer0()
 // CHECK-DXIL: %Buffer0_h = call target("dx.RawBuffer", i8, 0, 0) 
@llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_0_0t(i32 0, i32 0, i32 1, 
i32 0, i1 false)
diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor-opt.hlsl 
b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor-opt.hlsl
index 03f22620a097d..239fb6d556999 100644
--- a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor-opt.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor-opt.hlsl
@@ -1,8 +1,7 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm 
-O3 -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL
-// RUN: %clang_cc1 -triple spirv-vulkan-compute -x hlsl -emit-llvm -O3 -o - %s 
| FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm 
-O3 -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple spirv-vulkan-compute -x hlsl -emit-llvm -O3 -o - %s 
| FileCheck %s
 
-// CHECK-SPIRV: %"class.hlsl::RWBuffer" = type { target("spirv.Image", float, 
5, 2, 0, 0, 2, 0) }
-// CHECK-DXIL:  %"class.hlsl::RWBuffer" = type { target("dx.TypedBuffer", 
float, 1, 0, 0) }
+// All referenced to an unused resource should be removed by optimizations.
 RWBuffer<float> Buf : register(u5, space3);
 
 [shader("compute")]
@@ -10,12 +9,5 @@ RWBuffer<float> Buf : register(u5, space3);
 void main() {
 // CHECK: define void @main()
 // CHECK-NEXT: entry:
-
-// CHECK-SPIRV-NEXT: %[[HANDLE:.*]] = tail call target("spirv.Image", float, 
5, 2, 0, 0, 2, 0) 
@llvm.spv.resource.handlefrombinding.tspirv.Image_f32_5_2_0_0_2_0t(i32 3, i32 
5, i32 1, i32 0, i1 false)
-// CHECK-SPIRV-NEXT: store target("spirv.Image", float, 5, 2, 0, 0, 2, 0) 
%[[HANDLE:.*]], ptr @Buf, align 8
-
-// CHECK-DXIL-NEXT: %[[HANDLE:.*]] = tail call target("dx.TypedBuffer", float, 
1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, 
i32 5, i32 1, i32 0, i1 false)
-// CHECK-DXIL-NEXT: store target("dx.TypedBuffer", float, 1, 0, 0) 
%[[HANDLE]], ptr @Buf, align 4
-
 // CHECK-NEXT: ret void
 }
diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl 
b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl
index d7cc3892a404b..9527a8125fc56 100644
--- a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl
@@ -7,7 +7,7 @@
 RWBuffer<float> Buf : register(u5, space3);
 
 // CHECK: %"class.hlsl::RWBuffer" = type { target("dx.TypedBuffer", float, 1, 
0, 0) }
-// CHECK: @Buf = global %"class.hlsl::RWBuffer" zeroinitializer, align 4
+// CHECK: @Buf = internal global %"class.hlsl::RWBuffer" undef, align 4
 
 // CHECK: define internal void @_init_resource_Buf()
 // CHECK-DXIL: %Buf_h = call target("dx.TypedBuffer", float, 1, 0, 0) 
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, 
i32 1, i32 0, i1 false)
diff --git 
a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl 
b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl
index bd931181045ba..6a6a465092a62 100644
--- a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl
@@ -15,11 +15,11 @@ RasterizerOrderedStructuredBuffer<float> Buf5 : 
register(u1, space2);
 // CHECK: %"class.hlsl::ConsumeStructuredBuffer" = type { 
target("dx.RawBuffer", float, 1, 0) }
 // CHECK: %"class.hlsl::RasterizerOrderedStructuredBuffer" = type { 
target("dx.RawBuffer", float, 1, 1) }
 
-// CHECK: @Buf = global %"class.hlsl::StructuredBuffer" zeroinitializer, align 
4
-// CHECK: @Buf2 = global %"class.hlsl::RWStructuredBuffer" zeroinitializer, 
align 4
-// CHECK: @Buf3 = global %"class.hlsl::AppendStructuredBuffer" 
zeroinitializer, align 4
-// CHECK: @Buf4 = global %"class.hlsl::ConsumeStructuredBuffer" 
zeroinitializer, align 4
-// CHECK: @Buf5 = global %"class.hlsl::RasterizerOrderedStructuredBuffer" 
zeroinitializer, align 4
+// CHECK: @Buf = internal global %"class.hlsl::StructuredBuffer" undef, align 4
+// CHECK: @Buf2 = internal global %"class.hlsl::RWStructuredBuffer" undef, 
align 4
+// CHECK: @Buf3 = internal global %"class.hlsl::AppendStructuredBuffer" undef, 
align 4
+// CHECK: @Buf4 = internal global %"class.hlsl::ConsumeStructuredBuffer" 
undef, align 4
+// CHECK: @Buf5 = internal global 
%"class.hlsl::RasterizerOrderedStructuredBuffer" undef, align 4
 
 // CHECK: define internal void @_init_resource_Buf()
 // CHECK-DXIL: %Buf_h = call target("dx.RawBuffer", float, 0, 0) 
@llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_0_0t(i32 0, i32 10, i32 
1, i32 0, i1 false)

>From bcc685efeebd2c6f4465d3d257f05ad76f2e1bc2 Mon Sep 17 00:00:00 2001
From: Steven Perron <stevenper...@google.com>
Date: Tue, 4 Feb 2025 12:27:42 -0500
Subject: [PATCH 2/2] Use poison instead of undef.

---
 clang/lib/CodeGen/CodeGenModule.cpp                    |  2 +-
 .../builtins/ByteAddressBuffers-constructors.hlsl      |  6 +++---
 .../CodeGenHLSL/builtins/RWBuffer-constructor.hlsl     |  2 +-
 .../builtins/StructuredBuffers-constructors.hlsl       | 10 +++++-----
 4 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index 5b11bc89cdb2e..1f4ead3ba23c3 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -5590,7 +5590,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl 
*D,
         T = D->getType();
 
       if (getLangOpts().HLSL && getHLSLRuntime().isResource(D)) {
-        Init = llvm::UndefValue::get(getTypes().ConvertType(ASTTy));
+        Init = llvm::PoisonValue::get(getTypes().ConvertType(ASTTy));
         NeedsGlobalCtor = true;
       } else if (getLangOpts().CPlusPlus) {
         Init = EmitNullConstant(T);
diff --git 
a/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl 
b/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl
index 0e1ef3c70e7dd..5f71358109e68 100644
--- a/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl
@@ -11,9 +11,9 @@ RasterizerOrderedByteAddressBuffer Buffer2: register(u3, 
space4);
 // CHECK: "class.hlsl::RWByteAddressBuffer" = type { target("dx.RawBuffer", 
i8, 1, 0) }
 // CHECK: "class.hlsl::RasterizerOrderedByteAddressBuffer" = type { 
target("dx.RawBuffer", i8, 1, 1) }
 
-// CHECK: @Buffer0 = internal global %"class.hlsl::ByteAddressBuffer" undef, 
align 4
-// CHECK: @Buffer1 = internal global %"class.hlsl::RWByteAddressBuffer" undef, 
align 4
-// CHECK: @Buffer2 = internal global 
%"class.hlsl::RasterizerOrderedByteAddressBuffer" undef, align 4
+// CHECK: @Buffer0 = internal global %"class.hlsl::ByteAddressBuffer" poison, 
align 4
+// CHECK: @Buffer1 = internal global %"class.hlsl::RWByteAddressBuffer" 
poison, align 4
+// CHECK: @Buffer2 = internal global 
%"class.hlsl::RasterizerOrderedByteAddressBuffer" poison, align 4
 
 // CHECK; define internal void @_init_resource_Buffer0()
 // CHECK-DXIL: %Buffer0_h = call target("dx.RawBuffer", i8, 0, 0) 
@llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_0_0t(i32 0, i32 0, i32 1, 
i32 0, i1 false)
diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl 
b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl
index 9527a8125fc56..9df5d2a7f2624 100644
--- a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl
@@ -7,7 +7,7 @@
 RWBuffer<float> Buf : register(u5, space3);
 
 // CHECK: %"class.hlsl::RWBuffer" = type { target("dx.TypedBuffer", float, 1, 
0, 0) }
-// CHECK: @Buf = internal global %"class.hlsl::RWBuffer" undef, align 4
+// CHECK: @Buf = internal global %"class.hlsl::RWBuffer" poison, align 4
 
 // CHECK: define internal void @_init_resource_Buf()
 // CHECK-DXIL: %Buf_h = call target("dx.TypedBuffer", float, 1, 0, 0) 
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, 
i32 1, i32 0, i1 false)
diff --git 
a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl 
b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl
index 6a6a465092a62..4b64c3e28fb9b 100644
--- a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl
@@ -15,11 +15,11 @@ RasterizerOrderedStructuredBuffer<float> Buf5 : 
register(u1, space2);
 // CHECK: %"class.hlsl::ConsumeStructuredBuffer" = type { 
target("dx.RawBuffer", float, 1, 0) }
 // CHECK: %"class.hlsl::RasterizerOrderedStructuredBuffer" = type { 
target("dx.RawBuffer", float, 1, 1) }
 
-// CHECK: @Buf = internal global %"class.hlsl::StructuredBuffer" undef, align 4
-// CHECK: @Buf2 = internal global %"class.hlsl::RWStructuredBuffer" undef, 
align 4
-// CHECK: @Buf3 = internal global %"class.hlsl::AppendStructuredBuffer" undef, 
align 4
-// CHECK: @Buf4 = internal global %"class.hlsl::ConsumeStructuredBuffer" 
undef, align 4
-// CHECK: @Buf5 = internal global 
%"class.hlsl::RasterizerOrderedStructuredBuffer" undef, align 4
+// CHECK: @Buf = internal global %"class.hlsl::StructuredBuffer" poison, align 
4
+// CHECK: @Buf2 = internal global %"class.hlsl::RWStructuredBuffer" poison, 
align 4
+// CHECK: @Buf3 = internal global %"class.hlsl::AppendStructuredBuffer" 
poison, align 4
+// CHECK: @Buf4 = internal global %"class.hlsl::ConsumeStructuredBuffer" 
poison, align 4
+// CHECK: @Buf5 = internal global 
%"class.hlsl::RasterizerOrderedStructuredBuffer" poison, align 4
 
 // CHECK: define internal void @_init_resource_Buf()
 // CHECK-DXIL: %Buf_h = call target("dx.RawBuffer", float, 0, 0) 
@llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_0_0t(i32 0, i32 10, i32 
1, i32 0, i1 false)

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to