[Mlir-commits] [mlir] 568ce76 - [MLIR][LLVM] Add pass to update ops with default visibility (#171727)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Fri Dec 12 06:49:24 PST 2025


Author: Asher Mancinelli
Date: 2025-12-12T06:49:20-08:00
New Revision: 568ce76c6e8134ab9b631e357c134091d2fd4aa8

URL: https://github.com/llvm/llvm-project/commit/568ce76c6e8134ab9b631e357c134091d2fd4aa8
DIFF: https://github.com/llvm/llvm-project/commit/568ce76c6e8134ab9b631e357c134091d2fd4aa8.diff

LOG: [MLIR][LLVM] Add pass to update ops with default visibility (#171727)

To support the `-fvisibility=...` option in Flang, we need a pass to
rewrite all the global definitions in the LLVM dialect that have the
default visibility to have the specified visibility. This change adds
such a pass.

Note that I did not add an option for `visiblity=default`; I believe
this makes sense for compiler drivers since users may want to tack an
option on at the end of a compile line to override earlier options, but
I don't think it makes sense for this pass to accept
`visibility=default`--it would just be an early exit IIUC.

Added: 
    mlir/include/mlir/Dialect/LLVMIR/Transforms/UseDefaultVisibilityPass.h
    mlir/lib/Dialect/LLVMIR/Transforms/UseDefaultVisibilityPass.cpp
    mlir/test/Dialect/LLVMIR/use-default-visibility.mlir

Modified: 
    mlir/include/mlir/Dialect/LLVMIR/Transforms/Passes.td
    mlir/lib/Dialect/LLVMIR/Transforms/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/LLVMIR/Transforms/Passes.td b/mlir/include/mlir/Dialect/LLVMIR/Transforms/Passes.td
index 961909d5c8d27..eaffd2978047b 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/Transforms/Passes.td
@@ -9,6 +9,7 @@
 #ifndef MLIR_DIALECT_LLVMIR_TRANSFORMS_PASSES
 #define MLIR_DIALECT_LLVMIR_TRANSFORMS_PASSES
 
+include "mlir/Dialect/LLVMIR/LLVMOps.td"
 include "mlir/Pass/PassBase.td"
 
 def LLVMAddComdats : Pass<"llvm-add-comdats", "::mlir::ModuleOp"> {
@@ -45,6 +46,24 @@ def LLVMRequestCWrappersPass
   }];
 }
 
+def LLVMUseDefaultVisibilityPass
+    : Pass<"llvm-use-default-visibility", "::mlir::ModuleOp"> {
+  let summary =
+      "Update default visibility of all global values and function definitions";
+  let description = [{
+    Update the default visibility of all global values and function definitions
+    to `visibility`, as with -fvisibility=(hidden|protected).
+  }];
+  let options =
+      [Option<"useVisibility", "visibility", "::mlir::LLVM::Visibility",
+              /*default=*/"::mlir::LLVM::Visibility::Default",
+              "Visibility to use in place of default.", [{::llvm::cl::values(
+	     clEnumValN(::mlir::LLVM::Visibility::Hidden, "hidden", "Hidden"),
+	     clEnumValN(::mlir::LLVM::Visibility::Protected, "protected", "Protected")
+	   )}]>,
+  ];
+}
+
 def NVVMOptimizeForTargetPass : Pass<"llvm-optimize-for-nvvm-target"> {
   let summary = "Optimize NVVM IR";
 }
@@ -56,7 +75,7 @@ def DIScopeForLLVMFuncOpPass : Pass<"ensure-debug-info-scope-on-llvm-func", "::m
     emitting line tables from MLIR FileLocCol locations.
 
     This is not intended to be a proper replacement for frontends to emit
-    complete debug informations, however it is a convenient way to get line
+    complete debug information, however it is a convenient way to get line
     tables for debugging purposes. This allow to step trough in a debugger
     line-by-line or get a backtrace with line numbers.
   }];

