Skip to content

Commit a00b0bb

Browse files
committed
[MLIR][mlir-link] Add option to sort output symbols by name
1 parent 6aabc44 commit a00b0bb

File tree

5 files changed

+45
-3
lines changed

5 files changed

+45
-3
lines changed

mlir/include/mlir/Linker/Linker.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class Linker {
6464

6565
/// Perform linking and materialization in the destination module.
6666
/// Returns the linked module.
67-
OwningOpRef<ModuleOp> link();
67+
OwningOpRef<ModuleOp> link(bool sortSymbols = false);
6868

6969
MLIRContext *getContext() { return context; }
7070

mlir/include/mlir/Linker/LinkerInterface.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ struct SymbolLinkerInterface : LinkerInterface {
139139
/// Determines if the given operation is eligible for linking.
140140
virtual bool canBeLinked(Operation *op) const = 0;
141141

142+
/// Returns the symbol for the given operation.
143+
virtual StringRef getSymbol(Operation *op) const = 0;
144+
142145
/// Checks if an operation conflicts with existing linked operations.
143146
virtual ConflictPair findConflict(Operation *src) const = 0;
144147

mlir/lib/Dialect/LLVMIR/IR/LLVMLinkerInterface.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ struct LLVMSymbolLinkerInterface
217217
return isa<LLVM::GlobalOp>(op) || isa<LLVM::LLVMFuncOp>(op);
218218
}
219219

220+
StringRef getSymbol(Operation *op) const override { return symbol(op); }
221+
220222
ConflictPair findConflict(Operation *src) const override {
221223
assert(canBeLinked(src) && "expected linkable operation");
222224

mlir/lib/Linker/Linker.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,33 @@ LogicalResult Linker::process(ModuleOp src, unsigned flags) {
6969
return iface->process(src, flags);
7070
}
7171

72-
OwningOpRef<ModuleOp> Linker::link() {
72+
OwningOpRef<ModuleOp> Linker::link(bool sortSymbols) {
7373
ModuleOp mod = composite.get();
7474
if (failed(getModuleLinkerInterface(mod)->link(mod)))
7575
return nullptr;
76+
77+
if (sortSymbols) {
78+
std::vector<Operation *> symbols;
79+
80+
mod->walk([&](Operation *op) {
81+
if (auto iface = dyn_cast<SymbolLinkerInterface>(op->getDialect())) {
82+
if (iface->canBeLinked(op)) {
83+
symbols.push_back(op);
84+
}
85+
}
86+
});
87+
88+
llvm::stable_sort(symbols, [](Operation *lhs, Operation *rhs) {
89+
auto lhsSym = cast<SymbolLinkerInterface>(lhs->getDialect());
90+
auto rhsSym = cast<SymbolLinkerInterface>(rhs->getDialect());
91+
return lhsSym->getSymbol(lhs) < rhsSym->getSymbol(rhs);
92+
});
93+
94+
for (Operation *symbol : llvm::reverse(symbols)) {
95+
symbol->moveBefore(&mod.front());
96+
}
97+
}
98+
7699
return std::move(composite);
77100
}
78101

mlir/lib/Tools/mlir-link/MlirLinkMain.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,13 @@ struct LinkerCLOptions : public LinkerOptions {
6969
}
7070
StringRef outputSplitMarker() const { return outputSplitMarkerFlag; }
7171

72+
/// Sort symbols in the output module.
73+
LinkerCLOptions &sortSymbols(bool sort) {
74+
sortSymbolsFlag = sort;
75+
return *this;
76+
}
77+
bool shouldSortSymbols() const { return sortSymbolsFlag; }
78+
7279
/// Creates and initializes a LinkerOptions from command line options.
7380
/// These options are static but use ExternalStorage to initialize the
7481
/// members of the LinkerOptions class.
@@ -104,6 +111,10 @@ struct LinkerCLOptions : public LinkerOptions {
104111
}),
105112
cl::location(splitInputFileFlag), cl::init(""), cl::cat(getCategory()));
106113

114+
static cl::opt<bool, /*ExternalStorage=*/true> clSortSymbols(
115+
"sort-symbols", cl::desc("Sort symbols in the output module"),
116+
cl::location(sortSymbolsFlag), cl::init(false), cl::cat(getCategory()));
117+
107118
static cl::opt<std::string, /*ExternalStorage=*/true> clOutputSplitMarker(
108119
"output-split-marker",
109120
cl::desc("Split marker to use for merging the ouput"),
@@ -136,6 +147,9 @@ struct LinkerCLOptions : public LinkerOptions {
136147
/// Show the registered dialects before trying to load the input file.
137148
bool showDialectsFlag = false;
138149

150+
/// Sort symbols in the output module.
151+
bool sortSymbolsFlag = false;
152+
139153
/// Split the input file based on the given marker into chunks and process
140154
/// each chunk independently. Input is not split if empty.
141155
std::string splitInputFileFlag = "";
@@ -265,7 +279,7 @@ LogicalResult mlir::MlirLinkMain(int argc, char **argv,
265279
if (failed(proc.linkFiles(options.inputFiles)))
266280
return failure();
267281

268-
OwningOpRef<ModuleOp> composite = linker.link();
282+
OwningOpRef<ModuleOp> composite = linker.link(options.shouldSortSymbols());
269283
if (failed(verify(composite.get(), true))) {
270284
return composite->emitError("verification after linking failed");
271285
}

0 commit comments

Comments
 (0)