[Mlir-commits] [mlir] 36b95fa - [mlir][SPIR-V] Add Weak linkage type and SPV_AMD_weak_linkage extension (#195660)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Mon May 4 22:52:44 PDT 2026


Author: Arseniy Obolenskiy
Date: 2026-05-05T07:52:40+02:00
New Revision: 36b95facbc5f2cd6169ccc576fd172417d8acf4e

URL: https://github.com/llvm/llvm-project/commit/36b95facbc5f2cd6169ccc576fd172417d8acf4e
DIFF: https://github.com/llvm/llvm-project/commit/36b95facbc5f2cd6169ccc576fd172417d8acf4e.diff

LOG: [mlir][SPIR-V] Add Weak linkage type and SPV_AMD_weak_linkage extension (#195660)

- add 'Weak' linkage type (SPV_AMD_weak_linkage)
- deduce the Linkage capability and linkage-type extension from
linkage_attributes in UpdateVCE pass

---------

Co-authored-by: Jakub Kuderski <kubakuderski at gmail.com>

Added: 
    mlir/test/Target/SPIRV/linkage-types.mlir

Modified: 
    mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
    mlir/lib/Dialect/SPIRV/Transforms/UpdateVCEPass.cpp
    mlir/test/Dialect/SPIRV/Transforms/vce-deduction.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
index c13d24942a9e9..282195c7a8c87 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
@@ -369,6 +369,7 @@ def SPV_AMD_shader_fragment_mask                 : I32EnumAttrCase<"SPV_AMD_shad
 def SPV_AMD_shader_image_load_store_lod          : I32EnumAttrCase<"SPV_AMD_shader_image_load_store_lod", 2004>;
 def SPV_AMD_texture_gather_bias_lod              : I32EnumAttrCase<"SPV_AMD_texture_gather_bias_lod", 2005>;
 def SPV_AMD_shader_early_and_late_fragment_tests : I32EnumAttrCase<"SPV_AMD_shader_early_and_late_fragment_tests", 2006>;
+def SPV_AMD_weak_linkage                         : I32EnumAttrCase<"SPV_AMD_weak_linkage", 2007>;
 
 def SPV_GOOGLE_decorate_string           : I32EnumAttrCase<"SPV_GOOGLE_decorate_string", 3000>;
 def SPV_GOOGLE_hlsl_functionality1       : I32EnumAttrCase<"SPV_GOOGLE_hlsl_functionality1", 3001>;
@@ -456,7 +457,7 @@ def SPIRV_ExtensionAttr :
       SPV_AMD_gpu_shader_half_float_fetch, SPV_AMD_shader_ballot,
       SPV_AMD_shader_explicit_vertex_parameter, SPV_AMD_shader_fragment_mask,
       SPV_AMD_shader_image_load_store_lod, SPV_AMD_texture_gather_bias_lod,
-      SPV_AMD_shader_early_and_late_fragment_tests,
+      SPV_AMD_shader_early_and_late_fragment_tests, SPV_AMD_weak_linkage,
       SPV_GOOGLE_decorate_string, SPV_GOOGLE_hlsl_functionality1, SPV_GOOGLE_user_type,
       SPV_INTEL_device_side_avc_motion_estimation, SPV_INTEL_media_block_io,
       SPV_INTEL_shader_integer_functions2, SPV_INTEL_subgroups, SPV_INTEL_vector_compute,
@@ -3718,10 +3719,16 @@ def SPIRV_LT_LinkOnceODR : I32EnumAttrCase<"LinkOnceODR", 2> {
     Capability<[SPIRV_C_Linkage]>
   ];
 }
+def SPIRV_LT_Weak        : I32EnumAttrCase<"Weak", 3> {
+  list<Availability> availability = [
+    Extension<[SPV_AMD_weak_linkage]>,
+    Capability<[SPIRV_C_Linkage]>
+  ];
+}
 
 def SPIRV_LinkageTypeAttr :
     SPIRV_I32EnumAttr<"LinkageType", "valid SPIR-V LinkageType", "linkage_type", [
-      SPIRV_LT_Export, SPIRV_LT_Import, SPIRV_LT_LinkOnceODR
+      SPIRV_LT_Export, SPIRV_LT_Import, SPIRV_LT_LinkOnceODR, SPIRV_LT_Weak
     ]>;
 
 def SPIRV_LC_None                      : I32BitEnumAttrCaseNone<"None">;

diff  --git a/mlir/lib/Dialect/SPIRV/Transforms/UpdateVCEPass.cpp b/mlir/lib/Dialect/SPIRV/Transforms/UpdateVCEPass.cpp
index a72d891f3aad6..febfc0f7f57f5 100644
--- a/mlir/lib/Dialect/SPIRV/Transforms/UpdateVCEPass.cpp
+++ b/mlir/lib/Dialect/SPIRV/Transforms/UpdateVCEPass.cpp
@@ -153,6 +153,25 @@ void UpdateVCEPass::runOnOperation() {
     valueTypes.append(op->operand_type_begin(), op->operand_type_end());
     valueTypes.append(op->result_type_begin(), op->result_type_end());
 
+    // Per the SPIR-V spec Decoration table, the `LinkageAttributes` decoration
+    // requires the `Linkage` capability, and specific linkage types pull in
+    // additional extensions (e.g., `LinkOnceODR` -> `SPV_KHR_linkonce_odr`).
+    auto requireLinkage = [&](spirv::LinkageType linkageType) -> LogicalResult {
+      if (auto caps = spirv::getCapabilities(linkageType)) {
+        SmallVector<ArrayRef<spirv::Capability>, 1> capCandidates = {*caps};
+        if (failed(checkAndUpdateCapabilityRequirements(
+                op, targetEnv, capCandidates, deducedCapabilities)))
+          return failure();
+      }
+      if (auto exts = spirv::getExtensions(linkageType)) {
+        SmallVector<ArrayRef<spirv::Extension>, 1> extCandidates = {*exts};
+        if (failed(checkAndUpdateExtensionRequirements(
+                op, targetEnv, extCandidates, deducedExtensions)))
+          return failure();
+      }
+      return success();
+    };
+
     // Special treatment for global variables, whose type requirements are
     // conveyed by type attributes.
     if (auto globalVar = dyn_cast<spirv::GlobalVariableOp>(op)) {
@@ -168,8 +187,17 @@ void UpdateVCEPass::runOnOperation() {
                                                         deducedCapabilities)))
           return WalkResult::interrupt();
       }
