[llvm] [SPIR-V] Add SPV_AMD_weak_linkage extension (PR #193307)

Dmitry Sidorov via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 22 02:59:29 PDT 2026


https://github.com/MrSidims updated https://github.com/llvm/llvm-project/pull/193307

>From cd563c7979222398413700bb4252226654ac24bb Mon Sep 17 00:00:00 2001
From: Dmitry Sidorov <Dmitry.Sidorov at amd.com>
Date: Tue, 21 Apr 2026 14:39:11 -0500
Subject: [PATCH 1/3] [SPIR-V] Add SPV_AMD_weak_linkage extension

Spec is available here:
https://github.com/KhronosGroup/SPIRV-Registry/pull/401
---
 llvm/docs/SPIRVUsage.rst                      |  2 ++
 llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp    |  4 ++-
 llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp |  2 ++
 .../lib/Target/SPIRV/SPIRVSymbolicOperands.td |  2 ++
 llvm/lib/Target/SPIRV/SPIRVUtils.cpp          |  4 +++
 .../CodeGen/SPIRV/linkage/weak-linkage.ll     | 32 +++++++++++++++++++
 6 files changed, 45 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/CodeGen/SPIRV/linkage/weak-linkage.ll

diff --git a/llvm/docs/SPIRVUsage.rst b/llvm/docs/SPIRVUsage.rst
index 75a477b86da05..3ce35742ac4ff 100644
--- a/llvm/docs/SPIRVUsage.rst
+++ b/llvm/docs/SPIRVUsage.rst
@@ -223,6 +223,8 @@ Below is a list of supported SPIR-V extensions, sorted alphabetically by their e
      - Adds instructions for dot product operations on integer vectors with optional accumulation. Integer vectors includes 4-component vector of 8-bit integers and 4-component vectors of 8-bit integers packed into 32-bit integers.
    * - ``SPV_KHR_linkonce_odr``
      - Allows to use the LinkOnceODR linkage type that lets a function or global variable to be merged with other functions or global variables of the same name when linkage occurs.
+   * - ``SPV_AMD_weak_linkage``
+     - Allows to use the Weak linkage type that lets a function or global variable to be replaced by a definition with Export linkage from another module during linking.
    * - ``SPV_KHR_no_integer_wrap_decoration``
      - Adds decorations to indicate that a given instruction does not cause integer wrapping.
    * - ``SPV_KHR_shader_clock``
diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
index 734a03ff60141..3d13cc01a3c18 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
@@ -176,7 +176,9 @@ static const StringMap<SPIRV::Extension::Extension> SPIRVExtensionMap = {
     {"SPV_EXT_image_raw10_raw12",
      SPIRV::Extension::Extension::SPV_EXT_image_raw10_raw12},
     {"SPV_INTEL_unstructured_loop_controls",
-     SPIRV::Extension::Extension::SPV_INTEL_unstructured_loop_controls}};
+     SPIRV::Extension::Extension::SPV_INTEL_unstructured_loop_controls},
+    {"SPV_AMD_weak_linkage",
+     SPIRV::Extension::Extension::SPV_AMD_weak_linkage}};
 
 bool SPIRVExtensionsParser::parse(cl::Option &O, StringRef ArgName,
                                   StringRef ArgValue, ExtensionSet &Vals) {
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index 1f7c66bb352ba..a216205a13ad6 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -1014,6 +1014,8 @@ static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex,
         static_cast<SPIRV::LinkageType::LinkageType>(LinkageOp);
     if (LnkType == SPIRV::LinkageType::LinkOnceODR)
       Reqs.addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
+    else if (LnkType == SPIRV::LinkageType::Weak)
+      Reqs.addExtension(SPIRV::Extension::SPV_AMD_weak_linkage);
   } else if (Dec == SPIRV::Decoration::CacheControlLoadINTEL ||
              Dec == SPIRV::Decoration::CacheControlStoreINTEL) {
     Reqs.addExtension(SPIRV::Extension::SPV_INTEL_cache_controls);
diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
index 56608a80f4b23..cd52181bfc436 100644
--- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
+++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
@@ -398,6 +398,7 @@ defm SPV_EXT_image_raw10_raw12 :ExtensionOperand<133, [EnvOpenCL, EnvVulkan]>;
 defm SPV_ALTERA_arbitrary_precision_floating_point: ExtensionOperand<134, [EnvOpenCL]>;
 defm SPV_KHR_fma : ExtensionOperand<135, [EnvVulkan, EnvOpenCL]>;
 defm SPV_INTEL_masked_gather_scatter : ExtensionOperand<136, [EnvOpenCL]>;
+defm SPV_AMD_weak_linkage : ExtensionOperand<137, [EnvOpenCL]>;
 
 //===----------------------------------------------------------------------===//
 // Multiclass used to define Capabilities enum values and at the same time
@@ -1258,6 +1259,7 @@ multiclass LinkageTypeOperand<bits<32> value, list<Capability> reqCapabilities>
 defm Export : LinkageTypeOperand<0, [Linkage]>;
 defm Import : LinkageTypeOperand<1, [Linkage]>;
 defm LinkOnceODR : LinkageTypeOperand<2, [Linkage]>;
+defm Weak : LinkageTypeOperand<3, [Linkage]>;
 
 //===----------------------------------------------------------------------===//
 // Multiclass used to define AccessQualifier enum values and at the same time
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
index f8e3e27ca289b..2bcbb8e492b2a 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
@@ -1221,6 +1221,10 @@ getSpirvLinkageTypeFor(const SPIRVSubtarget &ST, const GlobalValue &GV) {
       ST.canUseExtension(SPIRV::Extension::SPV_KHR_linkonce_odr))
     return SPIRV::LinkageType::LinkOnceODR;
 
+  if (GV.hasWeakLinkage() &&
+      ST.canUseExtension(SPIRV::Extension::SPV_AMD_weak_linkage))
+    return SPIRV::LinkageType::Weak;
+
   return SPIRV::LinkageType::Export;
 }
 
