[llvm] [Offload] Cache symbols in program (PR #148209)

Ross Brunton via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 11 03:53:58 PDT 2025


https://github.com/RossBrunton created https://github.com/llvm/llvm-project/pull/148209

When creating a new symbol, check that it already exists. If it does,
return that pointer rather than building a new symbol structure.


>From 19060bebaa0c4ea3d34a2d99b2c99448b043a765 Mon Sep 17 00:00:00 2001
From: Ross Brunton <ross at codeplay.com>
Date: Fri, 11 Jul 2025 11:52:22 +0100
Subject: [PATCH] [Offload] Cache symbols in program

When creating a new symbol, check that it already exists. If it does,
return that pointer rather than building a new symbol structure.
---
 offload/liboffload/src/OffloadImpl.cpp        | 21 ++++++++++++++++---
 .../OffloadAPI/kernel/olGetKernel.cpp         |  8 +++++++
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index fa5d18c044048..4382aad08ede0 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -85,14 +85,16 @@ struct ol_program_impl_t {
   plugin::DeviceImageTy *Image;
   std::unique_ptr<llvm::MemoryBuffer> ImageData;
   std::vector<std::unique_ptr<ol_symbol_impl_t>> Symbols;
+  std::mutex SymbolListMutex;
   __tgt_device_image DeviceImage;
 };
 
 struct ol_symbol_impl_t {
-  ol_symbol_impl_t(GenericKernelTy *Kernel)
-      : PluginImpl(Kernel), Kind(OL_SYMBOL_KIND_KERNEL) {}
+  ol_symbol_impl_t(const char *Name, GenericKernelTy *Kernel)
+      : PluginImpl(Kernel), Kind(OL_SYMBOL_KIND_KERNEL), Name(Name) {}
   std::variant<GenericKernelTy *> PluginImpl;
   ol_symbol_kind_t Kind;
+  const char *Name;
 };
 
 namespace llvm {
@@ -662,6 +664,18 @@ Error olDestroyProgram_impl(ol_program_handle_t Program) {
 
 Error olGetKernel_impl(ol_program_handle_t Program, const char *KernelName,
                        ol_symbol_handle_t *Kernel) {
+  std::lock_guard<std::mutex> Lock{Program->SymbolListMutex};
+
+  // If it already exists, return an existing handle
+  auto Check = std::find_if(Program->Symbols.begin(), Program->Symbols.end(),
+                            [&](auto &Sym) {
+                              return Sym->Kind == OL_SYMBOL_KIND_KERNEL &&
+                                     !std::strcmp(Sym->Name, KernelName);
+                            });
+  if (Check != Program->Symbols.end()) {
+    *Kernel = Check->get();
+    return Error::success();
+  }
 
   auto &Device = Program->Image->getDevice();
   auto KernelImpl = Device.constructKernel(KernelName);
@@ -672,7 +686,8 @@ Error olGetKernel_impl(ol_program_handle_t Program, const char *KernelName,
     return Err;
 
   *Kernel = Program->Symbols
-                .emplace_back(std::make_unique<ol_symbol_impl_t>(&*KernelImpl))
+                .emplace_back(std::make_unique<ol_symbol_impl_t>(
+                    KernelImpl->getName(), &*KernelImpl))
                 .get();
 
   return Error::success();
diff --git a/offload/unittests/OffloadAPI/kernel/olGetKernel.cpp b/offload/unittests/OffloadAPI/kernel/olGetKernel.cpp
index 34870f1fbf0a3..8c222aa851dda 100644
--- a/offload/unittests/OffloadAPI/kernel/olGetKernel.cpp
+++ b/offload/unittests/OffloadAPI/kernel/olGetKernel.cpp
@@ -19,6 +19,14 @@ TEST_P(olGetKernelTest, Success) {
   ASSERT_NE(Kernel, nullptr);
 }
 
+TEST_P(olGetKernelTest, SuccessSamePtr) {
+  ol_symbol_handle_t KernelA = nullptr;
+  ol_symbol_handle_t KernelB = nullptr;
+  ASSERT_SUCCESS(olGetKernel(Program, "foo", &KernelA));
+  ASSERT_SUCCESS(olGetKernel(Program, "foo", &KernelB));
+  ASSERT_EQ(KernelA, KernelB);
+}
+
 TEST_P(olGetKernelTest, InvalidNullProgram) {
   ol_symbol_handle_t Kernel = nullptr;
   ASSERT_ERROR(OL_ERRC_INVALID_NULL_HANDLE,



More information about the llvm-commits mailing list