14bb31f73SAlex Zinenko //===- OptUtils.cpp - MLIR Execution Engine optimization pass utilities ---===//
24bb31f73SAlex Zinenko //
330857107SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
456222a06SMehdi Amini // See https://llvm.org/LICENSE.txt for license information.
556222a06SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64bb31f73SAlex Zinenko //
756222a06SMehdi Amini //===----------------------------------------------------------------------===//
84bb31f73SAlex Zinenko //
94bb31f73SAlex Zinenko // This file implements the utility functions to trigger LLVM optimizations from
104bb31f73SAlex Zinenko // MLIR Execution Engine.
114bb31f73SAlex Zinenko //
124bb31f73SAlex Zinenko //===----------------------------------------------------------------------===//
134bb31f73SAlex Zinenko 
144bb31f73SAlex Zinenko #include "mlir/ExecutionEngine/OptUtils.h"
154bb31f73SAlex Zinenko 
1668587dfcSDiego Caballero #include "llvm/Analysis/TargetTransformInfo.h"
174bb31f73SAlex Zinenko #include "llvm/IR/Module.h"
187ccd026cSArthur Eubanks #include "llvm/Passes/OptimizationLevel.h"
197ccd026cSArthur Eubanks #include "llvm/Passes/PassBuilder.h"
204bb31f73SAlex Zinenko #include "llvm/Support/Error.h"
217ccd026cSArthur Eubanks #include "llvm/Support/FormatVariadic.h"
2268587dfcSDiego Caballero #include "llvm/Target/TargetMachine.h"
234bb31f73SAlex Zinenko 
247ccd026cSArthur Eubanks using namespace llvm;
257ccd026cSArthur Eubanks 
mapToLevel(unsigned optLevel,unsigned sizeLevel)267ccd026cSArthur Eubanks static Optional<OptimizationLevel> mapToLevel(unsigned optLevel,
277ccd026cSArthur Eubanks                                               unsigned sizeLevel) {
287ccd026cSArthur Eubanks   switch (optLevel) {
297ccd026cSArthur Eubanks   case 0:
307ccd026cSArthur Eubanks     return OptimizationLevel::O0;
317ccd026cSArthur Eubanks 
327ccd026cSArthur Eubanks   case 1:
337ccd026cSArthur Eubanks     return OptimizationLevel::O1;
347ccd026cSArthur Eubanks 
357ccd026cSArthur Eubanks   case 2:
367ccd026cSArthur Eubanks     switch (sizeLevel) {
377ccd026cSArthur Eubanks     case 0:
387ccd026cSArthur Eubanks       return OptimizationLevel::O2;
397ccd026cSArthur Eubanks 
407ccd026cSArthur Eubanks     case 1:
417ccd026cSArthur Eubanks       return OptimizationLevel::Os;
427ccd026cSArthur Eubanks 
437ccd026cSArthur Eubanks     case 2:
447ccd026cSArthur Eubanks       return OptimizationLevel::Oz;
454bb31f73SAlex Zinenko     }
46*42f5b050SDaniil Dudkin     break;
477ccd026cSArthur Eubanks   case 3:
487ccd026cSArthur Eubanks     return OptimizationLevel::O3;
494bb31f73SAlex Zinenko   }
507ccd026cSArthur Eubanks   return None;
5168587dfcSDiego Caballero }
52d9cc3c31SAlex Zinenko // Create and return a lambda that uses LLVM pass manager builder to set up
53d9cc3c31SAlex Zinenko // optimizations based on the given level.
547ccd026cSArthur Eubanks std::function<Error(Module *)>
makeOptimizingTransformer(unsigned optLevel,unsigned sizeLevel,TargetMachine * targetMachine)5568587dfcSDiego Caballero mlir::makeOptimizingTransformer(unsigned optLevel, unsigned sizeLevel,
567ccd026cSArthur Eubanks                                 TargetMachine *targetMachine) {
577ccd026cSArthur Eubanks   return [optLevel, sizeLevel, targetMachine](Module *m) -> Error {
587ccd026cSArthur Eubanks     Optional<OptimizationLevel> ol = mapToLevel(optLevel, sizeLevel);
597ccd026cSArthur Eubanks     if (!ol) {
607ccd026cSArthur Eubanks       return make_error<StringError>(
617ccd026cSArthur Eubanks           formatv("invalid optimization/size level {0}/{1}", optLevel,
627ccd026cSArthur Eubanks                   sizeLevel)
637ccd026cSArthur Eubanks               .str(),
647ccd026cSArthur Eubanks           inconvertibleErrorCode());
654bb31f73SAlex Zinenko     }
667ccd026cSArthur Eubanks     LoopAnalysisManager lam;
677ccd026cSArthur Eubanks     FunctionAnalysisManager fam;
687ccd026cSArthur Eubanks     CGSCCAnalysisManager cgam;
697ccd026cSArthur Eubanks     ModuleAnalysisManager mam;
704bb31f73SAlex Zinenko 
717ccd026cSArthur Eubanks     PassBuilder pb(targetMachine);
724bb31f73SAlex Zinenko 
737ccd026cSArthur Eubanks     pb.registerModuleAnalyses(mam);
747ccd026cSArthur Eubanks     pb.registerCGSCCAnalyses(cgam);
757ccd026cSArthur Eubanks     pb.registerFunctionAnalyses(fam);
767ccd026cSArthur Eubanks     pb.registerLoopAnalyses(lam);
777ccd026cSArthur Eubanks     pb.crossRegisterProxies(lam, fam, cgam, mam);
784bb31f73SAlex Zinenko 
797ccd026cSArthur Eubanks     ModulePassManager mpm;
807ccd026cSArthur Eubanks     if (*ol == OptimizationLevel::O0)
817ccd026cSArthur Eubanks       mpm.addPass(pb.buildO0DefaultPipeline(*ol));
827ccd026cSArthur Eubanks     else
837ccd026cSArthur Eubanks       mpm.addPass(pb.buildPerModuleDefaultPipeline(*ol));
84d9cc3c31SAlex Zinenko 
857ccd026cSArthur Eubanks     mpm.run(*m, mam);
867ccd026cSArthur Eubanks     return Error::success();
874bb31f73SAlex Zinenko   };
884bb31f73SAlex Zinenko }
89