Skip to content

Commit 568ce76

Browse files
[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.
1 parent 3a04e01 commit 568ce76

File tree

5 files changed

+279
-1
lines changed

5 files changed

+279
-1
lines changed

mlir/include/mlir/Dialect/LLVMIR/Transforms/Passes.td

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef MLIR_DIALECT_LLVMIR_TRANSFORMS_PASSES
1010
#define MLIR_DIALECT_LLVMIR_TRANSFORMS_PASSES
1111

12+
include "mlir/Dialect/LLVMIR/LLVMOps.td"
1213
include "mlir/Pass/PassBase.td"
1314

1415
def LLVMAddComdats : Pass<"llvm-add-comdats", "::mlir::ModuleOp"> {
@@ -45,6 +46,24 @@ def LLVMRequestCWrappersPass
4546
}];
4647
}
4748

49+
def LLVMUseDefaultVisibilityPass
50+
: Pass<"llvm-use-default-visibility", "::mlir::ModuleOp"> {
51+
let summary =
52+
"Update default visibility of all global values and function definitions";
53+
let description = [{
54+
Update the default visibility of all global values and function definitions
55+
to `visibility`, as with -fvisibility=(hidden|protected).
56+
}];
57+
let options =
58+
[Option<"useVisibility", "visibility", "::mlir::LLVM::Visibility",
59+
/*default=*/"::mlir::LLVM::Visibility::Default",
60+
"Visibility to use in place of default.", [{::llvm::cl::values(
61+
clEnumValN(::mlir::LLVM::Visibility::Hidden, "hidden", "Hidden"),
62+
clEnumValN(::mlir::LLVM::Visibility::Protected, "protected", "Protected")
63+
)}]>,
64+
];
65+
}
66+
4867
def NVVMOptimizeForTargetPass : Pass<"llvm-optimize-for-nvvm-target"> {
4968
let summary = "Optimize NVVM IR";
5069
}
@@ -56,7 +75,7 @@ def DIScopeForLLVMFuncOpPass : Pass<"ensure-debug-info-scope-on-llvm-func", "::m
5675
emitting line tables from MLIR FileLocCol locations.
5776

5877
This is not intended to be a proper replacement for frontends to emit
59-
complete debug informations, however it is a convenient way to get line
78+
complete debug information, however it is a convenient way to get line
6079
tables for debugging purposes. This allow to step trough in a debugger
6180
line-by-line or get a backtrace with line numbers.
6281
}];
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//===- UseDefaultVisibilityPass.h - Update default visibility -*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef MLIR_DIALECT_LLVMIR_TRANSFORMS_USEDEFAULTVISIBILITYPASS_H
10+
#define MLIR_DIALECT_LLVMIR_TRANSFORMS_USEDEFAULTVISIBILITYPASS_H
11+
12+
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
13+
14+
namespace mlir {
15+
class Pass;
16+
17+
namespace LLVM {
18+
19+
#define GEN_PASS_DECL_LLVMUSEDEFAULTVISIBILITYPASS
20+
#include "mlir/Dialect/LLVMIR/Transforms/Passes.h.inc"
21+
22+
} // namespace LLVM
23+
} // namespace mlir
24+
25+
#endif // MLIR_DIALECT_LLVMIR_TRANSFORMS_USEDEFAULTVISIBILITYPASS_H

