Denys Shabalin f11e07416a [mlir] Use the same pipeline tuning options as clang for execution engine
This change make sure that ExecutionEngine's pass pipeline is identical to one
used by clang. Previously, SLPVectorization was not enabled which caused
differences in code...

...generation.

Reviewed By: ftynse

Differential Revision: https://reviews.llvm.org/D137248
2022-11-02 15:07:01 +01:00

95 lines
2.8 KiB
C++

//===- 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"
using namespace llvm;
static Optional<OptimizationLevel> 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 None;
}
// Create and return a lambda that uses LLVM pass manager builder to set up
// optimizations based on the given level.
std::function<Error(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());
}
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();
};
}