diff --git a/llvm/test/CodeGen/SPIRV/linkage/weak-linkage.ll b/llvm/test/CodeGen/SPIRV/linkage/weak-linkage.ll
new file mode 100644
index 0000000000000..f6627a1e22337
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/linkage/weak-linkage.ll
@@ -0,0 +1,32 @@
+; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_AMD_weak_linkage %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV-EXT
+; RUNx: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_AMD_weak_linkage %s -o - -filetype=obj | spirv-val %}
+
+; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-SPIRV-EXT: Capability Linkage
+; CHECK-SPIRV-EXT: Extension "SPV_AMD_weak_linkage"
+; CHECK-SPIRV-EXT-DAG: OpDecorate %[[#]] LinkageAttributes "GV" Weak
+; CHECK-SPIRV-EXT-DAG: OpDecorate %[[#]] LinkageAttributes "square" Weak
+
+; CHECK-SPIRV-NOT: OpExtension "SPV_AMD_weak_linkage"
+; CHECK-SPIRV-NOT: OpDecorate %[[#]] LinkageAttributes "GV" Weak
+; CHECK-SPIRV-NOT: OpDecorate %[[#]] LinkageAttributes "square" Weak
+
+ at GV = weak addrspace(1) global [3 x i32] zeroinitializer, align 4
+
+define spir_kernel void @k() {
+entry:
+  %call = call spir_func i32 @square(i32 2)
+  ret void
+}
+
+define weak dso_local spir_func i32 @square(i32 %in) {
+entry:
+  %in.addr = alloca i32, align 4
+  store i32 %in, ptr %in.addr, align 4
+  %0 = load i32, ptr %in.addr, align 4
+  %1 = load i32, ptr %in.addr, align 4
+  %mul = mul nsw i32 %0, %1
+  ret i32 %mul
+}

>From 3b3772627ab3cc9094e1cdfb024d0e9ae89a5501 Mon Sep 17 00:00:00 2001
From: Dmitry Sidorov <Dmitry.Sidorov at amd.com>
Date: Tue, 21 Apr 2026 15:12:46 -0500
Subject: [PATCH 2/3] shorten the test add verify

---
 llvm/test/CodeGen/SPIRV/linkage/weak-linkage.ll | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/llvm/test/CodeGen/SPIRV/linkage/weak-linkage.ll b/llvm/test/CodeGen/SPIRV/linkage/weak-linkage.ll
index f6627a1e22337..6d0af9173391b 100644
--- a/llvm/test/CodeGen/SPIRV/linkage/weak-linkage.ll
+++ b/llvm/test/CodeGen/SPIRV/linkage/weak-linkage.ll
@@ -1,7 +1,7 @@
-; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_AMD_weak_linkage %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV-EXT
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_AMD_weak_linkage %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV-EXT
 ; RUNx: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_AMD_weak_linkage %s -o - -filetype=obj | spirv-val %}
 
-; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
 ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
 
 ; CHECK-SPIRV-EXT: Capability Linkage
@@ -23,10 +23,6 @@ entry:
 
 define weak dso_local spir_func i32 @square(i32 %in) {
 entry:
-  %in.addr = alloca i32, align 4
-  store i32 %in, ptr %in.addr, align 4
-  %0 = load i32, ptr %in.addr, align 4
-  %1 = load i32, ptr %in.addr, align 4
-  %mul = mul nsw i32 %0, %1
+  %mul = mul nsw i32 %in, %in
   ret i32 %mul
 }

>From f865f0067c2578a3a81463e629aa260b4ca00a80 Mon Sep 17 00:00:00 2001
From: Dmitry Sidorov <Dmitry.Sidorov at amd.com>
Date: Wed, 22 Apr 2026 04:59:08 -0500
Subject: [PATCH 3/3] add check no ext

---
 llvm/test/CodeGen/SPIRV/linkage/weak-linkage.ll | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/llvm/test/CodeGen/SPIRV/linkage/weak-linkage.ll b/llvm/test/CodeGen/SPIRV/linkage/weak-linkage.ll
index 6d0af9173391b..be07ebed32548 100644
--- a/llvm/test/CodeGen/SPIRV/linkage/weak-linkage.ll
+++ b/llvm/test/CodeGen/SPIRV/linkage/weak-linkage.ll
@@ -12,6 +12,8 @@
 ; CHECK-SPIRV-NOT: OpExtension "SPV_AMD_weak_linkage"
 ; CHECK-SPIRV-NOT: OpDecorate %[[#]] LinkageAttributes "GV" Weak
 ; CHECK-SPIRV-NOT: OpDecorate %[[#]] LinkageAttributes "square" Weak
+; CHECK-SPIRV-DAG: OpDecorate %[[#]] LinkageAttributes "GV" Export
+; CHECK-SPIRV-DAG: OpDecorate %[[#]] LinkageAttributes "square" Export
 
 @GV = weak addrspace(1) global [3 x i32] zeroinitializer, align 4
 



More information about the llvm-commits mailing list