mlir/lib/Dialect/LLVMIR/Transforms/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ add_mlir_dialect_library(MLIRLLVMIRTransforms
77
LegalizeForExport.cpp
88
OptimizeForNVVM.cpp
99
RequestCWrappers.cpp
10+
UseDefaultVisibilityPass.cpp
1011

1112
DEPENDS
1213
MLIRLLVMPassIncGen
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//===- UseDefaultVisibilityPass.cpp - Update default visibility -----------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "mlir/Dialect/LLVMIR/Transforms/UseDefaultVisibilityPass.h"
10+
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
11+
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
12+
#include "mlir/Pass/Pass.h"
13+
14+
namespace mlir {
15+
namespace LLVM {
16+
#define GEN_PASS_DEF_LLVMUSEDEFAULTVISIBILITYPASS
17+
#include "mlir/Dialect/LLVMIR/Transforms/Passes.h.inc"
18+
} // namespace LLVM
19+
} // namespace mlir
20+
21+
using namespace mlir;
22+
23+
static void updateVisibility(Operation *op,
24+
LLVM::VisibilityAttr newVisibilityAttr) {
25+
if (auto visibilityAttr =
26+
op->getAttrOfType<LLVM::VisibilityAttr>(LLVM::VisibilityAttr::name)) {
27+
LLVM::Visibility visibility = visibilityAttr.getValue();
28+
if (visibility == LLVM::Visibility::Default) {
29+
op->setAttr(LLVM::VisibilityAttr::name, newVisibilityAttr);
30+
}
31+
}
32+
}
33+
34+
namespace {
35+
class UseDefaultVisibilityPass
36+
: public LLVM::impl::LLVMUseDefaultVisibilityPassBase<
37+
UseDefaultVisibilityPass> {
38+
using Base::Base;
39+
40+
public:
41+
void runOnOperation() override {
42+
LLVM::Visibility useDefaultVisibility = useVisibility.getValue();
43+
Operation *op = getOperation();
44+
MLIRContext *context = op->getContext();
45+
Dialect *llvmDialect = context->getLoadedDialect<LLVM::LLVMDialect>();
46+
auto newVisibilityAttr =
47+
LLVM::VisibilityAttr::get(context, useDefaultVisibility);
48+
op->walk([&](Operation *op) {
49+
if (op->getDialect() == llvmDialect)
50+
updateVisibility(op, newVisibilityAttr);
51+
});
52+
}
53+
};
54+
} // namespace
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
// RUN: mlir-opt --llvm-use-default-visibility=visibility=hidden %s | FileCheck %s --check-prefix=HIDDEN
2+
// RUN: mlir-opt --llvm-use-default-visibility=visibility=protected %s | FileCheck %s --check-prefix=PROTECTED
3+
4+
// Ensure the global function definitions and global values are changed to the specified visibility,
5+
// and only when they have default visibility.
6+
7+
llvm.comdat @llvm_comdat {
8+
llvm.comdat_selector @any any
9+
}
10+
11+
llvm.func @func() {
12+
llvm.return
13+
}
14+
15+
llvm.func @ifunc_resolver() -> !llvm.ptr {
16+
%0 = llvm.mlir.addressof @func : !llvm.ptr
17+
llvm.return %0 : !llvm.ptr
18+
}
19+
20+
// Default visibility
21+
22+
llvm.func @func1() {
23+
llvm.return
24+
}
25+
26+
llvm.mlir.global internal constant @global1(0 : i32) : i32
27+
28+
llvm.mlir.alias external @func1_alias {addr_space = 0 : i32} : !llvm.ptr {
29+
%0 = llvm.mlir.addressof @func1 : !llvm.ptr
30+
llvm.return %0 : !llvm.ptr
31+
}
32+
33+
llvm.func @decl1()
34+
35+
llvm.mlir.global internal constant @comdat1(1 : i64) comdat(@llvm_comdat::@any) : i64
36+
37+
llvm.mlir.ifunc external @ifunc1: !llvm.func<void ()>, !llvm.ptr @ifunc_resolver
38+
39+
// Hidden visibility
40+
41+
llvm.func hidden @func2() {
42+
llvm.return
43+
}
44+
45+
llvm.mlir.global internal hidden constant @global2(1 : i32) : i32
46+
47+
llvm.mlir.alias external hidden @func2_alias {addr_space = 0 : i32} : !llvm.ptr {
48+
%0 = llvm.mlir.addressof @func2 : !llvm.ptr
49+
llvm.return %0 : !llvm.ptr
50+
}
51+
52+
llvm.func hidden @decl2()
53+
54+
llvm.mlir.global internal hidden constant @comdat2(1 : i64) comdat(@llvm_comdat::@any) : i64
55+
56+
llvm.mlir.ifunc external hidden @ifunc2: !llvm.func<void ()>, !llvm.ptr @ifunc_resolver
57+
58+
// Protected visibility
59+
60+
llvm.func protected @func3() {
61+
llvm.return
62+
}
63+
64+
llvm.mlir.global internal protected constant @global3(2 : i32) : i32
65+
66+
llvm.mlir.alias external protected @func3_alias {addr_space = 0 : i32} : !llvm.ptr {
67+
%0 = llvm.mlir.addressof @func3 : !llvm.ptr
68+
llvm.return %0 : !llvm.ptr
69+
}
70+
71+
llvm.func protected @decl3()
72+
73+
llvm.mlir.global internal protected constant @comdat3(1 : i64) comdat(@llvm_comdat::@any) : i64
74+
75+
llvm.mlir.ifunc external protected @ifunc3: !llvm.func<void ()>, !llvm.ptr @ifunc_resolver
76+
77+
// HIDDEN-LABEL: llvm.comdat @llvm_comdat {
78+
// HIDDEN: llvm.comdat_selector @any any
79+
// HIDDEN: }
80+
81+
// HIDDEN-LABEL: llvm.func @func() {
82+
// HIDDEN: llvm.return
83+
// HIDDEN: }
84+
85+
// HIDDEN-LABEL: llvm.func @ifunc_resolver() -> !llvm.ptr {
86+
// HIDDEN: %[[MLIR_0:.*]] = llvm.mlir.addressof @func : !llvm.ptr
87+
// HIDDEN: llvm.return %[[MLIR_0]] : !llvm.ptr
88+
// HIDDEN: }
89+
90+
// HIDDEN-LABEL: llvm.func @func1() {
91+
// HIDDEN: llvm.return
92+
// HIDDEN: }
93+
// HIDDEN: llvm.mlir.global internal constant @global1(0 : i32) {addr_space = 0 : i32} : i32
94+
95+
// HIDDEN-LABEL: llvm.mlir.alias external @func1_alias {addr_space = 0 : i32} : !llvm.ptr {
96+
// HIDDEN: %[[MLIR_0:.*]] = llvm.mlir.addressof @func1 : !llvm.ptr
97+
// HIDDEN: llvm.return %[[MLIR_0]] : !llvm.ptr
98+
// HIDDEN: }
99+
// HIDDEN: llvm.func @decl1()
100+
// HIDDEN: llvm.mlir.global internal constant @comdat1(1 : i64) comdat(@llvm_comdat::@any) {addr_space = 0 : i32} : i64
101+
// HIDDEN: llvm.mlir.ifunc external @ifunc1 : !llvm.func<void ()>, !llvm.ptr @ifunc_resolver
102+
103+
// HIDDEN-LABEL: llvm.func hidden @func2() {
104+
// HIDDEN: llvm.return
105+
// HIDDEN: }
106+
// HIDDEN: llvm.mlir.global internal hidden constant @global2(1 : i32) {addr_space = 0 : i32} : i32
107+
108+
// HIDDEN-LABEL: llvm.mlir.alias external hidden @func2_alias {addr_space = 0 : i32} : !llvm.ptr {
109+
// HIDDEN: %[[MLIR_0:.*]] = llvm.mlir.addressof @func2 : !llvm.ptr
110+
// HIDDEN: llvm.return %[[MLIR_0]] : !llvm.ptr
111+
// HIDDEN: }
112+
// HIDDEN: llvm.func hidden @decl2()
113+
// HIDDEN: llvm.mlir.global internal hidden constant @comdat2(1 : i64) comdat(@llvm_comdat::@any) {addr_space = 0 : i32} : i64
114+
// HIDDEN: llvm.mlir.ifunc external hidden @ifunc2 : !llvm.func<void ()>, !llvm.ptr @ifunc_resolver
115+
116+
// HIDDEN-LABEL: llvm.func protected @func3() {
117+
// HIDDEN: llvm.return
118+
// HIDDEN: }
119+
// HIDDEN: llvm.mlir.global internal protected constant @global3(2 : i32) {addr_space = 0 : i32} : i32
120+
121+
// HIDDEN-LABEL: llvm.mlir.alias external protected @func3_alias {addr_space = 0 : i32} : !llvm.ptr {
122+
// HIDDEN: %[[MLIR_0:.*]] = llvm.mlir.addressof @func3 : !llvm.ptr
123+
// HIDDEN: llvm.return %[[MLIR_0]] : !llvm.ptr
124+
// HIDDEN: }
125+
// HIDDEN: llvm.func protected @decl3()
126+
// HIDDEN: llvm.mlir.global internal protected constant @comdat3(1 : i64) comdat(@llvm_comdat::@any) {addr_space = 0 : i32} : i64
127+
// HIDDEN: llvm.mlir.ifunc external protected @ifunc3 : !llvm.func<void ()>, !llvm.ptr @ifunc_resolver
128+
129+
// PROTECTED-LABEL: llvm.comdat @llvm_comdat {
130+
// PROTECTED: llvm.comdat_selector @any any
131+
// PROTECTED: }
132+
133+
// PROTECTED-LABEL: llvm.func @func() {
134+
// PROTECTED: llvm.return
135+
// PROTECTED: }
136+
137+
// PROTECTED-LABEL: llvm.func @ifunc_resolver() -> !llvm.ptr {
138+
// PROTECTED: %[[MLIR_0:.*]] = llvm.mlir.addressof @func : !llvm.ptr
139+
// PROTECTED: llvm.return %[[MLIR_0]] : !llvm.ptr
140+
// PROTECTED: }
141+
142+
// PROTECTED-LABEL: llvm.func @func1() {
143+
// PROTECTED: llvm.return
144+
// PROTECTED: }
145+
// PROTECTED: llvm.mlir.global internal constant @global1(0 : i32) {addr_space = 0 : i32} : i32
146+
147+
// PROTECTED-LABEL: llvm.mlir.alias external @func1_alias {addr_space = 0 : i32} : !llvm.ptr {
148+
// PROTECTED: %[[MLIR_0:.*]] = llvm.mlir.addressof @func1 : !llvm.ptr
149+
// PROTECTED: llvm.return %[[MLIR_0]] : !llvm.ptr
150+
// PROTECTED: }
151+
// PROTECTED: llvm.func @decl1()
152+
// PROTECTED: llvm.mlir.global internal constant @comdat1(1 : i64) comdat(@llvm_comdat::@any) {addr_space = 0 : i32} : i64
153+
// PROTECTED: llvm.mlir.ifunc external @ifunc1 : !llvm.func<void ()>, !llvm.ptr @ifunc_resolver
154+
155+
// PROTECTED-LABEL: llvm.func hidden @func2() {
156+
// PROTECTED: llvm.return
157+
// PROTECTED: }
158+
// PROTECTED: llvm.mlir.global internal hidden constant @global2(1 : i32) {addr_space = 0 : i32} : i32
159+
160+
// PROTECTED-LABEL: llvm.mlir.alias external hidden @func2_alias {addr_space = 0 : i32} : !llvm.ptr {
161+
// PROTECTED: %[[MLIR_0:.*]] = llvm.mlir.addressof @func2 : !llvm.ptr
162+
// PROTECTED: llvm.return %[[MLIR_0]] : !llvm.ptr
163+
// PROTECTED: }
164+
// PROTECTED: llvm.func hidden @decl2()
165+
// PROTECTED: llvm.mlir.global internal hidden constant @comdat2(1 : i64) comdat(@llvm_comdat::@any) {addr_space = 0 : i32} : i64
166+
// PROTECTED: llvm.mlir.ifunc external hidden @ifunc2 : !llvm.func<void ()>, !llvm.ptr @ifunc_resolver
167+
168+
// PROTECTED-LABEL: llvm.func protected @func3() {
169+
// PROTECTED: llvm.return
170+
// PROTECTED: }
171+
// PROTECTED: llvm.mlir.global internal protected constant @global3(2 : i32) {addr_space = 0 : i32} : i32
172+
173+
// PROTECTED-LABEL: llvm.mlir.alias external protected @func3_alias {addr_space = 0 : i32} : !llvm.ptr {
174+
// PROTECTED: %[[MLIR_0:.*]] = llvm.mlir.addressof @func3 : !llvm.ptr
175+
// PROTECTED: llvm.return %[[MLIR_0]] : !llvm.ptr
176+
// PROTECTED: }
177+
// PROTECTED: llvm.func protected @decl3()
178+
// PROTECTED: llvm.mlir.global internal protected constant @comdat3(1 : i64) comdat(@llvm_comdat::@any) {addr_space = 0 : i32} : i64
179+
// PROTECTED: llvm.mlir.ifunc external protected @ifunc3 : !llvm.func<void ()>, !llvm.ptr @ifunc_resolver

0 commit comments

Comments
 (0)