diff --git a/mlir/lib/Support/JitRunner.cpp b/mlir/lib/Support/JitRunner.cpp --- a/mlir/lib/Support/JitRunner.cpp +++ b/mlir/lib/Support/JitRunner.cpp @@ -41,54 +41,58 @@ using namespace mlir; using llvm::Error; -static llvm::cl::opt inputFilename(llvm::cl::Positional, - llvm::cl::desc(""), - llvm::cl::init("-")); -static llvm::cl::opt - mainFuncName("e", llvm::cl::desc("The function to be called"), - llvm::cl::value_desc(""), - llvm::cl::init("main")); -static llvm::cl::opt mainFuncType( - "entry-point-result", - llvm::cl::desc("Textual description of the function type to be called"), - llvm::cl::value_desc("f32 | void"), llvm::cl::init("f32")); - -static llvm::cl::OptionCategory optFlags("opt-like flags"); - -// CLI list of pass information -static llvm::cl::list - llvmPasses(llvm::cl::desc("LLVM optimizing passes to run"), - llvm::cl::cat(optFlags)); - -// CLI variables for -On options. -static llvm::cl::opt - optO0("O0", llvm::cl::desc("Run opt passes and codegen at O0"), - llvm::cl::cat(optFlags)); -static llvm::cl::opt - optO1("O1", llvm::cl::desc("Run opt passes and codegen at O1"), - llvm::cl::cat(optFlags)); -static llvm::cl::opt - optO2("O2", llvm::cl::desc("Run opt passes and codegen at O2"), - llvm::cl::cat(optFlags)); -static llvm::cl::opt - optO3("O3", llvm::cl::desc("Run opt passes and codegen at O3"), - llvm::cl::cat(optFlags)); - -static llvm::cl::OptionCategory clOptionsCategory("linking options"); -static llvm::cl::list - clSharedLibs("shared-libs", llvm::cl::desc("Libraries to link dynamically"), - llvm::cl::ZeroOrMore, llvm::cl::MiscFlags::CommaSeparated, - llvm::cl::cat(clOptionsCategory)); - -// CLI variables for debugging. -static llvm::cl::opt dumpObjectFile( - "dump-object-file", - llvm::cl::desc("Dump JITted-compiled object to file specified with " - "-object-filename (.o by default).")); - -static llvm::cl::opt objectFilename( - "object-filename", - llvm::cl::desc("Dump JITted-compiled object to file .o")); +namespace { +/// This options struct prevents the need for global static initializers, and +/// is only initialized if the JITRunner is invoked. +struct Options { + llvm::cl::opt inputFilename{llvm::cl::Positional, + llvm::cl::desc(""), + llvm::cl::init("-")}; + llvm::cl::opt mainFuncName{ + "e", llvm::cl::desc("The function to be called"), + llvm::cl::value_desc(""), llvm::cl::init("main")}; + llvm::cl::opt mainFuncType{ + "entry-point-result", + llvm::cl::desc("Textual description of the function type to be called"), + llvm::cl::value_desc("f32 | void"), llvm::cl::init("f32")}; + + llvm::cl::OptionCategory optFlags{"opt-like flags"}; + + // CLI list of pass information + llvm::cl::list llvmPasses{ + llvm::cl::desc("LLVM optimizing passes to run"), llvm::cl::cat(optFlags)}; + + // CLI variables for -On options. + llvm::cl::opt optO0{"O0", + llvm::cl::desc("Run opt passes and codegen at O0"), + llvm::cl::cat(optFlags)}; + llvm::cl::opt optO1{"O1", + llvm::cl::desc("Run opt passes and codegen at O1"), + llvm::cl::cat(optFlags)}; + llvm::cl::opt optO2{"O2", + llvm::cl::desc("Run opt passes and codegen at O2"), + llvm::cl::cat(optFlags)}; + llvm::cl::opt optO3{"O3", + llvm::cl::desc("Run opt passes and codegen at O3"), + llvm::cl::cat(optFlags)}; + + llvm::cl::OptionCategory clOptionsCategory{"linking options"}; + llvm::cl::list clSharedLibs{ + "shared-libs", llvm::cl::desc("Libraries to link dynamically"), + llvm::cl::ZeroOrMore, llvm::cl::MiscFlags::CommaSeparated, + llvm::cl::cat(clOptionsCategory)}; + + /// CLI variables for debugging. + llvm::cl::opt dumpObjectFile{ + "dump-object-file", + llvm::cl::desc("Dump JITted-compiled object to file specified with " + "-object-filename (.o by default).")}; + + llvm::cl::opt objectFilename{ + "object-filename", + llvm::cl::desc("Dump JITted-compiled object to file .o")}; +}; +} // end anonymous namespace static OwningModuleRef parseMLIRInput(StringRef inputFilename, MLIRContext *context) { @@ -110,10 +114,10 @@ llvm::inconvertibleErrorCode()); } -static Optional getCommandLineOptLevel() { +static Optional getCommandLineOptLevel(Options &options) { Optional optLevel; SmallVector>, 4> optFlags{ - optO0, optO1, optO2, optO3}; + options.optO0, options.optO1, options.optO2, options.optO3}; // Determine if there is an optimization flag present. for (unsigned j = 0; j < 4; ++j) { @@ -128,14 +132,15 @@ // JIT-compile the given module and run "entryPoint" with "args" as arguments. static Error -compileAndExecute(ModuleOp module, StringRef entryPoint, +compileAndExecute(Options &options, ModuleOp module, StringRef entryPoint, std::function transformer, void **args) { Optional jitCodeGenOptLevel; - if (auto clOptLevel = getCommandLineOptLevel()) + if (auto clOptLevel = getCommandLineOptLevel(options)) jitCodeGenOptLevel = static_cast(clOptLevel.getValue()); - SmallVector libs(clSharedLibs.begin(), clSharedLibs.end()); + SmallVector libs(options.clSharedLibs.begin(), + options.clSharedLibs.end()); auto expectedEngine = mlir::ExecutionEngine::create(module, transformer, jitCodeGenOptLevel, libs); if (!expectedEngine) @@ -146,9 +151,10 @@ if (!expectedFPtr) return expectedFPtr.takeError(); - if (dumpObjectFile) - engine->dumpToObjectFile(objectFilename.empty() ? inputFilename + ".o" - : objectFilename); + if (options.dumpObjectFile) + engine->dumpToObjectFile(options.objectFilename.empty() + ? options.inputFilename + ".o" + : options.objectFilename); void (*fptr)(void **) = *expectedFPtr; (*fptr)(args); @@ -157,17 +163,17 @@ } static Error compileAndExecuteVoidFunction( - ModuleOp module, StringRef entryPoint, + Options &options, ModuleOp module, StringRef entryPoint, std::function transformer) { auto mainFunction = module.lookupSymbol(entryPoint); if (!mainFunction || mainFunction.getBlocks().empty()) return make_string_error("entry point not found"); void *empty = nullptr; - return compileAndExecute(module, entryPoint, transformer, &empty); + return compileAndExecute(options, module, entryPoint, transformer, &empty); } static Error compileAndExecuteSingleFloatReturnFunction( - ModuleOp module, StringRef entryPoint, + Options &options, ModuleOp module, StringRef entryPoint, std::function transformer) { auto mainFunction = module.lookupSymbol(entryPoint); if (!mainFunction || mainFunction.isExternal()) @@ -184,28 +190,30 @@ void *data; } data; data.data = &res; - if (auto error = - compileAndExecute(module, entryPoint, transformer, (void **)&data)) + if (auto error = compileAndExecute(options, module, entryPoint, transformer, + (void **)&data)) return error; // Intentional printing of the output so we can test. llvm::outs() << res << '\n'; - return Error::success(); } -// Entry point for all CPU runners. Expects the common argc/argv arguments for -// standard C++ main functions and an mlirTransformer. -// The latter is applied after parsing the input into MLIR IR and before passing -// the MLIR module to the ExecutionEngine. +/// Entry point for all CPU runners. Expects the common argc/argv arguments for +/// standard C++ main functions and an mlirTransformer. +/// The latter is applied after parsing the input into MLIR IR and before +/// passing the MLIR module to the ExecutionEngine. int mlir::JitRunnerMain( int argc, char **argv, function_ref mlirTransformer) { + // Create the options struct containing the command line options for the + // runner. This must come before the command line options are parsed. + Options options; llvm::cl::ParseCommandLineOptions(argc, argv, "MLIR CPU execution driver\n"); - Optional optLevel = getCommandLineOptLevel(); + Optional optLevel = getCommandLineOptLevel(options); SmallVector>, 4> optFlags{ - optO0, optO1, optO2, optO3}; + options.optO0, options.optO1, options.optO2, options.optO3}; unsigned optCLIPosition = 0; // Determine if there is an optimization flag present, and its CLI position // (optCLIPosition). @@ -220,16 +228,16 @@ // insert any optimization passes in that vector (optPosition). SmallVector passes; unsigned optPosition = 0; - for (unsigned i = 0, e = llvmPasses.size(); i < e; ++i) { - passes.push_back(llvmPasses[i]); - if (optCLIPosition < llvmPasses.getPosition(i)) { + for (unsigned i = 0, e = options.llvmPasses.size(); i < e; ++i) { + passes.push_back(options.llvmPasses[i]); + if (optCLIPosition < options.llvmPasses.getPosition(i)) { optPosition = i; optCLIPosition = UINT_MAX; // To ensure we never insert again } } MLIRContext context; - auto m = parseMLIRInput(inputFilename, &context); + auto m = parseMLIRInput(options.inputFilename, &context); if (!m) { llvm::errs() << "could not parse the input IR\n"; return 1; @@ -254,17 +262,19 @@ passes, optLevel, /*targetMachine=*/tmOrError->get(), optPosition); // Get the function used to compile and execute the module. - using CompileAndExecuteFnT = Error (*)( - ModuleOp, StringRef, std::function); + using CompileAndExecuteFnT = + Error (*)(Options &, ModuleOp, StringRef, + std::function); auto compileAndExecuteFn = - llvm::StringSwitch(mainFuncType.getValue()) + llvm::StringSwitch(options.mainFuncType.getValue()) .Case("f32", compileAndExecuteSingleFloatReturnFunction) .Case("void", compileAndExecuteVoidFunction) .Default(nullptr); Error error = compileAndExecuteFn - ? compileAndExecuteFn(m.get(), mainFuncName.getValue(), transformer) + ? compileAndExecuteFn(options, m.get(), + options.mainFuncName.getValue(), transformer) : make_string_error("unsupported function type"); int exitCode = EXIT_SUCCESS;