[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