[llvm] [SPIR-V] Fix crash when a function pointer global is a use of a cloned function (PR #216638)

Arseniy Obolenskiy via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 16 22:41:25 PDT 2026


https://github.com/aobolensk updated https://github.com/llvm/llvm-project/pull/216638

>From c63063d64460490754a07b3dfbadd7212f513122 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Mon, 17 Aug 2026 06:27:41 +0200
Subject: [PATCH 1/2] [SPIR-V] Fix crash when a function pointer global is a
 use of a cloned function

GlobalValue operands must be updated via replaceUsesOfWith, not Constant::handleOperandChange, which doesn't support them
---
 llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp         | 2 +-
 llvm/test/CodeGen/SPIRV/passes/SPIRVPrepareFunctions.ll | 7 +++++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
index 6d54b6c6fa19d..f5d2dbfaf3d40 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
@@ -639,7 +639,7 @@ SPIRVPrepareFunctionsImpl::removeAggregateTypesFromSignature(Function *F) {
     if (CallInst *CI;
         (CI = dyn_cast<CallInst>(U)) && CI->getCalledFunction() == F)
       CI->mutateFunctionType(NewF->getFunctionType());
-    if (auto *C = dyn_cast<Constant>(U))
+    if (auto *C = dyn_cast<Constant>(U); C && !isa<GlobalValue>(C))
       C->handleOperandChange(F, NewF);
     else
       U->replaceUsesOfWith(F, NewF);
diff --git a/llvm/test/CodeGen/SPIRV/passes/SPIRVPrepareFunctions.ll b/llvm/test/CodeGen/SPIRV/passes/SPIRVPrepareFunctions.ll
index 91ba08d682015..d736afb2d3cd4 100644
--- a/llvm/test/CodeGen/SPIRV/passes/SPIRVPrepareFunctions.ll
+++ b/llvm/test/CodeGen/SPIRV/passes/SPIRVPrepareFunctions.ll
@@ -1,5 +1,7 @@
 ; RUN: opt -S -passes=spirv-prepare-functions -mtriple=spirv64-unknown-unknown < %s | FileCheck %s
 
+ at fp = global ptr addrspace(4) @callback
+
 ; @llvm.bswap.* is replaced with a call to a SPIR-V helper function whose
 ; body implements the byte-swap with shifts/masks/ors.
 define i32 @bswap_i32(i32 %x) {
@@ -71,3 +73,8 @@ declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1)
 declare i32 @llvm.bswap.i32(i32)
 declare i32 @llvm.fshl.i32(i32, i32, i32)
 declare i32 @llvm.fshr.i32(i32, i32, i32)
+
+; CHECK-LABEL: define i32 @callback(
+define { float, float } @callback({ float, float } %x) addrspace(4) {
+  ret { float, float } %x
+}

>From 375923fecb90691b968958e3cc9e626cffd7d387 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Mon, 17 Aug 2026 07:41:13 +0200
Subject: [PATCH 2/2] simplify

---
 llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp         | 6 ++----
 llvm/test/CodeGen/SPIRV/passes/SPIRVPrepareFunctions.ll | 1 +
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
index f5d2dbfaf3d40..8cf0a0164659e 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
@@ -630,6 +630,7 @@ SPIRVPrepareFunctionsImpl::removeAggregateTypesFromSignature(Function *F) {
   CloneFunctionInto(NewF, F, VMap, CloneFunctionChangeType::LocalChangesOnly,
                     Returns);
   NewF->takeName(F);
+  NewF->setComdat(F->getComdat());
 
   addFunctionTypeMutation(
       NewF->getParent()->getOrInsertNamedMetadata("spv.cloned_funcs"),
@@ -639,11 +640,8 @@ SPIRVPrepareFunctionsImpl::removeAggregateTypesFromSignature(Function *F) {
     if (CallInst *CI;
         (CI = dyn_cast<CallInst>(U)) && CI->getCalledFunction() == F)
       CI->mutateFunctionType(NewF->getFunctionType());
-    if (auto *C = dyn_cast<Constant>(U); C && !isa<GlobalValue>(C))
-      C->handleOperandChange(F, NewF);
-    else
-      U->replaceUsesOfWith(F, NewF);
   }
+  F->replaceAllUsesWith(NewF);
 
   // register the mutation
   if (RetType != F->getReturnType())
diff --git a/llvm/test/CodeGen/SPIRV/passes/SPIRVPrepareFunctions.ll b/llvm/test/CodeGen/SPIRV/passes/SPIRVPrepareFunctions.ll
index d736afb2d3cd4..e123b29ac21bd 100644
--- a/llvm/test/CodeGen/SPIRV/passes/SPIRVPrepareFunctions.ll
+++ b/llvm/test/CodeGen/SPIRV/passes/SPIRVPrepareFunctions.ll
@@ -1,6 +1,7 @@
 ; RUN: opt -S -passes=spirv-prepare-functions -mtriple=spirv64-unknown-unknown < %s | FileCheck %s
 
 @fp = global ptr addrspace(4) @callback
+; CHECK: @fp = global ptr addrspace(4) @callback
 
 ; @llvm.bswap.* is replaced with a call to a SPIR-V helper function whose
 ; body implements the byte-swap with shifts/masks/ors.



More information about the llvm-commits mailing list