https://github.com/jmmartinez updated 
https://github.com/llvm/llvm-project/pull/178143

From 494690638a8bf030e4b89aa75d033399e135d3d4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
 <[email protected]>
Date: Thu, 8 Jan 2026 10:04:48 +0100
Subject: [PATCH 01/11] [SPIRV] Emit intrinsics for globals only in function
 that references them

In the SPIRV backend, the SPIRVEmitIntrinscs::processGlobalValue
function adds intrinsic calls for every global variable of the module,
on every function.

These intrinsics are used to keep track of global variables, their types and
initializers.

In SPIRV everything is an instruction (even globals/constants). We currently
represent these global entities as individual instructions on every function.
Later, the `SPIRVModuleAnalysis` collects these entities and maps function 
_local_ registers
to _global_ registers. The `SPIRVAsmPrinter` is in charge of mapping back the 
_local_
registers to the appropiate _global_ register.

These instructions associated with global entities on functions that do not 
reference them leads
to a bloated intermediate representation and high memory consumption (as it 
happend
in https://github.com/llvm/llvm-project/issues/170339).

Consider this example:

```cpp
  int A[1024] = { 0, 1, 2, ..., 1023 };
  int get_a(int i) {
    return A[i];
  }

  void say_hi() {
    puts("hi!\n");
  }
```

Although, `say_hi` does not reference `A`; we would generate machine
instructions for the declaration of `A`, for the constant array that
initializes it, and for the 1024 constant elements of `A`.

This patch doesn't fix the underlying issue, but it mitigates it by only
emitting global-variable SPIRV intrinsics on the functions that use it.
If the global is not referenced by any function, we just pick the first
function definition.

With this patch, the example in 
https://github.com/llvm/llvm-project/issues/170339 drops from
~33Gb of maximum resident set size to less than ~570Mb. And compile
time goes from 2:09min to 1:26min.
---
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 40 ++++++++-
 .../SPV_KHR_float_controls2/exec_mode3.ll     | 72 ++++++++++------
 .../atomicrmw_faddfsub_vec_float16.ll         | 30 +++----
 .../atomicrmw_fminfmax_vec_float16.ll         | 30 +++----
 .../fun-with-aggregate-arg-in-const-init.ll   | 86 +++++++++++--------
 5 files changed, 160 insertions(+), 98 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp 
b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 0ae30a2cdf1ac..84815f6dc5767 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -2117,13 +2117,49 @@ Instruction 
*SPIRVEmitIntrinsics::visitUnreachableInst(UnreachableInst &I) {
   return &I;
 }
 
-void SPIRVEmitIntrinsics::processGlobalValue(GlobalVariable &GV,
-                                             IRBuilder<> &B) {
+static bool shouldEmitIntrinsicsForGlobalValue(const GlobalVariable &GV,
+                                               const Function *CurrF) {
   // Skip special artificial variables.
   static const StringSet<> ArtificialGlobals{"llvm.global.annotations",
                                              "llvm.compiler.used"};
 
   if (ArtificialGlobals.contains(GV.getName()))
+    return false;
+
+  SmallPtrSet<const Value *, 8> Visited;
+  SmallVector<const Value *> Worklist = {&GV};
+  bool ReferencedByAnotherFunction = false;
+  while (!Worklist.empty()) {
+    const Value *V = Worklist.pop_back_val();
+    if (!Visited.insert(V).second)
+      continue;
+
+    if (const Instruction *I = dyn_cast<Instruction>(V)) {
+      if (I->getFunction() == CurrF)
+        return true;
+      ReferencedByAnotherFunction = true;
+      continue;
+    }
+
+    if (const Constant *C = dyn_cast<Constant>(V))
+      Worklist.append(C->user_begin(), C->user_end());
+  }
+
+  // Do not emit the intrinsics in this function, it's going to be emitted on
+  // the functions that reference it.
+  if (ReferencedByAnotherFunction)
+    return false;
+
+  // Emit definitions for globals that are not referenced by any function on 
the
+  // first function definition.
+  const Module &M = *CurrF->getParent();
+  const Function &FirstDefinition = *M.getFunctionDefs().begin();
+  return CurrF == &FirstDefinition;
+}
+
+void SPIRVEmitIntrinsics::processGlobalValue(GlobalVariable &GV,
+                                             IRBuilder<> &B) {
+  if (!shouldEmitIntrinsicsForGlobalValue(GV, CurrF))
     return;
 
   Constant *Init = nullptr;
diff --git 
a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_float_controls2/exec_mode3.ll 
b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_float_controls2/exec_mode3.ll
index 9cc9870c2cfe1..656030b4f5916 100644
--- a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_float_controls2/exec_mode3.ll
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_float_controls2/exec_mode3.ll
@@ -8,39 +8,54 @@
 ; CHECK: OpEntryPoint Kernel %[[#KERNEL_FLOAT_V:]] "k_float_controls_float_v"
 ; CHECK: OpEntryPoint Kernel %[[#KERNEL_ALL_V:]] "k_float_controls_all_v"
 
+; CHECK-DAG: %[[#INT32_TYPE:]] = OpTypeInt 32 0
+; CHECK-DAG: %[[#HALF_TYPE:]] = OpTypeFloat 16
+; CHECK-DAG: %[[#FLOAT_TYPE:]] = OpTypeFloat 32
+; CHECK-DAG: %[[#DOUBLE_TYPE:]] = OpTypeFloat 64
+; CHECK-DAG: %[[#CONST0:]] = OpConstantNull %[[#INT32_TYPE]]
+; CHECK-DAG: %[[#CONST131079:]] = OpConstant %[[#INT32_TYPE]] 131079
+
+; CHECK-DAG: %[[#HALF_V_TYPE:]] = OpTypeVector %[[#HALF_TYPE]]
+; CHECK-DAG: %[[#FLOAT_V_TYPE:]] = OpTypeVector %[[#FLOAT_TYPE]]
+; CHECK-DAG: %[[#DOUBLE_V_TYPE:]] = OpTypeVector %[[#DOUBLE_TYPE]]
+
 ; We expect 130179 for float type.
-; CHECK-DAG: OpExecutionModeId %[[#KERNEL_FLOAT]] FPFastMathDefault 
%[[#FLOAT_TYPE:]] %[[#CONST131079:]]
-; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL]] FPFastMathDefault 
%[[#FLOAT_TYPE:]] %[[#CONST131079]]
+; CHECK-DAG: OpExecutionModeId %[[#KERNEL_FLOAT]] FPFastMathDefault 
%[[#FLOAT_TYPE]] %[[#CONST131079]]
+; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL]] FPFastMathDefault 
%[[#FLOAT_TYPE]] %[[#CONST131079]]
 ; We expect 0 for the rest of types because it's SignedZeroInfNanPreserve.
-; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL]] FPFastMathDefault 
%[[#HALF_TYPE:]] %[[#CONST0:]]
-; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL]] FPFastMathDefault 
%[[#DOUBLE_TYPE:]] %[[#CONST0]]
+; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL]] FPFastMathDefault 
%[[#HALF_TYPE]] %[[#CONST0]]
+; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL]] FPFastMathDefault 
%[[#DOUBLE_TYPE]] %[[#CONST0]]
 
 ; We expect 130179 for float type.
-; CHECK-DAG: OpExecutionModeId %[[#KERNEL_FLOAT_V]] FPFastMathDefault 
%[[#FLOAT_TYPE:]] %[[#CONST131079]]
-; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL_V]] FPFastMathDefault 
%[[#FLOAT_TYPE:]] %[[#CONST131079]]
+; CHECK-DAG: OpExecutionModeId %[[#KERNEL_FLOAT_V]] FPFastMathDefault 
%[[#FLOAT_TYPE]] %[[#CONST131079]]
+; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL_V]] FPFastMathDefault 
%[[#FLOAT_TYPE]] %[[#CONST131079]]
 ; We expect 0 for the rest of types because it's SignedZeroInfNanPreserve.
-; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL_V]] FPFastMathDefault 
%[[#DOUBLE_TYPE:]] %[[#CONST0]]
-; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL_V]] FPFastMathDefault 
%[[#HALF_TYPE:]] %[[#CONST0]]
-
-; CHECK-DAG: OpDecorate %[[#addRes:]] FPFastMathMode 
NotNaN|NotInf|NSZ|AllowReassoc
-; CHECK-DAG: OpDecorate %[[#addResH:]] FPFastMathMode None
-; CHECK-DAG: OpDecorate %[[#addResF:]] FPFastMathMode 
NotNaN|NotInf|NSZ|AllowReassoc
-; CHECK-DAG: OpDecorate %[[#addResD:]] FPFastMathMode None
-; CHECK-DAG: OpDecorate %[[#addRes_V:]] FPFastMathMode 
NotNaN|NotInf|NSZ|AllowReassoc
-; CHECK-DAG: OpDecorate %[[#addResH_V:]] FPFastMathMode None
-; CHECK-DAG: OpDecorate %[[#addResF_V:]] FPFastMathMode 
NotNaN|NotInf|NSZ|AllowReassoc
-; CHECK-DAG: OpDecorate %[[#addResD_V:]] FPFastMathMode None
+; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL_V]] FPFastMathDefault 
%[[#DOUBLE_TYPE]] %[[#CONST0]]
+; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL_V]] FPFastMathDefault 
%[[#HALF_TYPE]] %[[#CONST0]]
 
-; CHECK-DAG: %[[#INT32_TYPE:]] = OpTypeInt 32 0
-; CHECK-DAG: %[[#HALF_TYPE]] = OpTypeFloat 16
-; CHECK-DAG: %[[#FLOAT_TYPE]] = OpTypeFloat 32
-; CHECK-DAG: %[[#DOUBLE_TYPE]] = OpTypeFloat 64
-; CHECK-DAG: %[[#CONST0]] = OpConstantNull %[[#INT32_TYPE]]
-; CHECK-DAG: %[[#CONST131079]] = OpConstant %[[#INT32_TYPE]] 131079
+; CHECK-DAG: OpName %[[#G_addResH:]] "G_addResH"
+; CHECK-DAG: OpName %[[#G_addResF:]] "G_addResF"
+; CHECK-DAG: OpName %[[#G_addResD:]] "G_addResD"
+; CHECK-DAG: OpName %[[#G_addResV:]] "G_addResV"
+; CHECK-DAG: OpName %[[#G_addResH_V:]] "G_addResH_V"
+; CHECK-DAG: OpName %[[#G_addResF_V:]] "G_addResF_V"
+; CHECK-DAG: OpName %[[#G_addResD_V:]] "G_addResD_V"
 
-; CHECK-DAG: %[[#HALF_V_TYPE:]] = OpTypeVector %[[#HALF_TYPE]]
-; CHECK-DAG: %[[#FLOAT_V_TYPE:]] = OpTypeVector %[[#FLOAT_TYPE]]
-; CHECK-DAG: %[[#DOUBLE_V_TYPE:]] = OpTypeVector %[[#DOUBLE_TYPE]]
+; CHECK-DAG: OpStore %[[#G_addResH]] %[[#addResH:]]
+; CHECK-DAG: OpStore %[[#G_addResF]] %[[#addResF:]]
+; CHECK-DAG: OpStore %[[#G_addResD]] %[[#addResD:]]
+; CHECK-DAG: OpStore %[[#G_addResV]] %[[#addResV:]]
+; CHECK-DAG: OpStore %[[#G_addResH_V]] %[[#addResH_V:]]
+; CHECK-DAG: OpStore %[[#G_addResF_V]] %[[#addResF_V:]]
+; CHECK-DAG: OpStore %[[#G_addResD_V]] %[[#addResD_V:]]
+
+; CHECK-DAG: OpDecorate %[[#addResH]] FPFastMathMode None
+; CHECK-DAG: OpDecorate %[[#addResF]] FPFastMathMode 
NotNaN|NotInf|NSZ|AllowReassoc
+; CHECK-DAG: OpDecorate %[[#addResD]] FPFastMathMode None
+; CHECK-DAG: OpDecorate %[[#addResV]] FPFastMathMode 
NotNaN|NotInf|NSZ|AllowReassoc
+; CHECK-DAG: OpDecorate %[[#addResH_V]] FPFastMathMode None
+; CHECK-DAG: OpDecorate %[[#addResF_V]] FPFastMathMode 
NotNaN|NotInf|NSZ|AllowReassoc
+; CHECK-DAG: OpDecorate %[[#addResD_V]] FPFastMathMode None
 
 @G_addRes = global float 0.0
 @G_addResH = global half 0.0
@@ -53,7 +68,8 @@
 
 define dso_local dllexport spir_kernel void @k_float_controls_float(float %f) {
 entry:
-; CHECK-DAG: %[[#addRes]] = OpFAdd %[[#FLOAT_TYPE]]
+; CHECK-DAG: %[[#addRes:]] = OpFAdd %[[#FLOAT_TYPE]]
+; CHECK-DAG: OpDecorate %[[#addRes]] FPFastMathMode 
NotNaN|NotInf|NSZ|AllowReassoc
   %addRes = fadd float %f,  %f
   store volatile float %addRes, ptr @G_addRes
   ret void
@@ -75,7 +91,7 @@ entry:
 
 define dso_local dllexport spir_kernel void @k_float_controls_float_v(<2 x 
float> %f) {
 entry:
-; CHECK-DAG: %[[#addRes_V]] = OpFAdd %[[#FLOAT_V_TYPE]]
+; CHECK-DAG: %[[#addResV]] = OpFAdd %[[#FLOAT_V_TYPE]]
   %addRes = fadd <2 x float> %f,  %f
   store volatile <2 x float> %addRes, ptr @G_addResV
   ret void
diff --git 
a/llvm/test/CodeGen/SPIRV/extensions/SPV_NV_shader_atomic_fp16_vector/atomicrmw_faddfsub_vec_float16.ll
 
b/llvm/test/CodeGen/SPIRV/extensions/SPV_NV_shader_atomic_fp16_vector/atomicrmw_faddfsub_vec_float16.ll
index 36f6e38fc75de..733b356d82ff5 100644
--- 
a/llvm/test/CodeGen/SPIRV/extensions/SPV_NV_shader_atomic_fp16_vector/atomicrmw_faddfsub_vec_float16.ll
+++ 
b/llvm/test/CodeGen/SPIRV/extensions/SPV_NV_shader_atomic_fp16_vector/atomicrmw_faddfsub_vec_float16.ll
@@ -8,20 +8,20 @@
 ; CHECK-DAG: Capability AtomicFloat16VectorNV
 ; CHECK: Extension "SPV_NV_shader_atomic_fp16_vector"
 ; CHECK-DAG: %[[TyF16:[0-9]+]] = OpTypeFloat 16
-; CHECK: %[[TyF16Vec2:[0-9]+]] = OpTypeVector %[[TyF16]] 2
-; CHECK: %[[TyF16Vec4:[0-9]+]] = OpTypeVector %[[TyF16]] 4
-; CHECK: %[[TyF16Vec4Ptr:[0-9]+]] = OpTypePointer {{[a-zA-Z]+}} %[[TyF16Vec4]]
-; CHECK: %[[TyF16Vec2Ptr:[0-9]+]] = OpTypePointer {{[a-zA-Z]+}} %[[TyF16Vec2]]
-; CHECK: %[[TyInt32:[0-9]+]] = OpTypeInt 32 0
-; CHECK: %[[ConstF16:[0-9]+]] = OpConstant %[[TyF16]] 20800{{$}}
-; CHECK: %[[Const0F16Vec2:[0-9]+]] = OpConstantNull %[[TyF16Vec2]]
-; CHECK: %[[f:[0-9]+]] = OpVariable %[[TyF16Vec2Ptr]] CrossWorkgroup 
%[[Const0F16Vec2]]
-; CHECK: %[[Const0F16Vec4:[0-9]+]] = OpConstantNull %[[TyF16Vec4]]
-; CHECK: %[[g:[0-9]+]] = OpVariable %[[TyF16Vec4Ptr]] CrossWorkgroup 
%[[Const0F16Vec4]]
-; CHECK: %[[ConstF16Vec2:[0-9]+]] = OpConstantComposite %[[TyF16Vec2]] 
%[[ConstF16]] %[[ConstF16]]
-; CHECK: %[[ScopeAllSvmDevices:[0-9]+]] = OpConstantNull %[[TyInt32]]
-; CHECK: %[[MemSeqCst:[0-9]+]] = OpConstant %[[TyInt32]] 16{{$}}
-; CHECK: %[[ConstF16Vec4:[0-9]+]] = OpConstantComposite %[[TyF16Vec4]] 
%[[ConstF16]] %[[ConstF16]] %[[ConstF16]] %[[ConstF16]]
+; CHECK-DAG: %[[TyF16Vec2:[0-9]+]] = OpTypeVector %[[TyF16]] 2
+; CHECK-DAG: %[[TyF16Vec4:[0-9]+]] = OpTypeVector %[[TyF16]] 4
+; CHECK-DAG: %[[TyF16Vec4Ptr:[0-9]+]] = OpTypePointer {{[a-zA-Z]+}} 
%[[TyF16Vec4]]
+; CHECK-DAG: %[[TyF16Vec2Ptr:[0-9]+]] = OpTypePointer {{[a-zA-Z]+}} 
%[[TyF16Vec2]]
+; CHECK-DAG: %[[TyInt32:[0-9]+]] = OpTypeInt 32 0
+; CHECK-DAG: %[[ConstF16:[0-9]+]] = OpConstant %[[TyF16]] 20800{{$}}
+; CHECK-DAG: %[[Const0F16Vec2:[0-9]+]] = OpConstantNull %[[TyF16Vec2]]
+; CHECK-DAG: %[[f:[0-9]+]] = OpVariable %[[TyF16Vec2Ptr]] CrossWorkgroup 
%[[Const0F16Vec2]]
+; CHECK-DAG: %[[Const0F16Vec4:[0-9]+]] = OpConstantNull %[[TyF16Vec4]]
+; CHECK-DAG: %[[g:[0-9]+]] = OpVariable %[[TyF16Vec4Ptr]] CrossWorkgroup 
%[[Const0F16Vec4]]
+; CHECK-DAG: %[[ConstF16Vec2:[0-9]+]] = OpConstantComposite %[[TyF16Vec2]] 
%[[ConstF16]] %[[ConstF16]]
+; CHECK-DAG: %[[ScopeAllSvmDevices:[0-9]+]] = OpConstantNull %[[TyInt32]]
+; CHECK-DAG: %[[MemSeqCst:[0-9]+]] = OpConstant %[[TyInt32]] 16{{$}}
+; CHECK-DAG: %[[ConstF16Vec4:[0-9]+]] = OpConstantComposite %[[TyF16Vec4]] 
%[[ConstF16]] %[[ConstF16]] %[[ConstF16]] %[[ConstF16]]
 
 @f = common dso_local local_unnamed_addr addrspace(1) global <2 x half> <half 
0.000000e+00, half 0.000000e+00>
 @g = common dso_local local_unnamed_addr addrspace(1) global <4 x half> <half 
0.000000e+00, half 0.000000e+00, half 0.000000e+00, half 0.000000e+00>
@@ -44,4 +44,4 @@ entry:
   %addval = atomicrmw fadd ptr addrspace(1) @g, <4 x half> <half 
42.000000e+00, half 42.000000e+00, half 42.000000e+00, half 42.000000e+00> 
seq_cst
   %subval = atomicrmw fsub ptr addrspace(1) @g, <4 x half> <half 
42.000000e+00, half 42.000000e+00, half 42.000000e+00, half 42.000000e+00> 
seq_cst
   ret void
-}
\ No newline at end of file
+}
diff --git 
a/llvm/test/CodeGen/SPIRV/extensions/SPV_NV_shader_atomic_fp16_vector/atomicrmw_fminfmax_vec_float16.ll
 
b/llvm/test/CodeGen/SPIRV/extensions/SPV_NV_shader_atomic_fp16_vector/atomicrmw_fminfmax_vec_float16.ll
index 7ac772bf5d094..14e98a6fb1f05 100644
--- 
a/llvm/test/CodeGen/SPIRV/extensions/SPV_NV_shader_atomic_fp16_vector/atomicrmw_fminfmax_vec_float16.ll
+++ 
b/llvm/test/CodeGen/SPIRV/extensions/SPV_NV_shader_atomic_fp16_vector/atomicrmw_fminfmax_vec_float16.ll
@@ -8,20 +8,20 @@
 ; CHECK-DAG: Capability AtomicFloat16VectorNV
 ; CHECK: Extension "SPV_NV_shader_atomic_fp16_vector"
 ; CHECK-DAG: %[[TyF16:[0-9]+]] = OpTypeFloat 16
-; CHECK: %[[TyF16Vec2:[0-9]+]] = OpTypeVector %[[TyF16]] 2
-; CHECK: %[[TyF16Vec4:[0-9]+]] = OpTypeVector %[[TyF16]] 4
-; CHECK: %[[TyF16Vec4Ptr:[0-9]+]] = OpTypePointer {{[a-zA-Z]+}} %[[TyF16Vec4]]
-; CHECK: %[[TyF16Vec2Ptr:[0-9]+]] = OpTypePointer {{[a-zA-Z]+}} %[[TyF16Vec2]]
-; CHECK: %[[TyInt32:[0-9]+]] = OpTypeInt 32 0
-; CHECK: %[[ConstF16:[0-9]+]] = OpConstant %[[TyF16]] 20800{{$}}
-; CHECK: %[[Const0F16Vec2:[0-9]+]] = OpConstantNull %[[TyF16Vec2]]
-; CHECK: %[[f:[0-9]+]] = OpVariable %[[TyF16Vec2Ptr]] CrossWorkgroup 
%[[Const0F16Vec2]]
-; CHECK: %[[Const0F16Vec4:[0-9]+]] = OpConstantNull %[[TyF16Vec4]]
-; CHECK: %[[g:[0-9]+]] = OpVariable %[[TyF16Vec4Ptr]] CrossWorkgroup 
%[[Const0F16Vec4]]
-; CHECK: %[[ConstF16Vec2:[0-9]+]] = OpConstantComposite %[[TyF16Vec2]] 
%[[ConstF16]] %[[ConstF16]]
-; CHECK: %[[ScopeAllSvmDevices:[0-9]+]] = OpConstantNull %[[TyInt32]]
-; CHECK: %[[MemSeqCst:[0-9]+]] = OpConstant %[[TyInt32]] 16{{$}}
-; CHECK: %[[ConstF16Vec4:[0-9]+]] = OpConstantComposite %[[TyF16Vec4]] 
%[[ConstF16]] %[[ConstF16]] %[[ConstF16]] %[[ConstF16]]
+; CHECK-DAG: %[[TyF16Vec2:[0-9]+]] = OpTypeVector %[[TyF16]] 2
+; CHECK-DAG: %[[TyF16Vec4:[0-9]+]] = OpTypeVector %[[TyF16]] 4
+; CHECK-DAG: %[[TyF16Vec4Ptr:[0-9]+]] = OpTypePointer {{[a-zA-Z]+}} 
%[[TyF16Vec4]]
+; CHECK-DAG: %[[TyF16Vec2Ptr:[0-9]+]] = OpTypePointer {{[a-zA-Z]+}} 
%[[TyF16Vec2]]
+; CHECK-DAG: %[[TyInt32:[0-9]+]] = OpTypeInt 32 0
+; CHECK-DAG: %[[ConstF16:[0-9]+]] = OpConstant %[[TyF16]] 20800{{$}}
+; CHECK-DAG: %[[Const0F16Vec2:[0-9]+]] = OpConstantNull %[[TyF16Vec2]]
+; CHECK-DAG: %[[f:[0-9]+]] = OpVariable %[[TyF16Vec2Ptr]] CrossWorkgroup 
%[[Const0F16Vec2]]
+; CHECK-DAG: %[[Const0F16Vec4:[0-9]+]] = OpConstantNull %[[TyF16Vec4]]
+; CHECK-DAG: %[[g:[0-9]+]] = OpVariable %[[TyF16Vec4Ptr]] CrossWorkgroup 
%[[Const0F16Vec4]]
+; CHECK-DAG: %[[ConstF16Vec2:[0-9]+]] = OpConstantComposite %[[TyF16Vec2]] 
%[[ConstF16]] %[[ConstF16]]
+; CHECK-DAG: %[[ScopeAllSvmDevices:[0-9]+]] = OpConstantNull %[[TyInt32]]
+; CHECK-DAG: %[[MemSeqCst:[0-9]+]] = OpConstant %[[TyInt32]] 16{{$}}
+; CHECK-DAG: %[[ConstF16Vec4:[0-9]+]] = OpConstantComposite %[[TyF16Vec4]] 
%[[ConstF16]] %[[ConstF16]] %[[ConstF16]] %[[ConstF16]]
 
 @f = common dso_local local_unnamed_addr addrspace(1) global <2 x half> <half 
0.000000e+00, half 0.000000e+00>
 @g = common dso_local local_unnamed_addr addrspace(1) global <4 x half> <half 
0.000000e+00, half 0.000000e+00, half 0.000000e+00, half 0.000000e+00>
@@ -42,4 +42,4 @@ entry:
   %minval = atomicrmw fmin ptr addrspace(1) @g, <4 x half> <half 
42.000000e+00, half 42.000000e+00, half 42.000000e+00, half 42.000000e+00> 
seq_cst
   %maxval = atomicrmw fmax ptr addrspace(1) @g, <4 x half> <half 
42.000000e+00, half 42.000000e+00, half 42.000000e+00, half 42.000000e+00> 
seq_cst
   ret void
-}
\ No newline at end of file
+}
diff --git 
a/llvm/test/CodeGen/SPIRV/pointers/fun-with-aggregate-arg-in-const-init.ll 
b/llvm/test/CodeGen/SPIRV/pointers/fun-with-aggregate-arg-in-const-init.ll
index ec3fd41f7de9e..ffac585669c26 100644
--- a/llvm/test/CodeGen/SPIRV/pointers/fun-with-aggregate-arg-in-const-init.ll
+++ b/llvm/test/CodeGen/SPIRV/pointers/fun-with-aggregate-arg-in-const-init.ll
@@ -6,47 +6,57 @@
 ; CHECK-DAG: OpExtension "SPV_INTEL_function_pointers"
 ; CHECK-DAG: OpName %[[#fArray:]] "array"
 ; CHECK-DAG: OpName %[[#fStruct:]] "struct"
+; CHECK-DAG: OpName %[[#f0:]] "f0"
+; CHECK-DAG: OpName %[[#f1:]] "f1"
+; CHECK-DAG: OpName %[[#f2:]] "f2"
 
 ; CHECK-DAG: %[[#Int8Ty:]] = OpTypeInt 8 0
-; CHECK: %[[#GlobalInt8PtrTy:]] = OpTypePointer CrossWorkgroup %[[#Int8Ty]]
-; CHECK: %[[#VoidTy:]] = OpTypeVoid
-; CHECK: %[[#TestFnTy:]] = OpTypeFunction %[[#VoidTy]] %[[#GlobalInt8PtrTy]]
-; CHECK: %[[#F16Ty:]] = OpTypeFloat 16
-; CHECK: %[[#t_halfTy:]] = OpTypeStruct %[[#F16Ty]]
-; CHECK: %[[#FnTy:]] = OpTypeFunction %[[#t_halfTy]] %[[#GlobalInt8PtrTy]] 
%[[#t_halfTy]]
-; CHECK: %[[#IntelFnPtrTy:]] = OpTypePointer CodeSectionINTEL %[[#FnTy]]
-; CHECK: %[[#Int8PtrTy:]] = OpTypePointer Function %[[#Int8Ty]]
-; CHECK: %[[#Int32Ty:]] = OpTypeInt 32 0
-; CHECK: %[[#I32Const3:]] = OpConstant %[[#Int32Ty]] 3
-; CHECK: %[[#FnArrTy:]] = OpTypeArray %[[#Int8PtrTy]] %[[#I32Const3]]
-; CHECK: %[[#GlobalFnArrPtrTy:]] = OpTypePointer CrossWorkgroup %[[#FnArrTy]]
-; CHECK: %[[#GlobalFnPtrTy:]] = OpTypePointer CrossWorkgroup %[[#FnTy]]
-; CHECK: %[[#FnPtrTy:]] = OpTypePointer Function %[[#FnTy]]
-; CHECK: %[[#StructWithPfnTy:]] = OpTypeStruct %[[#FnPtrTy]] %[[#FnPtrTy]] 
%[[#FnPtrTy]]
-; CHECK: %[[#ArrayOfPfnTy:]] = OpTypeArray %[[#FnPtrTy]] %[[#I32Const3]]
-; CHECK: %[[#Int64Ty:]] = OpTypeInt 64 0
-; CHECK: %[[#GlobalStructWithPfnPtrTy:]] = OpTypePointer CrossWorkgroup 
%[[#StructWithPfnTy]]
-; CHECK: %[[#GlobalArrOfPfnPtrTy:]] = OpTypePointer CrossWorkgroup 
%[[#ArrayOfPfnTy]]
-; CHECK: %[[#I64Const2:]] = OpConstant %[[#Int64Ty]] 2
-; CHECK: %[[#I64Const1:]] = OpConstant %[[#Int64Ty]] 1
-; CHECK: %[[#I64Const0:]] = OpConstantNull %[[#Int64Ty]]
-; CHECK: %[[#f0Pfn:]] = OpConstantFunctionPointerINTEL %[[#IntelFnPtrTy]] %28
-; CHECK: %[[#f1Pfn:]] = OpConstantFunctionPointerINTEL %[[#IntelFnPtrTy]] %32
-; CHECK: %[[#f2Pfn:]] = OpConstantFunctionPointerINTEL %[[#IntelFnPtrTy]] %36
-; CHECK: %[[#f0Cast:]] = OpSpecConstantOp %[[#FnPtrTy]] Bitcast %[[#f0Pfn]]
-; CHECK: %[[#f1Cast:]] = OpSpecConstantOp %[[#FnPtrTy]] Bitcast %[[#f1Pfn]]
-; CHECK: %[[#f2Cast:]] = OpSpecConstantOp %[[#FnPtrTy]] Bitcast %[[#f2Pfn]]
-; CHECK: %[[#fnptrTy:]] = OpConstantComposite %[[#ArrayOfPfnTy]] %[[#f0Cast]] 
%[[#f1Cast]] %[[#f2Cast]]
-; CHECK: %[[#fnptr:]] = OpVariable %[[#GlobalArrOfPfnPtrTy]] CrossWorkgroup 
%[[#fnptrTy]]
-; CHECK: %[[#fnstructTy:]] = OpConstantComposite %[[#StructWithPfnTy]] 
%[[#f0Cast]] %[[#f1Cast]] %[[#f2Cast]]
-; CHECK: %[[#fnstruct:]] = OpVariable %[[#GlobalStructWithPfnPtrTy:]] 
CrossWorkgroup %[[#fnstructTy]]
+; CHECK-DAG: %[[#GlobalInt8PtrTy:]] = OpTypePointer CrossWorkgroup %[[#Int8Ty]]
+; CHECK-DAG: %[[#VoidTy:]] = OpTypeVoid
+; CHECK-DAG: %[[#TestFnTy:]] = OpTypeFunction %[[#VoidTy]] 
%[[#GlobalInt8PtrTy]]
+; CHECK-DAG: %[[#F16Ty:]] = OpTypeFloat 16
+; CHECK-DAG: %[[#t_halfTy:]] = OpTypeStruct %[[#F16Ty]]
+; CHECK-DAG: %[[#FnTy:]] = OpTypeFunction %[[#t_halfTy]] %[[#GlobalInt8PtrTy]] 
%[[#t_halfTy]]
+; CHECK-DAG: %[[#IntelFnPtrTy:]] = OpTypePointer CodeSectionINTEL %[[#FnTy]]
+; CHECK-DAG: %[[#Int8PtrTy:]] = OpTypePointer Function %[[#Int8Ty]]
+; CHECK-DAG: %[[#Int32Ty:]] = OpTypeInt 32 0
+; CHECK-DAG: %[[#I32Const3:]] = OpConstant %[[#Int32Ty]] 3
+; CHECK-DAG: %[[#FnArrTy:]] = OpTypeArray %[[#Int8PtrTy]] %[[#I32Const3]]
+; CHECK-DAG: %[[#GlobalFnArrPtrTy:]] = OpTypePointer CrossWorkgroup 
%[[#FnArrTy]]
+; CHECK-DAG: %[[#GlobalFnPtrTy:]] = OpTypePointer CrossWorkgroup %[[#FnTy]]
+; CHECK-DAG: %[[#FnPtrTy:]] = OpTypePointer Function %[[#FnTy]]
+; CHECK-DAG: %[[#StructWithPfnTy:]] = OpTypeStruct %[[#FnPtrTy]] %[[#FnPtrTy]] 
%[[#FnPtrTy]]
+; CHECK-DAG: %[[#ArrayOfPfnTy:]] = OpTypeArray %[[#FnPtrTy]] %[[#I32Const3]]
+; CHECK-DAG: %[[#Int64Ty:]] = OpTypeInt 64 0
+; CHECK-DAG: %[[#GlobalStructWithPfnPtrTy:]] = OpTypePointer CrossWorkgroup 
%[[#StructWithPfnTy]]
+; CHECK-DAG: %[[#GlobalArrOfPfnPtrTy:]] = OpTypePointer CrossWorkgroup 
%[[#ArrayOfPfnTy]]
+; CHECK-DAG: %[[#I64Const2:]] = OpConstant %[[#Int64Ty]] 2
+; CHECK-DAG: %[[#I64Const1:]] = OpConstant %[[#Int64Ty]] 1
+; CHECK-DAG: %[[#I64Const0:]] = OpConstantNull %[[#Int64Ty]]
+; CHECK-DAG: %[[#f0Pfn:]] = OpConstantFunctionPointerINTEL %[[#IntelFnPtrTy]] 
%[[#f0]]
+; CHECK-DAG: %[[#f1Pfn:]] = OpConstantFunctionPointerINTEL %[[#IntelFnPtrTy]] 
%[[#f1]]
+; CHECK-DAG: %[[#f2Pfn:]] = OpConstantFunctionPointerINTEL %[[#IntelFnPtrTy]] 
%[[#f2]]
+
+; These constants appear twice (duplicated) at the moment
+; CHECK-DAG: %[[#f0Cast_0:]] = OpSpecConstantOp %[[#FnPtrTy]] Bitcast 
%[[#f0Pfn]]
+; CHECK-DAG: %[[#f1Cast_0:]] = OpSpecConstantOp %[[#FnPtrTy]] Bitcast 
%[[#f1Pfn]]
+; CHECK-DAG: %[[#f2Cast_0:]] = OpSpecConstantOp %[[#FnPtrTy]] Bitcast 
%[[#f2Pfn]]
+; CHECK-DAG: %[[#f0Cast_1:]] = OpSpecConstantOp %[[#FnPtrTy]] Bitcast 
%[[#f0Pfn]]
+; CHECK-DAG: %[[#f1Cast_1:]] = OpSpecConstantOp %[[#FnPtrTy]] Bitcast 
%[[#f1Pfn]]
+; CHECK-DAG: %[[#f2Cast_1:]] = OpSpecConstantOp %[[#FnPtrTy]] Bitcast 
%[[#f2Pfn]]
+
+; CHECK-DAG: %[[#fnptrTy:]] = OpConstantComposite %[[#ArrayOfPfnTy]] 
%[[#f0Cast_0]] %[[#f1Cast_0]] %[[#f2Cast_0]]
+; CHECK-DAG: %[[#fnstructTy:]] = OpConstantComposite %[[#StructWithPfnTy]] 
%[[#f0Cast_1]] %[[#f1Cast_1]] %[[#f2Cast_1]]
+
+; CHECK-DAG: %[[#fnptr:]] = OpVariable %[[#GlobalArrOfPfnPtrTy]] 
CrossWorkgroup %[[#fnptrTy]]
+; CHECK-DAG: %[[#fnstruct:]] = OpVariable %[[#GlobalStructWithPfnPtrTy:]] 
CrossWorkgroup %[[#fnstructTy]]
 ; CHECK-DAG: %[[#GlobalInt8PtrPtrTy:]] = OpTypePointer CrossWorkgroup 
%[[#Int8PtrTy]]
-; CHECK: %[[#StructWithPtrTy:]] = OpTypeStruct %[[#Int8PtrTy]] %[[#Int8PtrTy]] 
%[[#Int8PtrTy]]
-; CHECK: %[[#GlobalStructWithPtrPtrTy:]] = OpTypePointer CrossWorkgroup 
%[[#StructWithPtrTy]]
-; CHECK: %[[#I32Const2:]] = OpConstant %[[#Int32Ty]] 2
-; CHECK: %[[#I32Const1:]] = OpConstant %[[#Int32Ty]] 1
-; CHECK: %[[#I32Const0:]] = OpConstantNull %[[#Int32Ty]]
-; CHECK: %[[#GlobalFnPtrPtrTy:]] = OpTypePointer CrossWorkgroup %[[#FnPtrTy]]
+; CHECK-DAG: %[[#StructWithPtrTy:]] = OpTypeStruct %[[#Int8PtrTy]] 
%[[#Int8PtrTy]] %[[#Int8PtrTy]]
+; CHECK-DAG: %[[#GlobalStructWithPtrPtrTy:]] = OpTypePointer CrossWorkgroup 
%[[#StructWithPtrTy]]
+; CHECK-DAG: %[[#I32Const2:]] = OpConstant %[[#Int32Ty]] 2
+; CHECK-DAG: %[[#I32Const1:]] = OpConstant %[[#Int32Ty]] 1
+; CHECK-DAG: %[[#I32Const0:]] = OpConstantNull %[[#Int32Ty]]
+; CHECK-DAG: %[[#GlobalFnPtrPtrTy:]] = OpTypePointer CrossWorkgroup 
%[[#FnPtrTy]]
 %t_half = type { half }
 %struct.anon = type { ptr, ptr, ptr }
 

From e2e50f687996a710b2fb32a3dbd481b94a8cafee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
 <[email protected]>
Date: Tue, 27 Jan 2026 16:05:55 +0100
Subject: [PATCH 02/11] [Review] Compute which functions reach which globals
 only once

---
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 108 +++++++++++++-----
 1 file changed, 82 insertions(+), 26 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp 
b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 84815f6dc5767..91a5092797740 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -62,6 +62,75 @@ namespace llvm::SPIRV {
 } // namespace llvm::SPIRV
 
 namespace {
+// This class keeps track of which functions reference which global variables.
+class GlobalVariableReferences {
+  template <typename T1, typename T2>
+  using OneToManyMapTy = DenseMap<T1, SmallPtrSet<T2, 4>>;
+
+  OneToManyMapTy<GlobalVariable *, Function *> GlobalIsReferencedByFun;
+
+  void collectGlobalReferences(
+      GlobalVariable *GV,
+      OneToManyMapTy<GlobalVariable *, GlobalVariable *> &Global2Global,
+      OneToManyMapTy<GlobalVariable *, Function *> &Global2Function) {
+    SmallVector<Value *> Stack = {GV->user_begin(), GV->user_end()};
+    while (!Stack.empty()) {
+      Value *V = Stack.pop_back_val();
+
+      if (Instruction *I = dyn_cast<Instruction>(V)) {
+        Global2Function[GV].insert(I->getFunction());
+        continue;
+      }
+
+      if (GlobalVariable *UserGV = dyn_cast<GlobalVariable>(V)) {
+        Global2Global[GV].insert(UserGV);
+        continue;
+      }
+
+      if (Constant *C = dyn_cast<Constant>(V))
+        Stack.append(C->user_begin(), C->user_end());
+    }
+  }
+
+public:
+  void init(Module &M) {
+    // Collect which global variables are referenced by which global variables
+    // and which functions reference each global variables.
+    OneToManyMapTy<GlobalVariable *, GlobalVariable *>
+        GlobalIsReferencedByGlobal;
+    GlobalIsReferencedByGlobal.clear();
+    for (GlobalVariable &GV : M.globals()) {
+      GlobalIsReferencedByGlobal.try_emplace(&GV);
+      collectGlobalReferences(&GV, GlobalIsReferencedByGlobal,
+                              GlobalIsReferencedByFun);
+    }
+
+    // Compute indirect references by iterating until a fixed point is found.
+    bool Changed;
+    do {
+      Changed = false;
+      for (auto &[GV, ReferencedBy] : GlobalIsReferencedByGlobal) {
+        SmallPtrSet<GlobalVariable *, 4> NewRefs = ReferencedBy;
+        for (GlobalVariable *ReferencedGV : ReferencedBy)
+          Changed |=
+              set_union(NewRefs, GlobalIsReferencedByGlobal[ReferencedGV]);
+
+        if (NewRefs.size() > ReferencedBy.size())
+          ReferencedBy = std::move(NewRefs);
+      }
+    } while (Changed);
+
+    for (auto &[GV, ReferencedBy] : GlobalIsReferencedByGlobal) {
+      auto &ReferencedByF = GlobalIsReferencedByFun[GV];
+      for (GlobalVariable *ReferencedGV : ReferencedBy)
+        set_union(ReferencedByF, GlobalIsReferencedByFun[ReferencedGV]);
+    }
+  }
+
+  const auto &getReferencedBy(GlobalVariable &GV) const {
+    return GlobalIsReferencedByFun.at(&GV);
+  }
+};
 
 class SPIRVEmitIntrinsics
     : public ModulePass,
@@ -74,6 +143,7 @@ class SPIRVEmitIntrinsics
   DenseMap<Instruction *, Constant *> AggrConsts;
   DenseMap<Instruction *, Type *> AggrConstTypes;
   DenseSet<Instruction *> AggrStores;
+  GlobalVariableReferences GlobalRefs;
   std::unordered_set<Value *> Named;
 
   // map of function declarations to <pointer arg index => element type>
@@ -204,7 +274,6 @@ class SPIRVEmitIntrinsics
   bool postprocessTypes(Module &M);
   bool processFunctionPointers(Module &M);
   void parseFunDeclarations(Module &M);
-
   void useRoundingMode(ConstrainedFPIntrinsic *FPI, IRBuilder<> &B);
 
   // Tries to walk the type accessed by the given GEP instruction.
@@ -2117,49 +2186,35 @@ Instruction 
*SPIRVEmitIntrinsics::visitUnreachableInst(UnreachableInst &I) {
   return &I;
 }
 
-static bool shouldEmitIntrinsicsForGlobalValue(const GlobalVariable &GV,
-                                               const Function *CurrF) {
+static bool
+shouldEmitIntrinsicsForGlobalValue(const GlobalVariableReferences &GlobalRefs,
+                                   GlobalVariable &GV, Function *F) {
   // Skip special artificial variables.
   static const StringSet<> ArtificialGlobals{"llvm.global.annotations",
                                              "llvm.compiler.used"};
-
   if (ArtificialGlobals.contains(GV.getName()))
     return false;
 
-  SmallPtrSet<const Value *, 8> Visited;
-  SmallVector<const Value *> Worklist = {&GV};
-  bool ReferencedByAnotherFunction = false;
-  while (!Worklist.empty()) {
-    const Value *V = Worklist.pop_back_val();
-    if (!Visited.insert(V).second)
-      continue;
-
-    if (const Instruction *I = dyn_cast<Instruction>(V)) {
-      if (I->getFunction() == CurrF)
-        return true;
-      ReferencedByAnotherFunction = true;
-      continue;
-    }
-
-    if (const Constant *C = dyn_cast<Constant>(V))
-      Worklist.append(C->user_begin(), C->user_end());
-  }
+  auto &ReferencedBy = GlobalRefs.getReferencedBy(GV);
+  if (ReferencedBy.contains(F))
+    return true;
 
   // Do not emit the intrinsics in this function, it's going to be emitted on
   // the functions that reference it.
-  if (ReferencedByAnotherFunction)
+  if (!ReferencedBy.empty())
     return false;
 
   // Emit definitions for globals that are not referenced by any function on 
the
   // first function definition.
-  const Module &M = *CurrF->getParent();
+  const Module &M = *F->getParent();
   const Function &FirstDefinition = *M.getFunctionDefs().begin();
-  return CurrF == &FirstDefinition;
+  return F == &FirstDefinition;
 }
 
 void SPIRVEmitIntrinsics::processGlobalValue(GlobalVariable &GV,
                                              IRBuilder<> &B) {
-  if (!shouldEmitIntrinsicsForGlobalValue(GV, CurrF))
+
+  if (!shouldEmitIntrinsicsForGlobalValue(GlobalRefs, GV, CurrF))
     return;
 
   Constant *Init = nullptr;
@@ -3141,6 +3196,7 @@ bool SPIRVEmitIntrinsics::runOnModule(Module &M) {
 
   parseFunDeclarations(M);
   insertConstantsForFPFastMathDefault(M);
+  GlobalRefs.init(M);
 
   TodoType.clear();
   for (auto &F : M)

From 1e85a6071201688536d5f9b204668223e62988a5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
 <[email protected]>
Date: Tue, 27 Jan 2026 17:23:59 +0100
Subject: [PATCH 03/11] [Review] Address typo in .clear() and me being lazy and
 not doing a .find()

---
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 36 +++++++++++--------
 1 file changed, 22 insertions(+), 14 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp 
b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 91a5092797740..ee84f242ab4d1 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -98,37 +98,45 @@ class GlobalVariableReferences {
     // and which functions reference each global variables.
     OneToManyMapTy<GlobalVariable *, GlobalVariable *>
         GlobalIsReferencedByGlobal;
-    GlobalIsReferencedByGlobal.clear();
-    for (GlobalVariable &GV : M.globals()) {
-      GlobalIsReferencedByGlobal.try_emplace(&GV);
+    GlobalIsReferencedByFun.clear();
+    for (GlobalVariable &GV : M.globals())
       collectGlobalReferences(&GV, GlobalIsReferencedByGlobal,
                               GlobalIsReferencedByFun);
-    }
 
     // Compute indirect references by iterating until a fixed point is found.
     bool Changed;
     do {
       Changed = false;
       for (auto &[GV, ReferencedBy] : GlobalIsReferencedByGlobal) {
-        SmallPtrSet<GlobalVariable *, 4> NewRefs = ReferencedBy;
-        for (GlobalVariable *ReferencedGV : ReferencedBy)
-          Changed |=
-              set_union(NewRefs, GlobalIsReferencedByGlobal[ReferencedGV]);
-
-        if (NewRefs.size() > ReferencedBy.size())
-          ReferencedBy = std::move(NewRefs);
+        SmallVector<GlobalVariable *> OldReferencedBy(ReferencedBy.begin(),
+                                                      ReferencedBy.end());
+        for (GlobalVariable *ReferencedGV : OldReferencedBy) {
+          auto It = GlobalIsReferencedByGlobal.find(ReferencedGV);
+          if (It == GlobalIsReferencedByGlobal.end())
+            continue;
+          Changed |= set_union(ReferencedBy, It->second);
+        }
       }
     } while (Changed);
 
     for (auto &[GV, ReferencedBy] : GlobalIsReferencedByGlobal) {
       auto &ReferencedByF = GlobalIsReferencedByFun[GV];
-      for (GlobalVariable *ReferencedGV : ReferencedBy)
-        set_union(ReferencedByF, GlobalIsReferencedByFun[ReferencedGV]);
+      for (GlobalVariable *ReferencedGV : ReferencedBy) {
+        auto It = GlobalIsReferencedByFun.find(ReferencedGV);
+        if (It == GlobalIsReferencedByFun.end())
+          continue;
+        set_union(ReferencedByF, It->second);
+      }
     }
   }
 
   const auto &getReferencedBy(GlobalVariable &GV) const {
-    return GlobalIsReferencedByFun.at(&GV);
+    auto It = GlobalIsReferencedByFun.find(&GV);
+    if (It != GlobalIsReferencedByFun.end())
+      return It->second;
+
+    const static SmallPtrSet<Function *, 4> Empty;
+    return Empty;
   }
 };
 

From d95d17dfe872034919b7db7a0b6d89d286f530c6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
 <[email protected]>
Date: Wed, 28 Jan 2026 15:07:33 +0100
Subject: [PATCH 04/11] [Review] Move loop body to helper method

---
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 33 +++++++++++--------
 1 file changed, 19 insertions(+), 14 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp 
b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index ee84f242ab4d1..8dbfbcfdbf5dc 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -92,6 +92,23 @@ class GlobalVariableReferences {
     }
   }
 
+  bool propagateGlobalToGlobalReferences(
+      OneToManyMapTy<GlobalVariable *, GlobalVariable *>
+          &GlobalIsReferencedByGlobal) {
+    bool Changed = false;
+    for (auto &[GV, ReferencedBy] : GlobalIsReferencedByGlobal) {
+      SmallVector<GlobalVariable *> OldReferencedBy(ReferencedBy.begin(),
+                                                    ReferencedBy.end());
+      for (GlobalVariable *ReferencedGV : OldReferencedBy) {
+        auto It = GlobalIsReferencedByGlobal.find(ReferencedGV);
+        if (It == GlobalIsReferencedByGlobal.end())
+          continue;
+        Changed |= set_union(ReferencedBy, It->second);
+      }
+    }
+    return Changed;
+  }
+
 public:
   void init(Module &M) {
     // Collect which global variables are referenced by which global variables
@@ -104,20 +121,8 @@ class GlobalVariableReferences {
                               GlobalIsReferencedByFun);
 
     // Compute indirect references by iterating until a fixed point is found.
-    bool Changed;
-    do {
-      Changed = false;
-      for (auto &[GV, ReferencedBy] : GlobalIsReferencedByGlobal) {
-        SmallVector<GlobalVariable *> OldReferencedBy(ReferencedBy.begin(),
-                                                      ReferencedBy.end());
-        for (GlobalVariable *ReferencedGV : OldReferencedBy) {
-          auto It = GlobalIsReferencedByGlobal.find(ReferencedGV);
-          if (It == GlobalIsReferencedByGlobal.end())
-            continue;
-          Changed |= set_union(ReferencedBy, It->second);
-        }
-      }
-    } while (Changed);
+    while (propagateGlobalToGlobalReferences(GlobalIsReferencedByGlobal))
+      (void)0;
 
     for (auto &[GV, ReferencedBy] : GlobalIsReferencedByGlobal) {
       auto &ReferencedByF = GlobalIsReferencedByFun[GV];

From 2185809031e9822b44fbd4f021cb274a29cb9ee8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
 <[email protected]>
Date: Wed, 28 Jan 2026 15:10:22 +0100
Subject: [PATCH 05/11] [Review] move second loop to helper method

---
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 24 ++++++++++++-------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp 
b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 8dbfbcfdbf5dc..e43e3f5ebe8e5 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -109,6 +109,20 @@ class GlobalVariableReferences {
     return Changed;
   }
 
+  void propagateGlobalToFunctionReferences(
+      OneToManyMapTy<GlobalVariable *, GlobalVariable *>
+          &GlobalIsReferencedByGlobal) {
+    for (auto &[GV, ReferencedBy] : GlobalIsReferencedByGlobal) {
+      auto &ReferencedByF = GlobalIsReferencedByFun[GV];
+      for (GlobalVariable *ReferencedGV : ReferencedBy) {
+        auto It = GlobalIsReferencedByFun.find(ReferencedGV);
+        if (It == GlobalIsReferencedByFun.end())
+          continue;
+        set_union(ReferencedByF, It->second);
+      }
+    }
+  }
+
 public:
   void init(Module &M) {
     // Collect which global variables are referenced by which global variables
@@ -124,15 +138,7 @@ class GlobalVariableReferences {
     while (propagateGlobalToGlobalReferences(GlobalIsReferencedByGlobal))
       (void)0;
 
-    for (auto &[GV, ReferencedBy] : GlobalIsReferencedByGlobal) {
-      auto &ReferencedByF = GlobalIsReferencedByFun[GV];
-      for (GlobalVariable *ReferencedGV : ReferencedBy) {
-        auto It = GlobalIsReferencedByFun.find(ReferencedGV);
-        if (It == GlobalIsReferencedByFun.end())
-          continue;
-        set_union(ReferencedByF, It->second);
-      }
-    }
+    propagateGlobalToFunctionReferences(GlobalIsReferencedByGlobal);
   }
 
   const auto &getReferencedBy(GlobalVariable &GV) const {

From a5ab8e86afed2b716c7326be641d3f70d4d364f4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
 <[email protected]>
Date: Wed, 28 Jan 2026 15:14:30 +0100
Subject: [PATCH 06/11] [Review] found -> reached

---
 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 e43e3f5ebe8e5..72c438f1eb4f2 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -134,7 +134,7 @@ class GlobalVariableReferences {
       collectGlobalReferences(&GV, GlobalIsReferencedByGlobal,
                               GlobalIsReferencedByFun);
 
-    // Compute indirect references by iterating until a fixed point is found.
+    // Compute indirect references by iterating until a fixed point is reached.
     while (propagateGlobalToGlobalReferences(GlobalIsReferencedByGlobal))
       (void)0;
 

From 919113dcbf73222c0a130ab5d819dbc2410d6190 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
 <[email protected]>
Date: Wed, 28 Jan 2026 15:22:28 +0100
Subject: [PATCH 07/11] [Review] miscleaneaous renaming

---
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 71 +++++++++----------
 1 file changed, 34 insertions(+), 37 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp 
b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 72c438f1eb4f2..4322bf46bbf75 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -63,27 +63,26 @@ namespace llvm::SPIRV {
 
 namespace {
 // This class keeps track of which functions reference which global variables.
-class GlobalVariableReferences {
+class GlobalVariableUsers {
   template <typename T1, typename T2>
   using OneToManyMapTy = DenseMap<T1, SmallPtrSet<T2, 4>>;
 
-  OneToManyMapTy<GlobalVariable *, Function *> GlobalIsReferencedByFun;
+  OneToManyMapTy<GlobalVariable *, Function *> GlobalIsUsedByFun;
 
-  void collectGlobalReferences(
-      GlobalVariable *GV,
-      OneToManyMapTy<GlobalVariable *, GlobalVariable *> &Global2Global,
-      OneToManyMapTy<GlobalVariable *, Function *> &Global2Function) {
+  void collectGlobalUsers(GlobalVariable *GV,
+                          OneToManyMapTy<GlobalVariable *, GlobalVariable *>
+                              &GlobalIsUsedByGlobal) {
     SmallVector<Value *> Stack = {GV->user_begin(), GV->user_end()};
     while (!Stack.empty()) {
       Value *V = Stack.pop_back_val();
 
       if (Instruction *I = dyn_cast<Instruction>(V)) {
-        Global2Function[GV].insert(I->getFunction());
+        GlobalIsUsedByFun[GV].insert(I->getFunction());
         continue;
       }
 
       if (GlobalVariable *UserGV = dyn_cast<GlobalVariable>(V)) {
-        Global2Global[GV].insert(UserGV);
+        GlobalIsUsedByGlobal[GV].insert(UserGV);
         continue;
       }
 
@@ -92,18 +91,18 @@ class GlobalVariableReferences {
     }
   }
 
-  bool propagateGlobalToGlobalReferences(
+  bool propagateGlobalToGlobalUsers(
       OneToManyMapTy<GlobalVariable *, GlobalVariable *>
-          &GlobalIsReferencedByGlobal) {
+          &GlobalIsUsedByGlobal) {
     bool Changed = false;
-    for (auto &[GV, ReferencedBy] : GlobalIsReferencedByGlobal) {
-      SmallVector<GlobalVariable *> OldReferencedBy(ReferencedBy.begin(),
-                                                    ReferencedBy.end());
-      for (GlobalVariable *ReferencedGV : OldReferencedBy) {
-        auto It = GlobalIsReferencedByGlobal.find(ReferencedGV);
-        if (It == GlobalIsReferencedByGlobal.end())
+    for (auto &[GV, UserGlobals] : GlobalIsUsedByGlobal) {
+      SmallVector<GlobalVariable *> OldUsersGlobals(UserGlobals.begin(),
+                                                    UserGlobals.end());
+      for (GlobalVariable *UserGV : OldUsersGlobals) {
+        auto It = GlobalIsUsedByGlobal.find(UserGV);
+        if (It == GlobalIsUsedByGlobal.end())
           continue;
-        Changed |= set_union(ReferencedBy, It->second);
+        Changed |= set_union(UserGlobals, It->second);
       }
     }
     return Changed;
@@ -111,14 +110,14 @@ class GlobalVariableReferences {
 
   void propagateGlobalToFunctionReferences(
       OneToManyMapTy<GlobalVariable *, GlobalVariable *>
-          &GlobalIsReferencedByGlobal) {
-    for (auto &[GV, ReferencedBy] : GlobalIsReferencedByGlobal) {
-      auto &ReferencedByF = GlobalIsReferencedByFun[GV];
-      for (GlobalVariable *ReferencedGV : ReferencedBy) {
-        auto It = GlobalIsReferencedByFun.find(ReferencedGV);
-        if (It == GlobalIsReferencedByFun.end())
+          &GlobalIsUsedByGlobal) {
+    for (auto &[GV, UserGlobals] : GlobalIsUsedByGlobal) {
+      auto &UserFunctions = GlobalIsUsedByFun[GV];
+      for (GlobalVariable *UserGV : UserGlobals) {
+        auto It = GlobalIsUsedByFun.find(UserGV);
+        if (It == GlobalIsUsedByFun.end())
           continue;
-        set_union(ReferencedByF, It->second);
+        set_union(UserFunctions, It->second);
       }
     }
   }
@@ -127,23 +126,21 @@ class GlobalVariableReferences {
   void init(Module &M) {
     // Collect which global variables are referenced by which global variables
     // and which functions reference each global variables.
-    OneToManyMapTy<GlobalVariable *, GlobalVariable *>
-        GlobalIsReferencedByGlobal;
-    GlobalIsReferencedByFun.clear();
+    OneToManyMapTy<GlobalVariable *, GlobalVariable *> GlobalIsUsedByGlobal;
+    GlobalIsUsedByFun.clear();
     for (GlobalVariable &GV : M.globals())
-      collectGlobalReferences(&GV, GlobalIsReferencedByGlobal,
-                              GlobalIsReferencedByFun);
+      collectGlobalUsers(&GV, GlobalIsUsedByGlobal);
 
     // Compute indirect references by iterating until a fixed point is reached.
-    while (propagateGlobalToGlobalReferences(GlobalIsReferencedByGlobal))
+    while (propagateGlobalToGlobalUsers(GlobalIsUsedByGlobal))
       (void)0;
 
-    propagateGlobalToFunctionReferences(GlobalIsReferencedByGlobal);
+    propagateGlobalToFunctionReferences(GlobalIsUsedByGlobal);
   }
 
-  const auto &getReferencedBy(GlobalVariable &GV) const {
-    auto It = GlobalIsReferencedByFun.find(&GV);
-    if (It != GlobalIsReferencedByFun.end())
+  const auto &getTransitiveUserFunctions(GlobalVariable &GV) const {
+    auto It = GlobalIsUsedByFun.find(&GV);
+    if (It != GlobalIsUsedByFun.end())
       return It->second;
 
     const static SmallPtrSet<Function *, 4> Empty;
@@ -162,7 +159,7 @@ class SPIRVEmitIntrinsics
   DenseMap<Instruction *, Constant *> AggrConsts;
   DenseMap<Instruction *, Type *> AggrConstTypes;
   DenseSet<Instruction *> AggrStores;
-  GlobalVariableReferences GlobalRefs;
+  GlobalVariableUsers GlobalRefs;
   std::unordered_set<Value *> Named;
 
   // map of function declarations to <pointer arg index => element type>
@@ -2206,7 +2203,7 @@ Instruction 
*SPIRVEmitIntrinsics::visitUnreachableInst(UnreachableInst &I) {
 }
 
 static bool
-shouldEmitIntrinsicsForGlobalValue(const GlobalVariableReferences &GlobalRefs,
+shouldEmitIntrinsicsForGlobalValue(const GlobalVariableUsers &GlobalRefs,
                                    GlobalVariable &GV, Function *F) {
   // Skip special artificial variables.
   static const StringSet<> ArtificialGlobals{"llvm.global.annotations",
@@ -2214,7 +2211,7 @@ shouldEmitIntrinsicsForGlobalValue(const 
GlobalVariableReferences &GlobalRefs,
   if (ArtificialGlobals.contains(GV.getName()))
     return false;
 
-  auto &ReferencedBy = GlobalRefs.getReferencedBy(GV);
+  auto &ReferencedBy = GlobalRefs.getTransitiveUserFunctions(GV);
   if (ReferencedBy.contains(F))
     return true;
 

From afcd690783ec359fa3d8d6bde3afe205f9bbb6ba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
 <[email protected]>
Date: Wed, 28 Jan 2026 15:26:29 +0100
Subject: [PATCH 08/11] [Review] Add const

---
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 38 ++++++++++---------
 1 file changed, 20 insertions(+), 18 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp 
b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 4322bf46bbf75..60e9f157f08e4 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -67,38 +67,39 @@ class GlobalVariableUsers {
   template <typename T1, typename T2>
   using OneToManyMapTy = DenseMap<T1, SmallPtrSet<T2, 4>>;
 
-  OneToManyMapTy<GlobalVariable *, Function *> GlobalIsUsedByFun;
+  OneToManyMapTy<const GlobalVariable *, const Function *> GlobalIsUsedByFun;
 
-  void collectGlobalUsers(GlobalVariable *GV,
-                          OneToManyMapTy<GlobalVariable *, GlobalVariable *>
-                              &GlobalIsUsedByGlobal) {
-    SmallVector<Value *> Stack = {GV->user_begin(), GV->user_end()};
+  void collectGlobalUsers(
+      const GlobalVariable *GV,
+      OneToManyMapTy<const GlobalVariable *, const GlobalVariable *>
+          &GlobalIsUsedByGlobal) {
+    SmallVector<const Value *> Stack = {GV->user_begin(), GV->user_end()};
     while (!Stack.empty()) {
-      Value *V = Stack.pop_back_val();
+      const Value *V = Stack.pop_back_val();
 
-      if (Instruction *I = dyn_cast<Instruction>(V)) {
+      if (const Instruction *I = dyn_cast<Instruction>(V)) {
         GlobalIsUsedByFun[GV].insert(I->getFunction());
         continue;
       }
 
-      if (GlobalVariable *UserGV = dyn_cast<GlobalVariable>(V)) {
+      if (const GlobalVariable *UserGV = dyn_cast<GlobalVariable>(V)) {
         GlobalIsUsedByGlobal[GV].insert(UserGV);
         continue;
       }
 
-      if (Constant *C = dyn_cast<Constant>(V))
+      if (const Constant *C = dyn_cast<Constant>(V))
         Stack.append(C->user_begin(), C->user_end());
     }
   }
 
   bool propagateGlobalToGlobalUsers(
-      OneToManyMapTy<GlobalVariable *, GlobalVariable *>
+      OneToManyMapTy<const GlobalVariable *, const GlobalVariable *>
           &GlobalIsUsedByGlobal) {
     bool Changed = false;
     for (auto &[GV, UserGlobals] : GlobalIsUsedByGlobal) {
-      SmallVector<GlobalVariable *> OldUsersGlobals(UserGlobals.begin(),
-                                                    UserGlobals.end());
-      for (GlobalVariable *UserGV : OldUsersGlobals) {
+      SmallVector<const GlobalVariable *> OldUsersGlobals(UserGlobals.begin(),
+                                                          UserGlobals.end());
+      for (const GlobalVariable *UserGV : OldUsersGlobals) {
         auto It = GlobalIsUsedByGlobal.find(UserGV);
         if (It == GlobalIsUsedByGlobal.end())
           continue;
@@ -109,11 +110,11 @@ class GlobalVariableUsers {
   }
 
   void propagateGlobalToFunctionReferences(
-      OneToManyMapTy<GlobalVariable *, GlobalVariable *>
+      OneToManyMapTy<const GlobalVariable *, const GlobalVariable *>
           &GlobalIsUsedByGlobal) {
     for (auto &[GV, UserGlobals] : GlobalIsUsedByGlobal) {
       auto &UserFunctions = GlobalIsUsedByFun[GV];
-      for (GlobalVariable *UserGV : UserGlobals) {
+      for (const GlobalVariable *UserGV : UserGlobals) {
         auto It = GlobalIsUsedByFun.find(UserGV);
         if (It == GlobalIsUsedByFun.end())
           continue;
@@ -126,7 +127,8 @@ class GlobalVariableUsers {
   void init(Module &M) {
     // Collect which global variables are referenced by which global variables
     // and which functions reference each global variables.
-    OneToManyMapTy<GlobalVariable *, GlobalVariable *> GlobalIsUsedByGlobal;
+    OneToManyMapTy<const GlobalVariable *, const GlobalVariable *>
+        GlobalIsUsedByGlobal;
     GlobalIsUsedByFun.clear();
     for (GlobalVariable &GV : M.globals())
       collectGlobalUsers(&GV, GlobalIsUsedByGlobal);
@@ -138,12 +140,12 @@ class GlobalVariableUsers {
     propagateGlobalToFunctionReferences(GlobalIsUsedByGlobal);
   }
 
-  const auto &getTransitiveUserFunctions(GlobalVariable &GV) const {
+  const auto &getTransitiveUserFunctions(const GlobalVariable &GV) const {
     auto It = GlobalIsUsedByFun.find(&GV);
     if (It != GlobalIsUsedByFun.end())
       return It->second;
 
-    const static SmallPtrSet<Function *, 4> Empty;
+    const static SmallPtrSet<const Function *, 4> Empty;
     return Empty;
   }
 };

From d267dbee8aaa3fa11c836dd70774e19731c54efa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
 <[email protected]>
Date: Wed, 28 Jan 2026 15:32:58 +0100
Subject: [PATCH 09/11] [Review] reuse vector

---
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp 
b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 60e9f157f08e4..b1d7e793388a7 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -95,10 +95,10 @@ class GlobalVariableUsers {
   bool propagateGlobalToGlobalUsers(
       OneToManyMapTy<const GlobalVariable *, const GlobalVariable *>
           &GlobalIsUsedByGlobal) {
+    SmallVector<const GlobalVariable *> OldUsersGlobals;
     bool Changed = false;
     for (auto &[GV, UserGlobals] : GlobalIsUsedByGlobal) {
-      SmallVector<const GlobalVariable *> OldUsersGlobals(UserGlobals.begin(),
-                                                          UserGlobals.end());
+      OldUsersGlobals.assign(UserGlobals.begin(), UserGlobals.end());
       for (const GlobalVariable *UserGV : OldUsersGlobals) {
         auto It = GlobalIsUsedByGlobal.find(UserGV);
         if (It == GlobalIsUsedByGlobal.end())

From cde40f4f6cf79ae065309fe5b0ae973c4ed2e25d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
 <[email protected]>
Date: Wed, 28 Jan 2026 15:50:13 +0100
Subject: [PATCH 10/11] [Review] add const and rename

---
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp 
b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index b1d7e793388a7..0f4302901c33e 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -161,7 +161,7 @@ class SPIRVEmitIntrinsics
   DenseMap<Instruction *, Constant *> AggrConsts;
   DenseMap<Instruction *, Type *> AggrConstTypes;
   DenseSet<Instruction *> AggrStores;
-  GlobalVariableUsers GlobalRefs;
+  GlobalVariableUsers GVUsers;
   std::unordered_set<Value *> Named;
 
   // map of function declarations to <pointer arg index => element type>
@@ -2205,21 +2205,22 @@ Instruction 
*SPIRVEmitIntrinsics::visitUnreachableInst(UnreachableInst &I) {
 }
 
 static bool
-shouldEmitIntrinsicsForGlobalValue(const GlobalVariableUsers &GlobalRefs,
-                                   GlobalVariable &GV, Function *F) {
+shouldEmitIntrinsicsForGlobalValue(const GlobalVariableUsers &GVUsers,
+                                   const GlobalVariable &GV,
+                                   const Function *F) {
   // Skip special artificial variables.
   static const StringSet<> ArtificialGlobals{"llvm.global.annotations",
                                              "llvm.compiler.used"};
   if (ArtificialGlobals.contains(GV.getName()))
     return false;
 
-  auto &ReferencedBy = GlobalRefs.getTransitiveUserFunctions(GV);
-  if (ReferencedBy.contains(F))
+  auto &UserFunctions = GVUsers.getTransitiveUserFunctions(GV);
+  if (UserFunctions.contains(F))
     return true;
 
   // Do not emit the intrinsics in this function, it's going to be emitted on
   // the functions that reference it.
-  if (!ReferencedBy.empty())
+  if (!UserFunctions.empty())
     return false;
 
   // Emit definitions for globals that are not referenced by any function on 
the
@@ -2232,7 +2233,7 @@ shouldEmitIntrinsicsForGlobalValue(const 
GlobalVariableUsers &GlobalRefs,
 void SPIRVEmitIntrinsics::processGlobalValue(GlobalVariable &GV,
                                              IRBuilder<> &B) {
 
-  if (!shouldEmitIntrinsicsForGlobalValue(GlobalRefs, GV, CurrF))
+  if (!shouldEmitIntrinsicsForGlobalValue(GVUsers, GV, CurrF))
     return;
 
   Constant *Init = nullptr;
@@ -3214,7 +3215,7 @@ bool SPIRVEmitIntrinsics::runOnModule(Module &M) {
 
   parseFunDeclarations(M);
   insertConstantsForFPFastMathDefault(M);
-  GlobalRefs.init(M);
+  GVUsers.init(M);
 
   TodoType.clear();
   for (auto &F : M)

From 1e0e7f763949de6c02405f51fa6293f3fbdc3c38 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
 <[email protected]>
Date: Wed, 28 Jan 2026 15:58:39 +0100
Subject: [PATCH 11/11] [Review] Avoid repeating the type

---
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp 
b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 0f4302901c33e..3e66fa0ea6dbe 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -145,7 +145,8 @@ class GlobalVariableUsers {
     if (It != GlobalIsUsedByFun.end())
       return It->second;
 
-    const static SmallPtrSet<const Function *, 4> Empty;
+    using FunctionSetType = typename decltype(GlobalIsUsedByFun)::mapped_type;
+    const static FunctionSetType Empty;
     return Empty;
   }
 };

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
  • [llvm-branch-commits... Juan Manuel Martinez Caamaño via llvm-branch-commits
    • [llvm-branch-co... Juan Manuel Martinez Caamaño via llvm-branch-commits

Reply via email to