//===- OptUtils.cpp - MLIR Execution Engine optimization pass utilities ---===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements the utility functions to trigger LLVM optimizations from // MLIR Execution Engine. // //===----------------------------------------------------------------------===// #include "mlir/ExecutionEngine/OptUtils.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/Module.h" #include "llvm/Passes/OptimizationLevel.h" #include "llvm/Passes/PassBuilder.h" #include "llvm/Support/Error.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Target/TargetMachine.h" #include using namespace llvm; static std::optional mapToLevel(unsigned optLevel, unsigned sizeLevel) { switch (optLevel) { case 0: return OptimizationLevel::O0; case 1: return OptimizationLevel::O1; case 2: switch (sizeLevel) { case 0: return OptimizationLevel::O2; case 1: return OptimizationLevel::Os; case 2: return OptimizationLevel::Oz; } break; case 3: return OptimizationLevel::O3; } return std::nullopt; } // Create and return a lambda that uses LLVM pass manager builder to set up // optimizations based on the given level. std::function mlir::makeOptimizingTransformer(unsigned optLevel, unsigned sizeLevel, TargetMachine *targetMachine) { return [optLevel, sizeLevel, targetMachine](Module *m) -> Error { std::optional ol = mapToLevel(optLevel, sizeLevel); if (!ol) { return make_error( formatv("invalid optimization/size level {0}/{1}", optLevel, sizeLevel) .str(), inconvertibleErrorCode()); } LoopAnalysisManager lam; FunctionAnalysisManager fam; CGSCCAnalysisManager cgam; ModuleAnalysisManager mam; PipelineTuningOptions tuningOptions; tuningOptions.LoopUnrolling = true; tuningOptions.LoopInterleaving = true; tuningOptions.LoopVectorization = true; tuningOptions.SLPVectorization = true; PassBuilder pb(targetMachine, tuningOptions); 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(); }; }