diff  --git a/mlir/include/mlir/Dialect/LLVMIR/Transforms/UseDefaultVisibilityPass.h b/mlir/include/mlir/Dialect/LLVMIR/Transforms/UseDefaultVisibilityPass.h
new file mode 100644
index 0000000000000..e77ee8cb5de0b
--- /dev/null
+++ b/mlir/include/mlir/Dialect/LLVMIR/Transforms/UseDefaultVisibilityPass.h
@@ -0,0 +1,25 @@
+//===- UseDefaultVisibilityPass.h - Update default visibility -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_LLVMIR_TRANSFORMS_USEDEFAULTVISIBILITYPASS_H
+#define MLIR_DIALECT_LLVMIR_TRANSFORMS_USEDEFAULTVISIBILITYPASS_H
+
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+
+namespace mlir {
+class Pass;
+
+namespace LLVM {
+
+#define GEN_PASS_DECL_LLVMUSEDEFAULTVISIBILITYPASS
+#include "mlir/Dialect/LLVMIR/Transforms/Passes.h.inc"
+
+} // namespace LLVM
+} // namespace mlir
+
+#endif // MLIR_DIALECT_LLVMIR_TRANSFORMS_USEDEFAULTVISIBILITYPASS_H

diff  --git a/mlir/lib/Dialect/LLVMIR/Transforms/CMakeLists.txt b/mlir/lib/Dialect/LLVMIR/Transforms/CMakeLists.txt
index 37a45d478a1fb..6ffa2d9a8a9e8 100644
--- a/mlir/lib/Dialect/LLVMIR/Transforms/CMakeLists.txt
+++ b/mlir/lib/Dialect/LLVMIR/Transforms/CMakeLists.txt
@@ -7,6 +7,7 @@ add_mlir_dialect_library(MLIRLLVMIRTransforms
   LegalizeForExport.cpp
   OptimizeForNVVM.cpp
   RequestCWrappers.cpp
+  UseDefaultVisibilityPass.cpp
 
   DEPENDS
   MLIRLLVMPassIncGen

diff  --git a/mlir/lib/Dialect/LLVMIR/Transforms/UseDefaultVisibilityPass.cpp b/mlir/lib/Dialect/LLVMIR/Transforms/UseDefaultVisibilityPass.cpp
new file mode 100644
index 0000000000000..767fc0799026b
--- /dev/null
+++ b/mlir/lib/Dialect/LLVMIR/Transforms/UseDefaultVisibilityPass.cpp
@@ -0,0 +1,54 @@
+//===- UseDefaultVisibilityPass.cpp - Update default visibility -----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/LLVMIR/Transforms/UseDefaultVisibilityPass.h"
+#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/Pass/Pass.h"
+
+namespace mlir {
+namespace LLVM {
+#define GEN_PASS_DEF_LLVMUSEDEFAULTVISIBILITYPASS
+#include "mlir/Dialect/LLVMIR/Transforms/Passes.h.inc"
+} // namespace LLVM
+} // namespace mlir
+
+using namespace mlir;
+
+static void updateVisibility(Operation *op,
+                             LLVM::VisibilityAttr newVisibilityAttr) {
+  if (auto visibilityAttr =
+          op->getAttrOfType<LLVM::VisibilityAttr>(LLVM::VisibilityAttr::name)) {
+    LLVM::Visibility visibility = visibilityAttr.getValue();
+    if (visibility == LLVM::Visibility::Default) {
+      op->setAttr(LLVM::VisibilityAttr::name, newVisibilityAttr);
+    }
+  }
+}
+
+namespace {
+class UseDefaultVisibilityPass
+    : public LLVM::impl::LLVMUseDefaultVisibilityPassBase<
+          UseDefaultVisibilityPass> {
+  using Base::Base;
+
+public:
+  void runOnOperation() override {
+    LLVM::Visibility useDefaultVisibility = useVisibility.getValue();
+    Operation *op = getOperation();
+    MLIRContext *context = op->getContext();
+    Dialect *llvmDialect = context->getLoadedDialect<LLVM::LLVMDialect>();
+    auto newVisibilityAttr =
+        LLVM::VisibilityAttr::get(context, useDefaultVisibility);
+    op->walk([&](Operation *op) {
+      if (op->getDialect() == llvmDialect)
+        updateVisibility(op, newVisibilityAttr);
+    });
+  }
+};
+} // namespace

diff  --git a/mlir/test/Dialect/LLVMIR/use-default-visibility.mlir b/mlir/test/Dialect/LLVMIR/use-default-visibility.mlir
new file mode 100644
index 0000000000000..37c75e52debcd
--- /dev/null
+++ b/mlir/test/Dialect/LLVMIR/use-default-visibility.mlir
@@ -0,0 +1,179 @@
+// RUN: mlir-opt --llvm-use-default-visibility=visibility=hidden %s | FileCheck %s --check-prefix=HIDDEN
+// RUN: mlir-opt --llvm-use-default-visibility=visibility=protected %s | FileCheck %s --check-prefix=PROTECTED
+
+// Ensure the global function definitions and global values are changed to the specified visibility,
+// and only when they have default visibility.
+
+llvm.comdat @llvm_comdat {
+  llvm.comdat_selector @any any
+}
+
+llvm.func @func() {
+  llvm.return
+}
+
+llvm.func @ifunc_resolver() -> !llvm.ptr {
+  %0 = llvm.mlir.addressof @func : !llvm.ptr
+  llvm.return %0 : !llvm.ptr
+}
+
+// Default visibility
+
+llvm.func @func1() {
+  llvm.return
+}
+
+llvm.mlir.global internal constant @global1(0 : i32) : i32
+
+llvm.mlir.alias external @func1_alias {addr_space = 0 : i32} : !llvm.ptr {
+  %0 = llvm.mlir.addressof @func1 : !llvm.ptr
+  llvm.return %0 : !llvm.ptr
+}
+
+llvm.func @decl1()
+
+llvm.mlir.global internal constant @comdat1(1 : i64) comdat(@llvm_comdat::@any) : i64
+
+llvm.mlir.ifunc external @ifunc1: !llvm.func<void ()>, !llvm.ptr @ifunc_resolver
+
+// Hidden visibility
+
+llvm.func hidden @func2() {
+  llvm.return
+}
+
+llvm.mlir.global internal hidden constant @global2(1 : i32) : i32
+
+llvm.mlir.alias external hidden @func2_alias {addr_space = 0 : i32} : !llvm.ptr {
+  %0 = llvm.mlir.addressof @func2 : !llvm.ptr
+  llvm.return %0 : !llvm.ptr
+}
+
+llvm.func hidden @decl2()
+
+llvm.mlir.global internal hidden constant @comdat2(1 : i64) comdat(@llvm_comdat::@any) : i64
+
+llvm.mlir.ifunc external hidden @ifunc2: !llvm.func<void ()>, !llvm.ptr @ifunc_resolver
+
+// Protected visibility
+
+llvm.func protected @func3() {
+  llvm.return
+}
+
+llvm.mlir.global internal protected constant @global3(2 : i32) : i32
+
+llvm.mlir.alias external protected @func3_alias {addr_space = 0 : i32} : !llvm.ptr {
+  %0 = llvm.mlir.addressof @func3 : !llvm.ptr
+  llvm.return %0 : !llvm.ptr
+}
+
+llvm.func protected @decl3()
+
+llvm.mlir.global internal protected constant @comdat3(1 : i64) comdat(@llvm_comdat::@any) : i64
+
+llvm.mlir.ifunc external protected @ifunc3: !llvm.func<void ()>, !llvm.ptr @ifunc_resolver
+
+// HIDDEN-LABEL:   llvm.comdat @llvm_comdat {
+// HIDDEN:           llvm.comdat_selector @any any
+// HIDDEN:         }
+
+// HIDDEN-LABEL:   llvm.func @func() {
+// HIDDEN:           llvm.return
+// HIDDEN:         }
+
+// HIDDEN-LABEL:   llvm.func @ifunc_resolver() -> !llvm.ptr {
+// HIDDEN:           %[[MLIR_0:.*]] = llvm.mlir.addressof @func : !llvm.ptr
+// HIDDEN:           llvm.return %[[MLIR_0]] : !llvm.ptr
+// HIDDEN:         }
+
+// HIDDEN-LABEL:   llvm.func @func1() {
+// HIDDEN:           llvm.return
+// HIDDEN:         }
+// HIDDEN:         llvm.mlir.global internal constant @global1(0 : i32) {addr_space = 0 : i32} : i32
+
+// HIDDEN-LABEL:   llvm.mlir.alias external @func1_alias {addr_space = 0 : i32} : !llvm.ptr {
+// HIDDEN:           %[[MLIR_0:.*]] = llvm.mlir.addressof @func1 : !llvm.ptr
+// HIDDEN:           llvm.return %[[MLIR_0]] : !llvm.ptr
+// HIDDEN:         }
+// HIDDEN:         llvm.func @decl1()
+// HIDDEN:         llvm.mlir.global internal constant @comdat1(1 : i64) comdat(@llvm_comdat::@any) {addr_space = 0 : i32} : i64
+// HIDDEN:         llvm.mlir.ifunc external @ifunc1 : !llvm.func<void ()>, !llvm.ptr @ifunc_resolver
+
+// HIDDEN-LABEL:   llvm.func hidden @func2() {
+// HIDDEN:           llvm.return
+// HIDDEN:         }
+// HIDDEN:         llvm.mlir.global internal hidden constant @global2(1 : i32) {addr_space = 0 : i32} : i32
+
+// HIDDEN-LABEL:   llvm.mlir.alias external hidden @func2_alias {addr_space = 0 : i32} : !llvm.ptr {
+// HIDDEN:           %[[MLIR_0:.*]] = llvm.mlir.addressof @func2 : !llvm.ptr
+// HIDDEN:           llvm.return %[[MLIR_0]] : !llvm.ptr
+// HIDDEN:         }
+// HIDDEN:         llvm.func hidden @decl2()
+// HIDDEN:         llvm.mlir.global internal hidden constant @comdat2(1 : i64) comdat(@llvm_comdat::@any) {addr_space = 0 : i32} : i64
+// HIDDEN:         llvm.mlir.ifunc external hidden @ifunc2 : !llvm.func<void ()>, !llvm.ptr @ifunc_resolver
+
+// HIDDEN-LABEL:   llvm.func protected @func3() {
+// HIDDEN:           llvm.return
+// HIDDEN:         }
+// HIDDEN:         llvm.mlir.global internal protected constant @global3(2 : i32) {addr_space = 0 : i32} : i32
+
+// HIDDEN-LABEL:   llvm.mlir.alias external protected @func3_alias {addr_space = 0 : i32} : !llvm.ptr {
+// HIDDEN:           %[[MLIR_0:.*]] = llvm.mlir.addressof @func3 : !llvm.ptr
+// HIDDEN:           llvm.return %[[MLIR_0]] : !llvm.ptr
+// HIDDEN:         }
+// HIDDEN:         llvm.func protected @decl3()
+// HIDDEN:         llvm.mlir.global internal protected constant @comdat3(1 : i64) comdat(@llvm_comdat::@any) {addr_space = 0 : i32} : i64
+// HIDDEN:         llvm.mlir.ifunc external protected @ifunc3 : !llvm.func<void ()>, !llvm.ptr @ifunc_resolver
+
+// PROTECTED-LABEL:   llvm.comdat @llvm_comdat {
+// PROTECTED:           llvm.comdat_selector @any any
+// PROTECTED:         }
+
+// PROTECTED-LABEL:   llvm.func @func() {
+// PROTECTED:           llvm.return
+// PROTECTED:         }
+
+// PROTECTED-LABEL:   llvm.func @ifunc_resolver() -> !llvm.ptr {
+// PROTECTED:           %[[MLIR_0:.*]] = llvm.mlir.addressof @func : !llvm.ptr
+// PROTECTED:           llvm.return %[[MLIR_0]] : !llvm.ptr
+// PROTECTED:         }
+
+// PROTECTED-LABEL:   llvm.func @func1() {
+// PROTECTED:           llvm.return
+// PROTECTED:         }
+// PROTECTED:         llvm.mlir.global internal constant @global1(0 : i32) {addr_space = 0 : i32} : i32
+
+// PROTECTED-LABEL:   llvm.mlir.alias external @func1_alias {addr_space = 0 : i32} : !llvm.ptr {
+// PROTECTED:           %[[MLIR_0:.*]] = llvm.mlir.addressof @func1 : !llvm.ptr
+// PROTECTED:           llvm.return %[[MLIR_0]] : !llvm.ptr
+// PROTECTED:         }
+// PROTECTED:         llvm.func @decl1()
+// PROTECTED:         llvm.mlir.global internal constant @comdat1(1 : i64) comdat(@llvm_comdat::@any) {addr_space = 0 : i32} : i64
+// PROTECTED:         llvm.mlir.ifunc external @ifunc1 : !llvm.func<void ()>, !llvm.ptr @ifunc_resolver
+
+// PROTECTED-LABEL:   llvm.func hidden @func2() {
+// PROTECTED:           llvm.return
+// PROTECTED:         }
+// PROTECTED:         llvm.mlir.global internal hidden constant @global2(1 : i32) {addr_space = 0 : i32} : i32
+
+// PROTECTED-LABEL:   llvm.mlir.alias external hidden @func2_alias {addr_space = 0 : i32} : !llvm.ptr {
+// PROTECTED:           %[[MLIR_0:.*]] = llvm.mlir.addressof @func2 : !llvm.ptr
+// PROTECTED:           llvm.return %[[MLIR_0]] : !llvm.ptr
+// PROTECTED:         }
+// PROTECTED:         llvm.func hidden @decl2()
+// PROTECTED:         llvm.mlir.global internal hidden constant @comdat2(1 : i64) comdat(@llvm_comdat::@any) {addr_space = 0 : i32} : i64
+// PROTECTED:         llvm.mlir.ifunc external hidden @ifunc2 : !llvm.func<void ()>, !llvm.ptr @ifunc_resolver
+
+// PROTECTED-LABEL:   llvm.func protected @func3() {
+// PROTECTED:           llvm.return
+// PROTECTED:         }
+// PROTECTED:         llvm.mlir.global internal protected constant @global3(2 : i32) {addr_space = 0 : i32} : i32
+
+// PROTECTED-LABEL:   llvm.mlir.alias external protected @func3_alias {addr_space = 0 : i32} : !llvm.ptr {
+// PROTECTED:           %[[MLIR_0:.*]] = llvm.mlir.addressof @func3 : !llvm.ptr
+// PROTECTED:           llvm.return %[[MLIR_0]] : !llvm.ptr
+// PROTECTED:         }
+// PROTECTED:         llvm.func protected @decl3()
+// PROTECTED:         llvm.mlir.global internal protected constant @comdat3(1 : i64) comdat(@llvm_comdat::@any) {addr_space = 0 : i32} : i64
+// PROTECTED:         llvm.mlir.ifunc external protected @ifunc3 : !llvm.func<void ()>, !llvm.ptr @ifunc_resolver


        


More information about the Mlir-commits mailing list