https://github.com/dnovillo updated https://github.com/llvm/llvm-project/pull/196404
>From 0375876a7daf14cca58d20dce2c7088753888c21 Mon Sep 17 00:00:00 2001 From: Diego Novillo <[email protected]> Date: Wed, 6 May 2026 11:13:34 -0400 Subject: [PATCH 1/4] [clang][SPIR-V] Implement -fspv-preserve-interface This flag, originally implemented in DXC, prevents GlobalDCE from removing entry-point interface variables, even if they are unreferenced after inlining. This adds HLSLSpvPreserveInterface to LangOptions.def and Options.td. In CGHLSLRuntime::finishCodeGen(), adds all addrspace(7) and addrspace(8) globals to llvm.compiler.used. In processGlobalValue(), it extends the condition that emits spv_unref_global to fire for globals whose only uses come from llvm.compiler.used or llvm.used. Fixes https://github.com/llvm/llvm-project/issues/136936 --- clang/include/clang/Basic/LangOptions.def | 1 + clang/include/clang/Options/Options.td | 9 +++ clang/lib/CodeGen/CGHLSLRuntime.cpp | 13 +++++ .../CodeGenHLSL/preserve-interface-dce.hlsl | 25 +++++++++ .../test/CodeGenHLSL/preserve-interface.hlsl | 24 ++++++++ .../Driver/dxc_fspv_preserve_interface.hlsl | 10 ++++ llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 45 +++++++++++++-- .../CodeGen/SPIRV/preserve-interface-dce.ll | 51 +++++++++++++++++ llvm/test/CodeGen/SPIRV/preserve-interface.ll | 55 +++++++++++++++++++ 9 files changed, 228 insertions(+), 5 deletions(-) create mode 100644 clang/test/CodeGenHLSL/preserve-interface-dce.hlsl create mode 100644 clang/test/CodeGenHLSL/preserve-interface.hlsl create mode 100644 clang/test/Driver/dxc_fspv_preserve_interface.hlsl create mode 100644 llvm/test/CodeGen/SPIRV/preserve-interface-dce.ll create mode 100644 llvm/test/CodeGen/SPIRV/preserve-interface.ll diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 4a3e3b7c04822..87a60fdd40475 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -248,6 +248,7 @@ LANGOPT(HLSLStrictAvailability, 1, 0, NotCompatible, "Strict availability diagnostic mode for HLSL built-in functions.") LANGOPT(HLSLSpvUseUnknownImageFormat, 1, 0, NotCompatible, "For storage images and texel buffers, sets the default format to 'Unknown' when not specified via the `vk::image_format` attribute. If this option is not used, the format is inferred from the resource's data type.") LANGOPT(HLSLSpvEnableMaximalReconvergence, 1, 0, NotCompatible, "Enables the MaximallyReconvergesKHR execution mode for this module. This ensures that control flow reconverges at well-defined merge points as defined by the Vulkan spec.") +LANGOPT(HLSLSpvPreserveInterface, 1, 0, NotCompatible, "Preserve entry-point interface variables from dead-code elimination.") LANGOPT(EmitLogicalPointer, 1, 0, NotCompatible, "Allow emitting structured GEP/alloca intrinsics instead of normal GEP/alloca instructions.") LANGOPT(CUDAIsDevice , 1, 0, NotCompatible, "compiling for CUDA device") diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index 8451a3698ef17..7d062346648d6 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -9754,6 +9754,15 @@ def fhlsl_spv_enable_maximal_reconvergence "well-defined merge points as defined by the Vulkan spec.">, MarshallingInfoFlag<LangOpts<"HLSLSpvEnableMaximalReconvergence">>; +def fhlsl_spv_preserve_interface + : Flag<["-"], "fspv-preserve-interface">, + Group<dxc_Group>, + Visibility<[CC1Option, DXCOption]>, + HelpText<"Preserve all interface variables at entry points, preventing " + "dead-code elimination of variables with Location or BuiltIn " + "decorations.">, + MarshallingInfoFlag<LangOpts<"HLSLSpvPreserveInterface">>; + def fexperimental_logical_pointer : Flag<["-"], "fexperimental-logical-pointer">, Visibility<[CC1Option, DXCOption]>, diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index 33d76cbda494a..2ce381e7a7f9a 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> @@ -596,6 +597,18 @@ void CGHLSLRuntime::finishCodeGen() { M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.nativelowprec", 1); + if (LangOpts.HLSLSpvPreserveInterface && T.isSPIRV()) { + // Runs before optimization. Keeps Input/Output globals from GlobalDCE. + SmallVector<GlobalValue *, 8> InterfaceVars; + for (GlobalVariable &GV : M.globals()) { + unsigned AS = GV.getAddressSpace(); + if (AS == 7 || AS == 8) // addrspace 7 = Input, addrspace 8 = Output + InterfaceVars.push_back(&GV); + } + if (!InterfaceVars.empty()) + appendToCompilerUsed(M, InterfaceVars); + } + generateGlobalCtorDtorCalls(); } diff --git a/clang/test/CodeGenHLSL/preserve-interface-dce.hlsl b/clang/test/CodeGenHLSL/preserve-interface-dce.hlsl new file mode 100644 index 0000000000000..6431df6d01a95 --- /dev/null +++ b/clang/test/CodeGenHLSL/preserve-interface-dce.hlsl @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-vertex -std=hlsl2021 \ +// RUN: -finclude-default-header -disable-llvm-passes -emit-llvm -o - %s \ +// RUN: | FileCheck %s --check-prefix=O0 +// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-vertex -std=hlsl2021 \ +// RUN: -finclude-default-header -O2 -emit-llvm -o - %s \ +// RUN: | FileCheck %s --check-prefix=O2 +// +// Confirm that the frontend creates addrspace(7) globals for all entry-point +// input parameters (O0), and that GlobalDCE removes the unused one at O2. +// A passing O2 run confirms that -fspv-preserve-interface requires a DCE guard. + +// Both input globals must be present before optimization. +// O0-DAG: @POSITION0 = external hidden thread_local addrspace(7) +// O0-DAG: @TEXCOORD0 = external hidden thread_local addrspace(7) + +// The used POSITION0 global must survive optimization. +// O2: @POSITION0 = external hidden thread_local{{.*}}addrspace(7) + +// The unused TEXCOORD0 global must be eliminated by GlobalDCE at -O2. +// O2-NOT: @TEXCOORD0 = {{.*}}addrspace(7) + +[shader("vertex")] +float4 main(float4 pos : POSITION0, float4 uv : TEXCOORD0) : SV_Position { + return pos; +} diff --git a/clang/test/CodeGenHLSL/preserve-interface.hlsl b/clang/test/CodeGenHLSL/preserve-interface.hlsl new file mode 100644 index 0000000000000..af30b2db84f93 --- /dev/null +++ b/clang/test/CodeGenHLSL/preserve-interface.hlsl @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-vertex -std=hlsl2021 \ +// RUN: -finclude-default-header -fspv-preserve-interface -O2 -emit-llvm \ +// RUN: -o - %s | FileCheck %s +// +// Confirm that -fspv-preserve-interface prevents GlobalDCE from removing an +// unused entry-point input semantic at -O2. Without the flag, @TEXCOORD0 is +// eliminated (see preserve-interface-dce.hlsl). With the flag, it must survive. + +// Both input globals must be present in the optimized IR. +// CHECK-DAG: @POSITION0 = external hidden thread_local addrspace(7) +// CHECK-DAG: @TEXCOORD0 = external hidden thread_local addrspace(7) + +// Both globals must appear in llvm.compiler.used. The implementation adds all +// addrspace(7) and addrspace(8) globals, not just the ones the optimizer would +// otherwise remove, matching DXC's behavior of marking the entire OpEntryPoint +// as live. +// CHECK: @llvm.compiler.used = appending +// CHECK-DAG: @POSITION0 to ptr +// CHECK-DAG: @TEXCOORD0 to ptr + +[shader("vertex")] +float4 main(float4 pos : POSITION0, float4 uv : TEXCOORD0) : SV_Position { + return pos; +} diff --git a/clang/test/Driver/dxc_fspv_preserve_interface.hlsl b/clang/test/Driver/dxc_fspv_preserve_interface.hlsl new file mode 100644 index 0000000000000..a3c883aa54418 --- /dev/null +++ b/clang/test/Driver/dxc_fspv_preserve_interface.hlsl @@ -0,0 +1,10 @@ +// Verify that -fspv-preserve-interface is accepted by the driver and forwarded +// to cc1 as -fspv-preserve-interface. +// RUN: %clang_dxc -spirv -Tlib_6_7 -fspv-preserve-interface -### %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-PRESERVE +// CHECK-PRESERVE: "-fspv-preserve-interface" + +// Without the flag, -fspv-preserve-interface must not appear in cc1 args. +// RUN: %clang_dxc -spirv -Tlib_6_7 -### %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-NO-PRESERVE +// CHECK-NO-PRESERVE-NOT: "-fspv-preserve-interface" diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp index 97fa49d8836fb..48e19bbca32b9 100644 --- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp @@ -2491,15 +2491,50 @@ Instruction *SPIRVEmitIntrinsics::visitUnreachableInst(UnreachableInst &I) { return &I; } +// llvm.compiler.used and llvm.used hold use-list entries that protect their +// referenced globals from DCE without participating in code generation. +static bool isUseListGlobal(StringRef Name) { + return Name == "llvm.compiler.used" || Name == "llvm.used"; +} + +// Returns true for module-level globals that should not have SPIR-V intrinsics +// emitted (use-list globals plus llvm.global.annotations). +static bool isArtificialGlobal(StringRef Name) { + return isUseListGlobal(Name) || Name == "llvm.global.annotations"; +} + +// Returns true if every use of GV traces back to llvm.compiler.used or +// llvm.used. Such uses are not real function uses. They protect the variable +// from GlobalDCE without participating in code generation. +static bool hasOnlyArtificialUses(const GlobalVariable &GV) { + SmallPtrSet<const Value *, 8> Visited; + SmallVector<const Value *> Stack(GV.users()); + while (!Stack.empty()) { + const Value *V = Stack.pop_back_val(); + if (!Visited.insert(V).second) + continue; + if (const auto *GVUser = dyn_cast<GlobalVariable>(V)) { + if (!isUseListGlobal(GVUser->getName())) + return false; + continue; + } + if (isa<Instruction>(V)) + return false; + if (const auto *C = dyn_cast<Constant>(V)) { + Stack.append(C->user_begin(), C->user_end()); + continue; + } + return false; + } + return true; +} + static bool shouldEmitIntrinsicsForGlobalValue(const GlobalVariableUsers &GVUsers, const GlobalVariable &GV, const Function *F) { // Skip special artificial variables. - static const StringSet<> ArtificialGlobals{"llvm.global.annotations", - "llvm.compiler.used", "llvm.used"}; - - if (ArtificialGlobals.contains(GV.getName())) + if (isArtificialGlobal(GV.getName())) return false; auto &UserFunctions = GVUsers.getTransitiveUserFunctions(GV); @@ -2582,7 +2617,7 @@ void SPIRVEmitIntrinsics::processGlobalValue(GlobalVariable &GV, {GV.getType(), Ty}, {&GV, Const}); InitInst->setArgOperand(1, InitOp); } - if (!Init && GV.use_empty()) + if (!Init && (GV.use_empty() || hasOnlyArtificialUses(GV))) B.CreateIntrinsic(Intrinsic::spv_unref_global, GV.getType(), &GV); } diff --git a/llvm/test/CodeGen/SPIRV/preserve-interface-dce.ll b/llvm/test/CodeGen/SPIRV/preserve-interface-dce.ll new file mode 100644 index 0000000000000..8b5a9310e8b6f --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/preserve-interface-dce.ll @@ -0,0 +1,51 @@ +; RUN: opt -passes=globaldce -S -o - %s | llc -mtriple=spirv-unknown-vulkan1.3-vertex \ +; RUN: -o - | FileCheck %s +; RUN: %if spirv-tools %{ opt -passes=globaldce -S -o - %s \ +; RUN: | llc -mtriple=spirv-unknown-vulkan1.3-vertex -filetype=obj -o - \ +; RUN: | spirv-val --target-env vulkan1.3 %} +; +; Confirm that GlobalDCE removes an addrspace(7) global with no users before +; the SPIR-V backend emits OpEntryPoint. A passing run means the dead variable +; is absent from the interface list and -fspv-preserve-interface must guard it. +; +; @used_input has a live load. It must appear in OpEntryPoint. +; @dead_input has no users. GlobalDCE removes it before backend emission. + +; OpEntryPoint appears before OpVariable in SPIR-V module order. Check it first. +; CHECK: OpCapability Shader +; CHECK: OpEntryPoint Vertex %[[#]] "main" + +; Exactly one Input variable must appear: the one for @used_input. +; CHECK: %[[#]] = OpTypePointer Input +; CHECK: %[[#UsedVar:]] = OpVariable %[[#]] Input +; CHECK-NOT: = OpVariable %[[#]] Input + +@used_input = external hidden thread_local addrspace(7) global float, + !spirv.Decorations !0 +@dead_input = external hidden thread_local addrspace(7) global float, + !spirv.Decorations !2 + +define void @main() #0 { + ; Load from @used_input. The result feeds the store to @output. + %v = load float, ptr addrspace(7) @used_input, align 4 + store float %v, ptr addrspace(8) @output, align 4 + ; @dead_input is never referenced. + ret void +} + +@output = external hidden thread_local addrspace(8) global float, + !spirv.Decorations !4 + +attributes #0 = { "hlsl.shader"="vertex" } + +; Location = 0 on @used_input +!0 = !{!1} +!1 = !{i32 30, i32 0} + +; Location = 1 on @dead_input +!2 = !{!3} +!3 = !{i32 30, i32 1} + +; Location = 0 on @output +!4 = !{!5} +!5 = !{i32 30, i32 0} diff --git a/llvm/test/CodeGen/SPIRV/preserve-interface.ll b/llvm/test/CodeGen/SPIRV/preserve-interface.ll new file mode 100644 index 0000000000000..b0d5fd79b8a62 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/preserve-interface.ll @@ -0,0 +1,55 @@ +; RUN: llc -mtriple=spirv-unknown-vulkan1.3-vertex -o - %s | FileCheck %s +; RUN: %if spirv-tools %{ llc -mtriple=spirv-unknown-vulkan1.3-vertex \ +; RUN: -filetype=obj -o - %s | spirv-val --target-env vulkan1.3 %} +; +; Confirm that an addrspace(7) global protected by llvm.compiler.used appears +; in the SPIR-V output as a distinct OpVariable, even though it has no IR users. +; +; @used_input has a real load. @dead_input is only in llvm.compiler.used. +; +; %[[#USED]] and %[[#DEAD]] capture different IDs (Location 0 vs 1), so the +; OpVariable checks below require two distinct OpVariable Input instructions. +; +; Without the processGlobalValue fix in SPIRVEmitIntrinsics.cpp, @dead_input +; gets no spv_unref_global, buildGlobalVariable is never called for it, and +; both OpDecorate Location 1 and the second OpVariable Input are absent. + +; CHECK: OpCapability Shader +; CHECK: OpEntryPoint Vertex %[[#]] "main" + +; CHECK-DAG: OpDecorate %[[#USED:]] Location 0 +; CHECK-DAG: OpDecorate %[[#DEAD:]] Location 1 +; CHECK-DAG: %[[#USED]] = OpVariable %[[#]] Input +; CHECK-DAG: %[[#DEAD]] = OpVariable %[[#]] Input +; CHECK-DAG: %[[#]] = OpVariable %[[#]] Output + +@used_input = external hidden thread_local addrspace(7) global float, + !spirv.Decorations !0 +@dead_input = external hidden thread_local addrspace(7) global float, + !spirv.Decorations !2 + [email protected] = appending global [1 x ptr addrspace(7)] + [ptr addrspace(7) @dead_input], section "llvm.metadata" + +define void @main() #0 { + %v = load float, ptr addrspace(7) @used_input, align 4 + store float %v, ptr addrspace(8) @output, align 4 + ret void +} + +@output = external hidden thread_local addrspace(8) global float, + !spirv.Decorations !4 + +attributes #0 = { "hlsl.shader"="vertex" } + +; Location = 0 on @used_input +!0 = !{!1} +!1 = !{i32 30, i32 0} + +; Location = 1 on @dead_input +!2 = !{!3} +!3 = !{i32 30, i32 1} + +; Location = 0 on @output +!4 = !{!5} +!5 = !{i32 30, i32 0} >From ae3dcba2c9421f03c07e1237aba4daac9c9e8bcd Mon Sep 17 00:00:00 2001 From: Diego Novillo <[email protected]> Date: Tue, 12 May 2026 17:10:34 -0400 Subject: [PATCH 2/4] Address review feedback. --- clang/lib/CodeGen/CGHLSLRuntime.cpp | 5 ++++- llvm/test/CodeGen/SPIRV/preserve-interface.ll | 14 +++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index 2ce381e7a7f9a..731668b14a1ce 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -599,10 +599,13 @@ void CGHLSLRuntime::finishCodeGen() { if (LangOpts.HLSLSpvPreserveInterface && T.isSPIRV()) { // Runs before optimization. Keeps Input/Output globals from GlobalDCE. + const ASTContext &Ctx = CGM.getContext(); + unsigned InputAS = Ctx.getTargetAddressSpace(LangAS::hlsl_input); + unsigned OutputAS = Ctx.getTargetAddressSpace(LangAS::hlsl_output); SmallVector<GlobalValue *, 8> InterfaceVars; for (GlobalVariable &GV : M.globals()) { unsigned AS = GV.getAddressSpace(); - if (AS == 7 || AS == 8) // addrspace 7 = Input, addrspace 8 = Output + if (AS == InputAS || AS == OutputAS) InterfaceVars.push_back(&GV); } if (!InterfaceVars.empty()) diff --git a/llvm/test/CodeGen/SPIRV/preserve-interface.ll b/llvm/test/CodeGen/SPIRV/preserve-interface.ll index b0d5fd79b8a62..12f2a9cde55e3 100644 --- a/llvm/test/CodeGen/SPIRV/preserve-interface.ll +++ b/llvm/test/CodeGen/SPIRV/preserve-interface.ll @@ -3,7 +3,8 @@ ; RUN: -filetype=obj -o - %s | spirv-val --target-env vulkan1.3 %} ; ; Confirm that an addrspace(7) global protected by llvm.compiler.used appears -; in the SPIR-V output as a distinct OpVariable, even though it has no IR users. +; in the SPIR-V output as a distinct OpVariable, even though it has no IR +; users, and that it is also listed in the OpEntryPoint interface. ; ; @used_input has a real load. @dead_input is only in llvm.compiler.used. ; @@ -13,15 +14,22 @@ ; Without the processGlobalValue fix in SPIRVEmitIntrinsics.cpp, @dead_input ; gets no spv_unref_global, buildGlobalVariable is never called for it, and ; both OpDecorate Location 1 and the second OpVariable Input are absent. +; +; The OpEntryPoint check pins the interface to exactly three IDs. The SPIR-V +; backend builds the interface by iterating every Input/Output OpVariable in +; the module, so combined with the three OpVariable checks below this proves +; all three preserved variables appear in OpEntryPoint regardless of the +; backend's interface ordering. ; CHECK: OpCapability Shader -; CHECK: OpEntryPoint Vertex %[[#]] "main" +; CHECK: OpEntryPoint Vertex %[[#]] "main" %[[#]] %[[#]] %[[#]] ; CHECK-DAG: OpDecorate %[[#USED:]] Location 0 ; CHECK-DAG: OpDecorate %[[#DEAD:]] Location 1 +; CHECK-DAG: OpDecorate %[[#OUTPUT:]] Location 0 ; CHECK-DAG: %[[#USED]] = OpVariable %[[#]] Input ; CHECK-DAG: %[[#DEAD]] = OpVariable %[[#]] Input -; CHECK-DAG: %[[#]] = OpVariable %[[#]] Output +; CHECK-DAG: %[[#OUTPUT]] = OpVariable %[[#]] Output @used_input = external hidden thread_local addrspace(7) global float, !spirv.Decorations !0 >From 6f996481ea4fe80d06c87e14e2b04ffef0b58ef7 Mon Sep 17 00:00:00 2001 From: Diego Novillo <[email protected]> Date: Thu, 4 Jun 2026 12:29:52 -0400 Subject: [PATCH 3/4] Update llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Juan Manuel Martinez Caamaño <[email protected]> --- llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp index 48e19bbca32b9..1b7bd14af1555 100644 --- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp @@ -2518,8 +2518,6 @@ static bool hasOnlyArtificialUses(const GlobalVariable &GV) { return false; continue; } - if (isa<Instruction>(V)) - return false; if (const auto *C = dyn_cast<Constant>(V)) { Stack.append(C->user_begin(), C->user_end()); continue; >From ef10320d6bf227f6c7e38497964c95ef2978d4ed Mon Sep 17 00:00:00 2001 From: Diego Novillo <[email protected]> Date: Thu, 4 Jun 2026 12:30:21 -0400 Subject: [PATCH 4/4] Update llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Juan Manuel Martinez Caamaño <[email protected]> --- llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp index 1b7bd14af1555..4bf9356d69343 100644 --- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp @@ -2615,7 +2615,7 @@ void SPIRVEmitIntrinsics::processGlobalValue(GlobalVariable &GV, {GV.getType(), Ty}, {&GV, Const}); InitInst->setArgOperand(1, InitOp); } - if (!Init && (GV.use_empty() || hasOnlyArtificialUses(GV))) + if (!Init && hasOnlyArtificialUses(GV)) B.CreateIntrinsic(Intrinsic::spv_unref_global, GV.getType(), &GV); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
