[llvm] 18cb220 - [SPIR-V] Fix lowering of declarations with hidden visibility (#185029)

via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 11 06:39:38 PDT 2026


Author: Dmitry Sidorov
Date: 2026-03-11T14:39:32+01:00
New Revision: 18cb220146aee00ddb37fa29c45619c4f13034ea

URL: https://github.com/llvm/llvm-project/commit/18cb220146aee00ddb37fa29c45619c4f13034ea
DIFF: https://github.com/llvm/llvm-project/commit/18cb220146aee00ddb37fa29c45619c4f13034ea.diff

LOG: [SPIR-V] Fix lowering of declarations with hidden visibility (#185029)

They should be translated to SPIR-V and have Import linkage (unless they
are Interface variables).

Also add a test for protected visibility, just to make sure, that we are
aligned it its translation.

Added: 
    llvm/test/CodeGen/SPIRV/linkage/hidden-interface-vars.ll
    llvm/test/CodeGen/SPIRV/linkage/hidden-visibility.ll
    llvm/test/CodeGen/SPIRV/linkage/protected-visibility.ll

Modified: 
    llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCAsmInfo.cpp
    llvm/lib/Target/SPIRV/SPIRVUtils.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCAsmInfo.cpp b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCAsmInfo.cpp
index 800bf2297fa7b..3f0a4c2eb5c76 100644
--- a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCAsmInfo.cpp
+++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVMCAsmInfo.cpp
@@ -27,6 +27,9 @@ SPIRVMCAsmInfo::SPIRVMCAsmInfo(const Triple &TT,
   CodePointerSize = 4;
   CommentString = ";";
   HasFunctionAlignment = false;
+
+  HiddenDeclarationVisibilityAttr = HiddenVisibilityAttr = MCSA_Invalid;
+  ProtectedVisibilityAttr = MCSA_Invalid;
 }
 
 bool SPIRVMCAsmInfo::shouldOmitSectionDirective(StringRef SectionName) const {

diff  --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
index 7858f7f932a46..4a25886614098 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
@@ -1197,11 +1197,23 @@ Type *reconstitutePeeledArrayType(Type *Ty) {
 
 std::optional<SPIRV::LinkageType::LinkageType>
 getSpirvLinkageTypeFor(const SPIRVSubtarget &ST, const GlobalValue &GV) {
-  if (GV.hasLocalLinkage() || GV.hasHiddenVisibility())
+  if (GV.hasLocalLinkage())
     return std::nullopt;
 
-  if (GV.isDeclarationForLinker())
+  if (GV.isDeclarationForLinker()) {
+    // Interface variables must not get Import linkage.
+    if (const auto *GVar = dyn_cast<GlobalVariable>(&GV)) {
+      auto SC = addressSpaceToStorageClass(GVar->getAddressSpace(), ST);
+      if (SC == SPIRV::StorageClass::Input ||
+          SC == SPIRV::StorageClass::Output ||
+          SC == SPIRV::StorageClass::PushConstant)
+        return std::nullopt;
+    }
     return SPIRV::LinkageType::Import;
+  }
+
+  if (GV.hasHiddenVisibility())
+    return std::nullopt;
 
   if (GV.hasLinkOnceODRLinkage() &&
       ST.canUseExtension(SPIRV::Extension::SPV_KHR_linkonce_odr))

diff  --git a/llvm/test/CodeGen/SPIRV/linkage/hidden-interface-vars.ll b/llvm/test/CodeGen/SPIRV/linkage/hidden-interface-vars.ll
new file mode 100644
index 0000000000000..4b156bf5cbda9
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/linkage/hidden-interface-vars.ll
@@ -0,0 +1,36 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-vulkan1.3-pixel %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan1.3-pixel %s -o - -filetype=obj | spirv-val --target-env vulkan1.3 %}
+
+; Check that interface variables (Input, Output, PushConstant) do not get
+; Import linkage even when declared as external hidden.
+
+; CHECK-NOT: OpCapability Linkage
+; CHECK-NOT: LinkageAttributes
+
+%struct.PC = type <{ float }>
+
+ at input_var = external hidden addrspace(7) global <4 x float>, !spirv.Decorations !0
+ at output_var = external hidden addrspace(8) global <4 x float>, !spirv.Decorations !2
+ at push_const = external hidden addrspace(13) externally_initialized global %struct.PC, align 1
+
+; CHECK-DAG: %[[#INPUT_TYPE:]] = OpTypePointer Input %[[#FLOAT4:]]
+; CHECK-DAG: %[[#OUTPUT_TYPE:]] = OpTypePointer Output %[[#FLOAT4]]
+; CHECK-DAG: %[[#INPUT_VAR:]] = OpVariable %[[#INPUT_TYPE]] Input
+; CHECK-DAG: %[[#OUTPUT_VAR:]] = OpVariable %[[#OUTPUT_TYPE]] Output
+; CHECK-DAG: %[[#PC_VAR:]] = OpVariable %[[#]] PushConstant
+
+define void @main() #0 {
+entry:
+  %val = load <4 x float>, ptr addrspace(7) @input_var
+  %pc = load float, ptr addrspace(13) @push_const
+  %ins = insertelement <4 x float> %val, float %pc, i32 0
+  store <4 x float> %ins, ptr addrspace(8) @output_var
+  ret void
+}
+
+attributes #0 = { "hlsl.shader"="pixel" }
+
+!0 = !{!1}
+!1 = !{i32 30, i32 0}   ; Location 0
+!2 = !{!3}
+!3 = !{i32 30, i32 1}   ; Location 1

diff  --git a/llvm/test/CodeGen/SPIRV/linkage/hidden-visibility.ll b/llvm/test/CodeGen/SPIRV/linkage/hidden-visibility.ll
new file mode 100644
index 0000000000000..ef0e214544970
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/linkage/hidden-visibility.ll
@@ -0,0 +1,71 @@
+; Check that hidden visibility does not cause a crash and that hidden
+; declarations get Import linkage while hidden definitions do not.
+
+; RUN: split-file %s %t
+
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %t/opencl.ll -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %t/opencl.ll -o - -filetype=obj | spirv-val %}
+
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-vulkan1.3-compute %t/vulkan.ll -o - | FileCheck %s
+; FIXME: re-enable validator check when spirv-val allows Linkage in vulkan env.
+; RUNx: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan1.3-compute %t/vulkan.ll -o - -filetype=obj | spirv-val --target-env vulkan1.3 %}
+
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-vulkan-library %t/vulkan-lib.ll -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-vulkan-library %t/vulkan-lib.ll -o - -filetype=obj | spirv-val %}
+
+; CHECK-DAG: OpName %[[#HIDDEN_HELPER:]] "hidden_helper"
+; CHECK-DAG: OpName %[[#HIDDEN_DEF:]] "hidden_def"
+
+; CHECK-DAG: OpDecorate %[[#HIDDEN_HELPER]] LinkageAttributes "hidden_helper" Import
+; CHECK-NOT: OpDecorate %[[#HIDDEN_DEF]] LinkageAttributes
+
+;--- opencl.ll
+ at hidden_leaf_var = external hidden addrspace(1) global i32
+
+declare hidden spir_func void @hidden_helper(ptr addrspace(1))
+
+define hidden spir_func void @hidden_def(ptr addrspace(1) %x) {
+entry:
+  ret void
+}
+
+define spir_kernel void @test_kernel(ptr addrspace(1) %data) {
+entry:
+  %val = load i32, ptr addrspace(1) @hidden_leaf_var
+  store i32 %val, ptr addrspace(1) %data
+  call spir_func void @hidden_helper(ptr addrspace(1) %data)
+  call spir_func void @hidden_def(ptr addrspace(1) %data)
+  ret void
+}
+
+;--- vulkan.ll
+declare hidden void @hidden_helper()
+
+define hidden void @hidden_def() {
+entry:
+  ret void
+}
+
+define void @main() #0 {
+entry:
+  call void @hidden_helper()
+  call void @hidden_def()
+  ret void
+}
+
+attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
+
+;--- vulkan-lib.ll
+declare hidden void @hidden_helper()
+
+define hidden void @hidden_def() {
+entry:
+  ret void
+}
+
+define void @caller() {
+entry:
+  call void @hidden_helper()
+  call void @hidden_def()
+  ret void
+}

diff  --git a/llvm/test/CodeGen/SPIRV/linkage/protected-visibility.ll b/llvm/test/CodeGen/SPIRV/linkage/protected-visibility.ll
new file mode 100644
index 0000000000000..31bf63e6f3e53
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/linkage/protected-visibility.ll
@@ -0,0 +1,67 @@
+; Check that protected visibility does not cause a crash, that protected
+; declarations get Import linkage, and protected definitions get Export.
+
+; RUN: split-file %s %t
+
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %t/opencl.ll -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %t/opencl.ll -o - -filetype=obj | spirv-val %}
+
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-vulkan1.3-compute %t/vulkan.ll -o - | FileCheck %s
+; FIXME: re-enable validator check when spirv-val allows Linkage in vulkan env.
+; RUNx: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan1.3-compute %t/vulkan.ll -o - -filetype=obj | spirv-val --target-env vulkan1.3 %}
+
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-vulkan-library %t/vulkan-lib.ll -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-vulkan-library %t/vulkan-lib.ll -o - -filetype=obj | spirv-val %}
+
+; CHECK-DAG: OpName %[[#PROTECTED_DECL:]] "protected_decl"
+; CHECK-DAG: OpName %[[#PROTECTED_DEF:]] "protected_def"
+
+; CHECK-DAG: OpDecorate %[[#PROTECTED_DECL]] LinkageAttributes "protected_decl" Import
+; CHECK-DAG: OpDecorate %[[#PROTECTED_DEF]] LinkageAttributes "protected_def" Export
+
+;--- opencl.ll
+declare protected spir_func void @protected_decl(ptr addrspace(1))
+
+define protected spir_func void @protected_def(ptr addrspace(1) %x) {
+entry:
+  ret void
+}
+
+define spir_kernel void @test_kernel(ptr addrspace(1) %data) {
+entry:
+  call spir_func void @protected_decl(ptr addrspace(1) %data)
+  call spir_func void @protected_def(ptr addrspace(1) %data)
+  ret void
+}
+
+;--- vulkan.ll
+declare protected void @protected_decl()
+
+define protected void @protected_def() {
+entry:
+  ret void
+}
+
+define void @main() #0 {
+entry:
+  call void @protected_decl()
+  call void @protected_def()
+  ret void
+}
+
+attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
+
+;--- vulkan-lib.ll
+declare protected void @protected_decl()
+
+define protected void @protected_def() {
+entry:
+  ret void
+}
+
+define void @caller() {
+entry:
+  call void @protected_decl()
+  call void @protected_def()
+  ret void
+}


        


More information about the llvm-commits mailing list