Skip to content

Commit 293c521

Browse files
committed
[mlir][NFC] Wrap the cl::opts in JitRunner within a struct to avoid global initializers.
Summary: This avoids the need for having global static initializers within the JITRunner support library, and only constructs the options when the runner is invoked. Differential Revision: https://reviews.llvm.org/D77760
1 parent 7baad0c commit 293c521

File tree

1 file changed

+86
-76
lines changed

1 file changed

+86
-76
lines changed

mlir/lib/Support/JitRunner.cpp

Lines changed: 86 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -41,54 +41,58 @@
4141
using namespace mlir;
4242
using llvm::Error;
4343

44-
static llvm::cl::opt<std::string> inputFilename(llvm::cl::Positional,
45-
llvm::cl::desc("<input file>"),
46-
llvm::cl::init("-"));
47-
static llvm::cl::opt<std::string>
48-
mainFuncName("e", llvm::cl::desc("The function to be called"),
49-
llvm::cl::value_desc("<function name>"),
50-
llvm::cl::init("main"));
51-
static llvm::cl::opt<std::string> mainFuncType(
52-
"entry-point-result",
53-
llvm::cl::desc("Textual description of the function type to be called"),
54-
llvm::cl::value_desc("f32 | void"), llvm::cl::init("f32"));
55-
56-
static llvm::cl::OptionCategory optFlags("opt-like flags");
57-
58-
// CLI list of pass information
59-
static llvm::cl::list<const llvm::PassInfo *, bool, llvm::PassNameParser>
60-
llvmPasses(llvm::cl::desc("LLVM optimizing passes to run"),
61-
llvm::cl::cat(optFlags));
62-
63-
// CLI variables for -On options.
64-
static llvm::cl::opt<bool>
65-
optO0("O0", llvm::cl::desc("Run opt passes and codegen at O0"),
66-
llvm::cl::cat(optFlags));
67-
static llvm::cl::opt<bool>
68-
optO1("O1", llvm::cl::desc("Run opt passes and codegen at O1"),
69-
llvm::cl::cat(optFlags));
70-
static llvm::cl::opt<bool>
71-
optO2("O2", llvm::cl::desc("Run opt passes and codegen at O2"),
72-
llvm::cl::cat(optFlags));
73-
static llvm::cl::opt<bool>
74-
optO3("O3", llvm::cl::desc("Run opt passes and codegen at O3"),
75-
llvm::cl::cat(optFlags));
76-
77-
static llvm::cl::OptionCategory clOptionsCategory("linking options");
78-
static llvm::cl::list<std::string>
79-
clSharedLibs("shared-libs", llvm::cl::desc("Libraries to link dynamically"),
80-
llvm::cl::ZeroOrMore, llvm::cl::MiscFlags::CommaSeparated,
81-
llvm::cl::cat(clOptionsCategory));
82-
83-
// CLI variables for debugging.
84-
static llvm::cl::opt<bool> dumpObjectFile(
85-
"dump-object-file",
86-
llvm::cl::desc("Dump JITted-compiled object to file specified with "
87-
"-object-filename (<input file>.o by default)."));
88-
89-
static llvm::cl::opt<std::string> objectFilename(
90-
"object-filename",
91-
llvm::cl::desc("Dump JITted-compiled object to file <input file>.o"));
44+
namespace {
45+
/// This options struct prevents the need for global static initializers, and
46+
/// is only initialized if the JITRunner is invoked.
47+
struct Options {
48+
llvm::cl::opt<std::string> inputFilename{llvm::cl::Positional,
49+
llvm::cl::desc("<input file>"),
50+
llvm::cl::init("-")};
51+
llvm::cl::opt<std::string> mainFuncName{
52+
"e", llvm::cl::desc("The function to be called"),
53+
llvm::cl::value_desc("<function name>"), llvm::cl::init("main")};
54+
llvm::cl::opt<std::string> mainFuncType{
55+
"entry-point-result",
56+
llvm::cl::desc("Textual description of the function type to be called"),
57+
llvm::cl::value_desc("f32 | void"), llvm::cl::init("f32")};
58+
59+
llvm::cl::OptionCategory optFlags{"opt-like flags"};
60+
61+
// CLI list of pass information
62+
llvm::cl::list<const llvm::PassInfo *, bool, llvm::PassNameParser> llvmPasses{
63+
llvm::cl::desc("LLVM optimizing passes to run"), llvm::cl::cat(optFlags)};
64+
65+
// CLI variables for -On options.
66+
llvm::cl::opt<bool> optO0{"O0",
67+
llvm::cl::desc("Run opt passes and codegen at O0"),
68+
llvm::cl::cat(optFlags)};
69+
llvm::cl::opt<bool> optO1{"O1",
70+
llvm::cl::desc("Run opt passes and codegen at O1"),
71+
llvm::cl::cat(optFlags)};
72+
llvm::cl::opt<bool> optO2{"O2",
73+
llvm::cl::desc("Run opt passes and codegen at O2"),
74+
llvm::cl::cat(optFlags)};
75+
llvm::cl::opt<bool> optO3{"O3",
76+
llvm::cl::desc("Run opt passes and codegen at O3"),
77+
llvm::cl::cat(optFlags)};
78+
79+
llvm::cl::OptionCategory clOptionsCategory{"linking options"};
80+
llvm::cl::list<std::string> clSharedLibs{
81+
"shared-libs", llvm::cl::desc("Libraries to link dynamically"),
82+
llvm::cl::ZeroOrMore, llvm::cl::MiscFlags::CommaSeparated,
83+
llvm::cl::cat(clOptionsCategory)};
84+
85+
/// CLI variables for debugging.
86+
llvm::cl::opt<bool> dumpObjectFile{
87+
"dump-object-file",
88+
llvm::cl::desc("Dump JITted-compiled object to file specified with "
89+
"-object-filename (<input file>.o by default).")};
90+
91+
llvm::cl::opt<std::string> objectFilename{
92+
"object-filename",
93+
llvm::cl::desc("Dump JITted-compiled object to file <input file>.o")};
94+
};
95+
} // end anonymous namespace
9296

