[Mlir-commits] [mlir] c3efb75 - Revert "[mlir] Remove uses of LLVM's legacy pass manager"
Arthur Eubanks
llvmlistbot at llvm.org
Mon Apr 11 16:45:49 PDT 2022
Author: Arthur Eubanks
Date: 2022-04-11T16:45:19-07:00
New Revision: c3efb75061ce0cdec85f691bafc6d658ca587102
URL: https://github.com/llvm/llvm-project/commit/c3efb75061ce0cdec85f691bafc6d658ca587102
DIFF: https://github.com/llvm/llvm-project/commit/c3efb75061ce0cdec85f691bafc6d658ca587102.diff
LOG: Revert "[mlir] Remove uses of LLVM's legacy pass manager"
This reverts commit b0f7f6f78d050cc89b31c87fb48744989145af60.
Causes test failures: https://lab.llvm.org/buildbot#builders/61/builds/24879
Added:
Modified:
mlir/include/mlir/ExecutionEngine/OptUtils.h
mlir/lib/CAPI/ExecutionEngine/ExecutionEngine.cpp
mlir/lib/ExecutionEngine/CMakeLists.txt
mlir/lib/ExecutionEngine/JitRunner.cpp
mlir/lib/ExecutionEngine/OptUtils.cpp
mlir/tools/mlir-cpu-runner/mlir-cpu-runner.cpp
mlir/tools/mlir-spirv-cpu-runner/mlir-spirv-cpu-runner.cpp
mlir/tools/mlir-vulkan-runner/mlir-vulkan-runner.cpp
Removed:
################################################################################
diff --git a/mlir/include/mlir/ExecutionEngine/OptUtils.h b/mlir/include/mlir/ExecutionEngine/OptUtils.h
index 4cee8c6d60ff1..b5c4e2d3b3005 100644
--- a/mlir/include/mlir/ExecutionEngine/OptUtils.h
+++ b/mlir/include/mlir/ExecutionEngine/OptUtils.h
@@ -14,6 +14,8 @@
#ifndef MLIR_EXECUTIONENGINE_OPTUTILS_H
#define MLIR_EXECUTIONENGINE_OPTUTILS_H
+#include "llvm/Pass.h"
+
#include <functional>
#include <string>
@@ -25,6 +27,10 @@ class TargetMachine;
namespace mlir {
+/// Initialize LLVM passes that can be used when running MLIR code using
+/// ExecutionEngine.
+void initializeLLVMPasses();
+
/// Create a module transformer function for MLIR ExecutionEngine that runs
/// LLVM IR passes corresponding to the given speed and size optimization
/// levels (e.g. -O2 or -Os). If not null, `targetMachine` is used to
@@ -34,6 +40,18 @@ std::function<llvm::Error(llvm::Module *)>
makeOptimizingTransformer(unsigned optLevel, unsigned sizeLevel,
llvm::TargetMachine *targetMachine);
+/// Create a module transformer function for MLIR ExecutionEngine that runs
+/// LLVM IR passes explicitly specified, plus an optional optimization level,
+/// Any optimization passes, if present, will be inserted before the pass at
+/// position optPassesInsertPos. If not null, `targetMachine` is used to
+/// initialize passes that provide target-specific information to the LLVM
+/// optimizer. `targetMachine` must outlive the returned std::function.
+std::function<llvm::Error(llvm::Module *)>
+makeLLVMPassesTransformer(llvm::ArrayRef<const llvm::PassInfo *> llvmPasses,
+ llvm::Optional<unsigned> mbOptLevel,
+ llvm::TargetMachine *targetMachine,
+ unsigned optPassesInsertPos = 0);
+
} // namespace mlir
#endif // MLIR_EXECUTIONENGINE_OPTUTILS_H
diff --git a/mlir/lib/CAPI/ExecutionEngine/ExecutionEngine.cpp b/mlir/lib/CAPI/ExecutionEngine/ExecutionEngine.cpp
index 2190566b22b13..4c55530870df7 100644
--- a/mlir/lib/CAPI/ExecutionEngine/ExecutionEngine.cpp
+++ b/mlir/lib/CAPI/ExecutionEngine/ExecutionEngine.cpp
@@ -48,8 +48,8 @@ mlirExecutionEngineCreate(MlirModule op, int optLevel, int numPaths,
// Create a transformer to run all LLVM optimization passes at the
// specified optimization level.
auto llvmOptLevel = static_cast<llvm::CodeGenOpt::Level>(optLevel);
- auto transformer = mlir::makeOptimizingTransformer(
- llvmOptLevel, /*sizeLevel=*/0, /*targetMachine=*/tmOrError->get());
+ auto transformer = mlir::makeLLVMPassesTransformer(
+ /*passes=*/{}, llvmOptLevel, /*targetMachine=*/tmOrError->get());
ExecutionEngineOptions jitOptions;
jitOptions.transformer = transformer;
jitOptions.jitCodeGenOptLevel = llvmOptLevel;
diff --git a/mlir/lib/ExecutionEngine/CMakeLists.txt b/mlir/lib/ExecutionEngine/CMakeLists.txt
index e1f30470a9fd6..8776d6f7e5d8f 100644
--- a/mlir/lib/ExecutionEngine/CMakeLists.txt
+++ b/mlir/lib/ExecutionEngine/CMakeLists.txt
@@ -52,7 +52,6 @@ add_mlir_library(MLIRExecutionEngine
TransformUtils
nativecodegen
IPO
- Passes
${LLVM_JIT_LISTENER_LIB}
LINK_LIBS PUBLIC
diff --git a/mlir/lib/ExecutionEngine/JitRunner.cpp b/mlir/lib/ExecutionEngine/JitRunner.cpp
index 5e738002728dd..f61710f390acd 100644
--- a/mlir/lib/ExecutionEngine/JitRunner.cpp
+++ b/mlir/lib/ExecutionEngine/JitRunner.cpp
@@ -57,6 +57,10 @@ struct Options {
llvm::cl::OptionCategory optFlags{"opt-like flags"};
+ // CLI list of pass information
+ llvm::cl::list<const llvm::PassInfo *, bool, llvm::PassNameParser> llvmPasses{
+ llvm::cl::desc("LLVM optimizing passes to run"), llvm::cl::cat(optFlags)};
+
// CLI variables for -On options.
llvm::cl::opt<bool> optO0{"O0",
llvm::cl::desc("Run opt passes and codegen at O0"),
@@ -318,6 +322,27 @@ int mlir::JitRunnerMain(int argc, char **argv, const DialectRegistry ®istry,
Optional<unsigned> optLevel = getCommandLineOptLevel(options);
SmallVector<std::reference_wrapper<llvm::cl::opt<bool>>, 4> optFlags{
options.optO0, options.optO1, options.optO2, options.optO3};
+ unsigned optCLIPosition = 0;
+ // Determine if there is an optimization flag present, and its CLI position
+ // (optCLIPosition).
+ for (unsigned j = 0; j < 4; ++j) {
+ auto &flag = optFlags[j].get();
+ if (flag) {
+ optCLIPosition = flag.getPosition();
+ break;
+ }
+ }
+ // Generate vector of pass information, plus the index at which we should
+ // insert any optimization passes in that vector (optPosition).
+ SmallVector<const llvm::PassInfo *, 4> passes;
+ unsigned optPosition = 0;
+ 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(registry);
@@ -342,11 +367,11 @@ int mlir::JitRunnerMain(int argc, char **argv, const DialectRegistry ®istry,
return EXIT_FAILURE;
}
+ auto transformer = mlir::makeLLVMPassesTransformer(
+ passes, optLevel, /*targetMachine=*/tmOrError->get(), optPosition);
+
CompileAndExecuteConfig compileAndExecuteConfig;
- if (optLevel) {
- compileAndExecuteConfig.transformer = mlir::makeOptimizingTransformer(
- *optLevel, /*sizeLevel=*/0, /*targetMachine=*/tmOrError->get());
- }
+ compileAndExecuteConfig.transformer = transformer;
compileAndExecuteConfig.llvmModuleBuilder = config.llvmModuleBuilder;
compileAndExecuteConfig.runtimeSymbolMap = config.runtimesymbolMap;
diff --git a/mlir/lib/ExecutionEngine/OptUtils.cpp b/mlir/lib/ExecutionEngine/OptUtils.cpp
index 33b52aadf9c48..53ad7fd66a9af 100644
--- a/mlir/lib/ExecutionEngine/OptUtils.cpp
+++ b/mlir/lib/ExecutionEngine/OptUtils.cpp
@@ -13,76 +13,135 @@
#include "mlir/ExecutionEngine/OptUtils.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/LegacyPassNameParser.h"
#include "llvm/IR/Module.h"
-#include "llvm/Passes/OptimizationLevel.h"
-#include "llvm/Passes/PassBuilder.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
-#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/StringSaver.h"
#include "llvm/Target/TargetMachine.h"
+#include "llvm/Transforms/Coroutines.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#include <climits>
+#include <mutex>
-using namespace llvm;
-
-static Optional<OptimizationLevel> mapToLevel(unsigned optLevel,
- unsigned sizeLevel) {
- switch (optLevel) {
- case 0:
- return OptimizationLevel::O0;
+// Run the module and function passes managed by the module manager.
+static void runPasses(llvm::legacy::PassManager &modulePM,
+ llvm::legacy::FunctionPassManager &funcPM,
+ llvm::Module &m) {
+ funcPM.doInitialization();
+ for (auto &func : m) {
+ funcPM.run(func);
+ }
+ funcPM.doFinalization();
+ modulePM.run(m);
+}
- case 1:
- return OptimizationLevel::O1;
+// Initialize basic LLVM transformation passes under lock.
+void mlir::initializeLLVMPasses() {
+ static std::mutex mutex;
+ std::lock_guard<std::mutex> lock(mutex);
- case 2:
- switch (sizeLevel) {
- case 0:
- return OptimizationLevel::O2;
+ auto ®istry = *llvm::PassRegistry::getPassRegistry();
+ llvm::initializeCore(registry);
+ llvm::initializeTransformUtils(registry);
+ llvm::initializeScalarOpts(registry);
+ llvm::initializeIPO(registry);
+ llvm::initializeInstCombine(registry);
+ llvm::initializeAggressiveInstCombine(registry);
+ llvm::initializeAnalysis(registry);
+ llvm::initializeVectorization(registry);
+ llvm::initializeCoroutines(registry);
+}
- case 1:
- return OptimizationLevel::Os;
+// Populate pass managers according to the optimization and size levels.
+// This behaves similarly to LLVM opt.
+static void populatePassManagers(llvm::legacy::PassManager &modulePM,
+ llvm::legacy::FunctionPassManager &funcPM,
+ unsigned optLevel, unsigned sizeLevel,
+ llvm::TargetMachine *targetMachine) {
+ llvm::PassManagerBuilder builder;
+ builder.OptLevel = optLevel;
+ builder.SizeLevel = sizeLevel;
+ builder.Inliner = llvm::createFunctionInliningPass(
+ optLevel, sizeLevel, /*DisableInlineHotCallSite=*/false);
+ builder.LoopVectorize = optLevel > 1 && sizeLevel < 2;
+ builder.SLPVectorize = optLevel > 1 && sizeLevel < 2;
+ builder.DisableUnrollLoops = (optLevel == 0);
- case 2:
- return OptimizationLevel::Oz;
- }
+ // Add all coroutine passes to the builder.
+ addCoroutinePassesToExtensionPoints(builder);
- case 3:
- return OptimizationLevel::O3;
+ if (targetMachine) {
+ // Add pass to initialize TTI for this specific target. Otherwise, TTI will
+ // be initialized to NoTTIImpl by default.
+ modulePM.add(createTargetTransformInfoWrapperPass(
+ targetMachine->getTargetIRAnalysis()));
+ funcPM.add(createTargetTransformInfoWrapperPass(
+ targetMachine->getTargetIRAnalysis()));
}
- return None;
+
+ builder.populateModulePassManager(modulePM);
+ builder.populateFunctionPassManager(funcPM);
}
+
// Create and return a lambda that uses LLVM pass manager builder to set up
// optimizations based on the given level.
-std::function<Error(Module *)>
+std::function<llvm::Error(llvm::Module *)>
mlir::makeOptimizingTransformer(unsigned optLevel, unsigned sizeLevel,
- TargetMachine *targetMachine) {
- return [optLevel, sizeLevel, targetMachine](Module *m) -> Error {
- Optional<OptimizationLevel> ol = mapToLevel(optLevel, sizeLevel);
- if (!ol) {
- return make_error<StringError>(
- formatv("invalid optimization/size level {0}/{1}", optLevel,
- sizeLevel)
- .str(),
- inconvertibleErrorCode());
+ llvm::TargetMachine *targetMachine) {
+ return [optLevel, sizeLevel, targetMachine](llvm::Module *m) -> llvm::Error {
+ llvm::legacy::PassManager modulePM;
+ llvm::legacy::FunctionPassManager funcPM(m);
+ populatePassManagers(modulePM, funcPM, optLevel, sizeLevel, targetMachine);
+ runPasses(modulePM, funcPM, *m);
+
+ return llvm::Error::success();
+ };
+}
+
+// Create and return a lambda that is given a set of passes to run, plus an
+// optional optimization level to pre-populate the pass manager.
+std::function<llvm::Error(llvm::Module *)> mlir::makeLLVMPassesTransformer(
+ llvm::ArrayRef<const llvm::PassInfo *> llvmPasses,
+ llvm::Optional<unsigned> mbOptLevel, llvm::TargetMachine *targetMachine,
+ unsigned optPassesInsertPos) {
+ return [llvmPasses, mbOptLevel, optPassesInsertPos,
+ targetMachine](llvm::Module *m) -> llvm::Error {
+ llvm::legacy::PassManager modulePM;
+ llvm::legacy::FunctionPassManager funcPM(m);
+
+ bool insertOptPasses = mbOptLevel.hasValue();
+ for (unsigned i = 0, e = llvmPasses.size(); i < e; ++i) {
+ const auto *passInfo = llvmPasses[i];
+ if (!passInfo->getNormalCtor())
+ continue;
+
+ if (insertOptPasses && optPassesInsertPos == i) {
+ populatePassManagers(modulePM, funcPM, mbOptLevel.getValue(), 0,
+ targetMachine);
+ insertOptPasses = false;
+ }
+
+ auto *pass = passInfo->createPass();
+ if (!pass)
+ return llvm::make_error<llvm::StringError>(
+ "could not create pass " + passInfo->getPassName(),
+ llvm::inconvertibleErrorCode());
+ modulePM.add(pass);
}
- LoopAnalysisManager lam;
- FunctionAnalysisManager fam;
- CGSCCAnalysisManager cgam;
- ModuleAnalysisManager mam;
-
- PassBuilder pb(targetMachine);
-
- pb.registerModuleAnalyses(mam);
- pb.registerCGSCCAnalyses(cgam);
- pb.registerFunctionAnalyses(fam);
- pb.registerLoopAnalyses(lam);
- pb.crossRegisterProxies(lam, fam, cgam, mam);
-
- ModulePassManager mpm;
- if (*ol == OptimizationLevel::O0)
- mpm.addPass(pb.buildO0DefaultPipeline(*ol));
- else
- mpm.addPass(pb.buildPerModuleDefaultPipeline(*ol));
-
- mpm.run(*m, mam);
- return Error::success();
+
+ if (insertOptPasses)
+ populatePassManagers(modulePM, funcPM, mbOptLevel.getValue(), 0,
+ targetMachine);
+
+ runPasses(modulePM, funcPM, *m);
+ return llvm::Error::success();
};
}
diff --git a/mlir/tools/mlir-cpu-runner/mlir-cpu-runner.cpp b/mlir/tools/mlir-cpu-runner/mlir-cpu-runner.cpp
index 1b1d5d03d2be5..b1009a1fae458 100644
--- a/mlir/tools/mlir-cpu-runner/mlir-cpu-runner.cpp
+++ b/mlir/tools/mlir-cpu-runner/mlir-cpu-runner.cpp
@@ -26,6 +26,7 @@ int main(int argc, char **argv) {
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
llvm::InitializeNativeTargetAsmParser();
+ mlir::initializeLLVMPasses();
mlir::DialectRegistry registry;
mlir::registerAllToLLVMIRTranslations(registry);
diff --git a/mlir/tools/mlir-spirv-cpu-runner/mlir-spirv-cpu-runner.cpp b/mlir/tools/mlir-spirv-cpu-runner/mlir-spirv-cpu-runner.cpp
index fb51af9002e12..ee2c4be2574b8 100644
--- a/mlir/tools/mlir-spirv-cpu-runner/mlir-spirv-cpu-runner.cpp
+++ b/mlir/tools/mlir-spirv-cpu-runner/mlir-spirv-cpu-runner.cpp
@@ -90,6 +90,7 @@ int main(int argc, char **argv) {
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
+ mlir::initializeLLVMPasses();
mlir::JitRunnerConfig jitRunnerConfig;
jitRunnerConfig.mlirTransformer = runMLIRPasses;
diff --git a/mlir/tools/mlir-vulkan-runner/mlir-vulkan-runner.cpp b/mlir/tools/mlir-vulkan-runner/mlir-vulkan-runner.cpp
index 6d0edda7feb9b..972292954663b 100644
--- a/mlir/tools/mlir-vulkan-runner/mlir-vulkan-runner.cpp
+++ b/mlir/tools/mlir-vulkan-runner/mlir-vulkan-runner.cpp
@@ -67,6 +67,7 @@ int main(int argc, char **argv) {
llvm::InitLLVM y(argc, argv);
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
+ mlir::initializeLLVMPasses();
mlir::JitRunnerConfig jitRunnerConfig;
jitRunnerConfig.mlirTransformer = runMLIRPasses;
More information about the Mlir-commits
mailing list