Mercurial > projects > ldc
view gen/optimizer.cpp @ 1650:40bd4a0d4870
Update to work with LLVM 2.7.
Removed use of dyn_cast, llvm no compiles
without exceptions and rtti by
default. We do need exceptions for the libconfig stuff, but rtti isn't
necessary (anymore).
Debug info needs to be rewritten, as in LLVM 2.7 the format has
completely changed. To have something to look at while rewriting, the
old code has been wrapped inside #ifndef DISABLE_DEBUG_INFO , this means
that you have to define this to compile at the moment.
Updated tango 0.99.9 patch to include updated EH runtime code, which is
needed for LLVM 2.7 as well.
author | Tomas Lindquist Olsen |
---|---|
date | Wed, 19 May 2010 12:42:32 +0200 |
parents | 4551475bc6b6 |
children |
line wrap: on
line source
#include "gen/optimizer.h" #include "gen/cl_helpers.h" #include "gen/passes/Passes.h" #include "llvm/PassManager.h" #include "llvm/LinkAllPasses.h" #include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Target/TargetData.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/PassNameParser.h" #include "root.h" // error() #include <cstring> // strcmp(); using namespace llvm; // Allow the user to specify specific optimizations to run. static cl::list<const PassInfo*, bool, PassNameParser> passList( cl::desc("Running specific optimizations:"), cl::Hidden // to clean up --help output ); static cl::opt<unsigned char> optimizeLevel( cl::desc("Setting the optimization level:"), cl::ZeroOrMore, cl::values( clEnumValN(2, "O", "Equivalent to -O2"), clEnumValN(0, "O0", "No optimizations (default)"), clEnumValN(1, "O1", "Simple optimizations"), clEnumValN(2, "O2", "Good optimizations"), clEnumValN(3, "O3", "Aggressive optimizations"), clEnumValN(4, "O4", "Link-time optimization"), // not implemented? clEnumValN(5, "O5", "Link-time optimization"), // not implemented? clEnumValEnd), cl::init(0)); static cl::opt<bool> verifyEach("verify-each", cl::desc("Run verifier after each optimization pass"), cl::Hidden, cl::ZeroOrMore); static cl::opt<bool> disableLangSpecificPasses("disable-d-passes", cl::desc("Disable D-specific passes in -O<N>"), cl::ZeroOrMore); static cl::opt<bool> disableSimplifyRuntimeCalls("disable-simplify-drtcalls", cl::desc("Disable simplification of runtime calls in -O<N>"), cl::ZeroOrMore); static cl::opt<bool> disableGCToStack("disable-gc2stack", cl::desc("Disable promotion of GC allocations to stack memory in -O<N>"), cl::ZeroOrMore); static cl::opt<opts::BoolOrDefaultAdapter, false, opts::FlagParser> enableInlining("inlining", cl::desc("(*) Enable function inlining in -O<N>"), cl::ZeroOrMore); // Determine whether or not to run the inliner as part of the default list of // optimization passes. // If not explicitly specified, treat as false for -O0-2, and true for -O3. bool doInline() { return enableInlining == cl::BOU_TRUE || (enableInlining == cl::BOU_UNSET && optimizeLevel >= 3); } // Determine whether the inliner will be run. bool willInline() { if (doInline()) return true; // It may also have been specified explicitly on the command line as an explicit pass typedef cl::list<const PassInfo*, bool, PassNameParser> PL; for (PL::iterator I = passList.begin(), E = passList.end(); I != E; ++I) { if (!std::strcmp((*I)->getPassArgument(), "inline")) return true; } return false; } // Some extra accessors for the linker: (llvm-ld version only, currently unused?) int optLevel() { return optimizeLevel; } bool optimize() { return optimizeLevel || doInline() || !passList.empty(); } static void addPass(PassManager& pm, Pass* pass) { pm.add(pass); if (verifyEach) pm.add(createVerifierPass()); } // this function inserts some or all of the std-compile-opts passes depending on the // optimization level given. static void addPassesForOptLevel(PassManager& pm) { // -O1 if (optimizeLevel >= 1) { //addPass(pm, createStripDeadPrototypesPass()); addPass(pm, createGlobalDCEPass()); addPass(pm, createPromoteMemoryToRegisterPass()); addPass(pm, createCFGSimplificationPass()); if (optimizeLevel == 1) addPass(pm, createPromoteMemoryToRegisterPass()); else addPass(pm, createScalarReplAggregatesPass()); addPass(pm, createGlobalOptimizerPass()); } // -O2 if (optimizeLevel >= 2) { addPass(pm, createIPConstantPropagationPass()); addPass(pm, createDeadArgEliminationPass()); addPass(pm, createInstructionCombiningPass()); addPass(pm, createCFGSimplificationPass()); addPass(pm, createPruneEHPass()); addPass(pm, createFunctionAttrsPass()); addPass(pm, createTailCallEliminationPass()); addPass(pm, createCFGSimplificationPass()); addPass(pm, createGVNPass()); } // -inline if (doInline()) { addPass(pm, createFunctionInliningPass()); if (optimizeLevel >= 2) { // Run some optimizations to clean up after inlining. addPass(pm, createScalarReplAggregatesPass()); addPass(pm, createInstructionCombiningPass()); // -instcombine + gvn == devirtualization :) addPass(pm, createGVNPass()); // Inline again, to catch things like now nonvirtual // function calls, foreach delegates passed to inlined // opApply's, etc. where the actual function being called // wasn't known during the first inliner pass. addPass(pm, createFunctionInliningPass()); } } if (optimizeLevel >= 2) { if (!disableLangSpecificPasses) { if (!disableSimplifyRuntimeCalls) addPass(pm, createSimplifyDRuntimeCalls()); #if USE_METADATA if (!disableGCToStack) addPass(pm, createGarbageCollect2Stack()); #endif // USE_METADATA } // Run some clean-up passes addPass(pm, createInstructionCombiningPass()); addPass(pm, createScalarReplAggregatesPass()); addPass(pm, createCFGSimplificationPass()); addPass(pm, createInstructionCombiningPass()); } // -O3 if (optimizeLevel >= 3) { addPass(pm, createArgumentPromotionPass()); addPass(pm, createTailDuplicationPass()); addPass(pm, createSimplifyLibCallsPass()); addPass(pm, createInstructionCombiningPass()); addPass(pm, createJumpThreadingPass()); addPass(pm, createCFGSimplificationPass()); addPass(pm, createScalarReplAggregatesPass()); addPass(pm, createInstructionCombiningPass()); addPass(pm, createConstantPropagationPass()); addPass(pm, createReassociatePass()); addPass(pm, createLoopRotatePass()); addPass(pm, createLICMPass()); addPass(pm, createLoopUnswitchPass()); addPass(pm, createLoopIndexSplitPass()); addPass(pm, createInstructionCombiningPass()); addPass(pm, createIndVarSimplifyPass()); addPass(pm, createLoopDeletionPass()); addPass(pm, createLoopUnrollPass()); addPass(pm, createInstructionCombiningPass()); addPass(pm, createGVNPass()); addPass(pm, createMemCpyOptPass()); addPass(pm, createSCCPPass()); addPass(pm, createInstructionCombiningPass()); addPass(pm, createConstantPropagationPass()); addPass(pm, createDeadStoreEliminationPass()); addPass(pm, createAggressiveDCEPass()); addPass(pm, createCFGSimplificationPass()); addPass(pm, createDeadTypeEliminationPass()); addPass(pm, createConstantMergePass()); } if (optimizeLevel >= 1) { addPass(pm, createStripExternalsPass()); addPass(pm, createGlobalDCEPass()); } // level -O4 and -O5 are linktime optimizations } ////////////////////////////////////////////////////////////////////////////////////////// // This function runs optimization passes based on command line arguments. // Returns true if any optimization passes were invoked. bool ldc_optimize_module(llvm::Module* m) { if (!optimize()) return false; PassManager pm; if (verifyEach) pm.add(createVerifierPass()); addPass(pm, new TargetData(m)); bool optimize = optimizeLevel != 0 || doInline(); unsigned optPos = optimizeLevel != 0 ? optimizeLevel.getPosition() : enableInlining.getPosition(); for (size_t i = 0; i < passList.size(); i++) { // insert -O<N> / -enable-inlining in right position if (optimize && optPos < passList.getPosition(i)) { addPassesForOptLevel(pm); optimize = false; } const PassInfo* pass = passList[i]; if (PassInfo::NormalCtor_t ctor = pass->getNormalCtor()) { addPass(pm, ctor()); } else { const char* arg = pass->getPassArgument(); // may return null if (arg) error("Can't create pass '-%s' (%s)", arg, pass->getPassName()); else error("Can't create pass (%s)", pass->getPassName()); assert(0); // Should be unreachable; root.h:error() calls exit() } } // insert -O<N> / -enable-inlining if specified at the end, if (optimize) addPassesForOptLevel(pm); pm.run(*m); return true; }