9397
static OwningModuleRef parseMLIRInput(StringRef inputFilename,
9498
MLIRContext *context) {
@@ -110,10 +114,10 @@ static inline Error make_string_error(const Twine &message) {
110114
llvm::inconvertibleErrorCode());
111115
}
112116

113-
static Optional<unsigned> getCommandLineOptLevel() {
117+
static Optional<unsigned> getCommandLineOptLevel(Options &options) {
114118
Optional<unsigned> optLevel;
115119
SmallVector<std::reference_wrapper<llvm::cl::opt<bool>>, 4> optFlags{
116-
optO0, optO1, optO2, optO3};
120+
options.optO0, options.optO1, options.optO2, options.optO3};
117121

118122
// Determine if there is an optimization flag present.
119123
for (unsigned j = 0; j < 4; ++j) {
@@ -128,14 +132,15 @@ static Optional<unsigned> getCommandLineOptLevel() {
128132

129133
// JIT-compile the given module and run "entryPoint" with "args" as arguments.
130134
static Error
131-
compileAndExecute(ModuleOp module, StringRef entryPoint,
135+
compileAndExecute(Options &options, ModuleOp module, StringRef entryPoint,
132136
std::function<llvm::Error(llvm::Module *)> transformer,
133137
void **args) {
134138
Optional<llvm::CodeGenOpt::Level> jitCodeGenOptLevel;
135-
if (auto clOptLevel = getCommandLineOptLevel())
139+
if (auto clOptLevel = getCommandLineOptLevel(options))
136140
jitCodeGenOptLevel =
137141
static_cast<llvm::CodeGenOpt::Level>(clOptLevel.getValue());
138-
SmallVector<StringRef, 4> libs(clSharedLibs.begin(), clSharedLibs.end());
142+
SmallVector<StringRef, 4> libs(options.clSharedLibs.begin(),
143+
options.clSharedLibs.end());
139144
auto expectedEngine = mlir::ExecutionEngine::create(module, transformer,
140145
jitCodeGenOptLevel, libs);
141146
if (!expectedEngine)
@@ -146,9 +151,10 @@ compileAndExecute(ModuleOp module, StringRef entryPoint,
146151
if (!expectedFPtr)
147152
return expectedFPtr.takeError();
148153

149-
if (dumpObjectFile)
150-
engine->dumpToObjectFile(objectFilename.empty() ? inputFilename + ".o"
151-
: objectFilename);
154+
if (options.dumpObjectFile)
155+
engine->dumpToObjectFile(options.objectFilename.empty()
156+
? options.inputFilename + ".o"
157+
: options.objectFilename);
152158

153159
void (*fptr)(void **) = *expectedFPtr;
154160
(*fptr)(args);
@@ -157,17 +163,17 @@ compileAndExecute(ModuleOp module, StringRef entryPoint,
157163
}
158164

159165
static Error compileAndExecuteVoidFunction(
160-
ModuleOp module, StringRef entryPoint,
166+
Options &options, ModuleOp module, StringRef entryPoint,
161167
std::function<llvm::Error(llvm::Module *)> transformer) {
162168
auto mainFunction = module.lookupSymbol<LLVM::LLVMFuncOp>(entryPoint);
163169
if (!mainFunction || mainFunction.getBlocks().empty())
164170
return make_string_error("entry point not found");
165171
void *empty = nullptr;
166-
return compileAndExecute(module, entryPoint, transformer, &empty);
172+
return compileAndExecute(options, module, entryPoint, transformer, &empty);
167173
}
168174

169175
static Error compileAndExecuteSingleFloatReturnFunction(
170-
ModuleOp module, StringRef entryPoint,
176+
Options &options, ModuleOp module, StringRef entryPoint,
171177
std::function<llvm::Error(llvm::Module *)> transformer) {
172178
auto mainFunction = module.lookupSymbol<LLVM::LLVMFuncOp>(entryPoint);
173179
if (!mainFunction || mainFunction.isExternal())
@@ -184,28 +190,30 @@ static Error compileAndExecuteSingleFloatReturnFunction(
184190
void *data;
185191
} data;
186192
data.data = &res;
187-
if (auto error =
188-
compileAndExecute(module, entryPoint, transformer, (void **)&data))
193+
if (auto error = compileAndExecute(options, module, entryPoint, transformer,
194+
(void **)&data))
189195
return error;
190196

191197
// Intentional printing of the output so we can test.
192198
llvm::outs() << res << '\n';
193-
194199
return Error::success();
195200
}
196201

197-
// Entry point for all CPU runners. Expects the common argc/argv arguments for
198-
// standard C++ main functions and an mlirTransformer.
199-
// The latter is applied after parsing the input into MLIR IR and before passing
200-
// the MLIR module to the ExecutionEngine.
202+
/// Entry point for all CPU runners. Expects the common argc/argv arguments for
203+
/// standard C++ main functions and an mlirTransformer.
204+
/// The latter is applied after parsing the input into MLIR IR and before
205+
/// passing the MLIR module to the ExecutionEngine.
201206
int mlir::JitRunnerMain(
202207
int argc, char **argv,
203208
function_ref<LogicalResult(mlir::ModuleOp)> mlirTransformer) {
209+
// Create the options struct containing the command line options for the
210+
// runner. This must come before the command line options are parsed.
211+
Options options;
204212
llvm::cl::ParseCommandLineOptions(argc, argv, "MLIR CPU execution driver\n");
205213

206-
Optional<unsigned> optLevel = getCommandLineOptLevel();
214+
Optional<unsigned> optLevel = getCommandLineOptLevel(options);
207215
SmallVector<std::reference_wrapper<llvm::cl::opt<bool>>, 4> optFlags{
208-
optO0, optO1, optO2, optO3};
216+
options.optO0, options.optO1, options.optO2, options.optO3};
209217
unsigned optCLIPosition = 0;
210218
// Determine if there is an optimization flag present, and its CLI position
211219
// (optCLIPosition).
@@ -220,16 +228,16 @@ int mlir::JitRunnerMain(
220228
// insert any optimization passes in that vector (optPosition).
221229
SmallVector<const llvm::PassInfo *, 4> passes;
222230
unsigned optPosition = 0;
223-
for (unsigned i = 0, e = llvmPasses.size(); i < e; ++i) {
224-
passes.push_back(llvmPasses[i]);
225-
if (optCLIPosition < llvmPasses.getPosition(i)) {
231+
for (unsigned i = 0, e = options.llvmPasses.size(); i < e; ++i) {
232+
passes.push_back(options.llvmPasses[i]);
233+
if (optCLIPosition < options.llvmPasses.getPosition(i)) {
226234
optPosition = i;
227235
optCLIPosition = UINT_MAX; // To ensure we never insert again
228236
}
229237
}
230238

231239
MLIRContext context;
232-
auto m = parseMLIRInput(inputFilename, &context);
240+
auto m = parseMLIRInput(options.inputFilename, &context);
233241
if (!m) {
234242
llvm::errs() << "could not parse the input IR\n";
235243
return 1;
@@ -254,17 +262,19 @@ int mlir::JitRunnerMain(
254262
passes, optLevel, /*targetMachine=*/tmOrError->get(), optPosition);
255263

256264
// Get the function used to compile and execute the module.
257-
using CompileAndExecuteFnT = Error (*)(
258-
ModuleOp, StringRef, std::function<llvm::Error(llvm::Module *)>);
265+
using CompileAndExecuteFnT =
266+
Error (*)(Options &, ModuleOp, StringRef,
267+
std::function<llvm::Error(llvm::Module *)>);
259268
auto compileAndExecuteFn =
260-
llvm::StringSwitch<CompileAndExecuteFnT>(mainFuncType.getValue())
269+
llvm::StringSwitch<CompileAndExecuteFnT>(options.mainFuncType.getValue())
261270
.Case("f32", compileAndExecuteSingleFloatReturnFunction)
262271
.Case("void", compileAndExecuteVoidFunction)
263272
.Default(nullptr);
264273

265274
Error error =
266275
compileAndExecuteFn
267-
? compileAndExecuteFn(m.get(), mainFuncName.getValue(), transformer)
276+
? compileAndExecuteFn(options, m.get(),
277+
options.mainFuncName.getValue(), transformer)
268278
: make_string_error("unsupported function type");
269279

270280
int exitCode = EXIT_SUCCESS;

0 commit comments

Comments
 (0)