ldc/runtime/jit-rt/cpp-so/optimizer.cpp
2017-11-05 22:47:10 +03:00

212 lines
7.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//===-- optimizer.cpp -----------------------------------------------------===//
//
// LDC the LLVM D compiler
//
// This file is distributed under the Boost Software License. See the LICENSE
// file for details.
//
//===----------------------------------------------------------------------===//
#include "optimizer.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "context.h"
#include "utils.h"
#include "valueparser.h"
namespace {
void addOptimizationPasses(llvm::legacy::PassManagerBase &mpm,
llvm::legacy::FunctionPassManager &fpm,
unsigned optLevel, unsigned sizeLevel) {
// if (!noVerify) {
// fpm.add(createVerifierPass());
// }
llvm::PassManagerBuilder builder;
builder.OptLevel = optLevel;
builder.SizeLevel = sizeLevel;
if (/*willInline()*/ true) {
unsigned threshold = 225;
if (sizeLevel == 1) { // -Os
threshold = 75;
} else if (sizeLevel == 2) { // -Oz
threshold = 25;
}
if (optLevel > 2) {
threshold = 275;
}
builder.Inliner = llvm::createFunctionInliningPass(threshold);
}
// builder.DisableUnitAtATime = !unitAtATime;
builder.DisableUnrollLoops = optLevel == 0;
// builder.DisableUnrollLoops = (disableLoopUnrolling.getNumOccurrences() >
// 0)
// ? disableLoopUnrolling
// : optLevel == 0;
// This is final, unless there is a #pragma vectorize enable
if (/*disableLoopVectorization*/ false) {
builder.LoopVectorize = false;
// If option wasn't forced via cmd line (-vectorize-loops, -loop-vectorize)
} else if (!builder.LoopVectorize) {
builder.LoopVectorize = optLevel > 1 && sizeLevel < 2;
}
// When #pragma vectorize is on for SLP, do the same as above
builder.SLPVectorize =
/*disableSLPVectorization*/ false ? false : optLevel > 1 && sizeLevel < 2;
// if (opts::sanitize == opts::AddressSanitizer) {
// builder.addExtension(PassManagerBuilder::EP_OptimizerLast,
// addAddressSanitizerPasses);
// builder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
// addAddressSanitizerPasses);
// }
// if (opts::sanitize == opts::MemorySanitizer) {
// builder.addExtension(PassManagerBuilder::EP_OptimizerLast,
// addMemorySanitizerPass);
// builder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
// addMemorySanitizerPass);
// }
// if (opts::sanitize == opts::ThreadSanitizer) {
// builder.addExtension(PassManagerBuilder::EP_OptimizerLast,
// addThreadSanitizerPass);
// builder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
// addThreadSanitizerPass);
// }
// if (!disableLangSpecificPasses) {
// if (!disableSimplifyDruntimeCalls) {
// builder.addExtension(PassManagerBuilder::EP_LoopOptimizerEnd,
// addSimplifyDRuntimeCallsPass);
// }
// if (!disableGCToStack) {
// builder.addExtension(PassManagerBuilder::EP_LoopOptimizerEnd,
// addGarbageCollect2StackPass);
// }
// }
// EP_OptimizerLast does not exist in LLVM 3.0, add it manually below.
// builder.addExtension(llvm::PassManagerBuilder::EP_OptimizerLast,
// addStripExternalsPass);
// addInstrProfilingPass(mpm);
builder.populateFunctionPassManager(fpm);
builder.populateModulePassManager(mpm);
}
void setupPasses(llvm::TargetMachine &targetMachine,
const OptimizerSettings &settings,
llvm::legacy::PassManager &mpm,
llvm::legacy::FunctionPassManager &fpm) {
mpm.add(
new llvm::TargetLibraryInfoWrapperPass(targetMachine.getTargetTriple()));
mpm.add(llvm::createTargetTransformInfoWrapperPass(
targetMachine.getTargetIRAnalysis()));
fpm.add(llvm::createTargetTransformInfoWrapperPass(
targetMachine.getTargetIRAnalysis()));
if (/*stripDebug*/ true) {
mpm.add(llvm::createStripSymbolsPass(true));
}
mpm.add(llvm::createStripDeadPrototypesPass());
mpm.add(llvm::createStripDeadDebugInfoPass());
addOptimizationPasses(mpm, fpm, settings.optLevel, settings.sizeLevel);
}
struct FuncFinalizer final {
llvm::legacy::FunctionPassManager &fpm;
explicit FuncFinalizer(llvm::legacy::FunctionPassManager &_fpm) : fpm(_fpm) {
fpm.doInitialization();
}
~FuncFinalizer() { fpm.doFinalization(); }
};
} // anon namespace
void optimizeModule(const Context &context, llvm::TargetMachine &targetMachine,
const OptimizerSettings &settings, llvm::Module &module) {
llvm::legacy::PassManager mpm;
llvm::legacy::FunctionPassManager fpm(&module);
const auto name = module.getName();
interruptPoint(context, "Setup passes for module", name.data());
setupPasses(targetMachine, settings, mpm, fpm);
// Run per-function passes.
{
FuncFinalizer finalizer(fpm);
for (auto &fun : module) {
if (fun.isDeclaration()) {
interruptPoint(context, "Func decl", fun.getName().data());
} else {
interruptPoint(context, "Run passes for function",
fun.getName().data());
}
fpm.run(fun);
}
}
// Run per-module passes.
interruptPoint(context, "Run passes for module", name.data());
mpm.run(module);
}
void setRtCompileVar(const Context &context, llvm::Module &module,
const char *name, const void *init) {
assert(nullptr != name);
assert(nullptr != init);
auto var = module.getGlobalVariable(name);
if (nullptr != var) {
auto type = var->getType()->getElementType();
auto initializer =
parseInitializer(context, module.getDataLayout(), type, init);
var->setConstant(true);
var->setInitializer(initializer);
var->setLinkage(llvm::GlobalValue::PrivateLinkage);
// auto tempVar = new llvm::GlobalVariable(
// module,
// type,
// true,
// llvm::GlobalValue::PrivateLinkage,
// initializer,
// ".str");
// llvm::Constant *idxs[] = {zero};
// auto constPtr = llvm::ConstantExpr::getGetElementPtr(nullptr,
// tempVar,
// idxs,
// true);
// for (auto&& use: var->uses()) {
// use->dump();
// use->getType()->dump();
// auto i = llvm::cast<llvm::GlobalVariable>(use);
// i->replaceAllUsesWith(constPtr);
// i->eraseFromParent();
// }
// var->replaceAllUsesWith(initializer);
// var->eraseFromParent();
}
}