+
+      if (auto linkage = globalVar.getLinkageAttributes())
+        if (failed(requireLinkage(linkage->getLinkageType().getValue())))
+          return WalkResult::interrupt();
     }
 
+    if (auto funcOp = dyn_cast<spirv::FuncOp>(op))
+      if (auto linkage = funcOp.getLinkageAttributes())
+        if (failed(requireLinkage(linkage->getLinkageType().getValue())))
+          return WalkResult::interrupt();
+
     // If the op is FunctionLike make sure to process input and result types.
     if (auto funcOpInterface = dyn_cast<FunctionOpInterface>(op)) {
       llvm::append_range(valueTypes, funcOpInterface.getArgumentTypes());

diff  --git a/mlir/test/Dialect/SPIRV/Transforms/vce-deduction.mlir b/mlir/test/Dialect/SPIRV/Transforms/vce-deduction.mlir
index d382ca5691fab..c9f3edc078b85 100644
--- a/mlir/test/Dialect/SPIRV/Transforms/vce-deduction.mlir
+++ b/mlir/test/Dialect/SPIRV/Transforms/vce-deduction.mlir
@@ -303,3 +303,31 @@ spirv.module Physical64 GLSL450 attributes {
   spirv.GlobalVariable @recursive:
     !spirv.ptr<!spirv.struct<rec, (!spirv.ptr<!spirv.struct<rec>, StorageBuffer>)>, StorageBuffer>
 }
+
+// CHECK: requires #spirv.vce<v1.0, [Linkage, Shader, Matrix], [SPV_KHR_linkonce_odr]>
+spirv.module Logical GLSL450 attributes {
+  spirv.target_env = #spirv.target_env<
+    #spirv.vce<v1.5, [Shader, Linkage], [SPV_KHR_linkonce_odr]>,
+    #spirv.resource_limits<>>
+} {
+  spirv.func @linkonce_odr_fn() "None" attributes {
+    linkage_attributes = #spirv.linkage_attributes<
+      linkage_name = "linkonce_odr_fn",
+      linkage_type = <LinkOnceODR>>
+  } {
+    spirv.Return
+  }
+}
+
+// CHECK: requires #spirv.vce<v1.0, [Linkage, Shader, Matrix], [SPV_AMD_weak_linkage]>
+spirv.module Logical GLSL450 attributes {
+  spirv.target_env = #spirv.target_env<
+    #spirv.vce<v1.5, [Shader, Linkage], [SPV_AMD_weak_linkage]>,
+    #spirv.resource_limits<>>
+} {
+  spirv.GlobalVariable @weak_var {
+    linkage_attributes = #spirv.linkage_attributes<
+      linkage_name = "weak_var",
+      linkage_type = <Weak>>
+  } : !spirv.ptr<i32, Private>
+}

diff  --git a/mlir/test/Target/SPIRV/linkage-types.mlir b/mlir/test/Target/SPIRV/linkage-types.mlir
new file mode 100644
index 0000000000000..bd9932f42ad6f
--- /dev/null
+++ b/mlir/test/Target/SPIRV/linkage-types.mlir
@@ -0,0 +1,45 @@
+// RUN: mlir-translate --no-implicit-module --test-spirv-roundtrip --split-input-file %s | FileCheck %s
+
+// SPV_AMD_weak_linkage's Weak value isn't in the bundled SPIRV-Tools grammar,
+// so this file skips the spirv-val step that other Target/SPIRV tests run.
+
+spirv.module Logical GLSL450 requires
+    #spirv.vce<v1.0, [Shader, Linkage], [SPV_KHR_linkonce_odr]> {
+  // CHECK: spirv.func @linkonce_odr_fn() "None" attributes
+  // CHECK-SAME: linkage_attributes = #spirv.linkage_attributes<linkage_name = "linkonce_odr_fn", linkage_type = <LinkOnceODR>>
+  spirv.func @linkonce_odr_fn() "None" attributes {
+    linkage_attributes = #spirv.linkage_attributes<
+      linkage_name = "linkonce_odr_fn",
+      linkage_type = <LinkOnceODR>>
+  } {
+    spirv.Return
+  }
+}
+
+// -----
+
+spirv.module Logical GLSL450 requires
+    #spirv.vce<v1.0, [Shader, Linkage], [SPV_AMD_weak_linkage]> {
+  // CHECK: spirv.func @weak_fn() "None" attributes
+  // CHECK-SAME: linkage_attributes = #spirv.linkage_attributes<linkage_name = "weak_fn", linkage_type = <Weak>>
+  spirv.func @weak_fn() "None" attributes {
+    linkage_attributes = #spirv.linkage_attributes<
+      linkage_name = "weak_fn",
+      linkage_type = <Weak>>
+  } {
+    spirv.Return
+  }
+}
+
+// -----
+
+spirv.module Logical GLSL450 requires
+    #spirv.vce<v1.0, [Shader, Linkage], [SPV_AMD_weak_linkage]> {
+  // CHECK: spirv.GlobalVariable @weak_var
+  // CHECK-SAME: linkage_attributes = #spirv.linkage_attributes<linkage_name = "weak_var", linkage_type = <Weak>>
+  spirv.GlobalVariable @weak_var {
+    linkage_attributes = #spirv.linkage_attributes<
+      linkage_name = "weak_var",
+      linkage_type = <Weak>>
+  } : !spirv.ptr<i32, Private>
+}


        


More information about the Mlir-commits mailing list