mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-02-26 08:33:14 +01:00
Allow specific optimization passes to be requested from the command line.
Now you can run "`ldc test.d -c -mem2reg -simplifycfg`" if you feel the urge. The -O<N> options are still supported, and are inserted in the passes list in the position where they appear on the command line. (so -simplifycfg -O1 -instcombine does the "right thing") One small change: -inline is renamed to -enable-inlining due to a naming conflict with the option to add the -inline pass. -inline now inserts the inlining pass in the position specified, not in the middle of -O<N>. (ldmd has been updated to translate -inline to -enable-inlining)
This commit is contained in:
8
bin/ldmd
8
bin/ldmd
@@ -17,9 +17,17 @@ declare -a ARGS
|
||||
IDX=0
|
||||
for arg; do
|
||||
case "$arg" in
|
||||
-C*)
|
||||
# turn -Cfoo into -foo.
|
||||
# Useful for passing -inline to ldc, for instance.
|
||||
arg="-${arg:2}"
|
||||
;;
|
||||
-debug|-debug=*|-version=*)
|
||||
arg="-d$arg"
|
||||
;;
|
||||
-inline)
|
||||
arg="-enable-inlining"
|
||||
;;
|
||||
-fPIC)
|
||||
arg="-relocation-model=pic"
|
||||
;;
|
||||
|
||||
@@ -138,8 +138,11 @@ struct Param
|
||||
bool link; // perform link
|
||||
bool verbose; // verbose compile
|
||||
char symdebug; // insert debug symbolic information
|
||||
#if !IN_LLVM
|
||||
// LDC uses a different mechanism
|
||||
bool optimize; // run optimizer
|
||||
char optimizeLevel; // optimization level
|
||||
#endif
|
||||
ARCH cpu; // target CPU
|
||||
OS os; // target OS
|
||||
bool is64bit; // generate 64 bit code
|
||||
@@ -210,7 +213,6 @@ struct Param
|
||||
OUTPUTFLAG output_bc;
|
||||
OUTPUTFLAG output_s;
|
||||
OUTPUTFLAG output_o;
|
||||
bool llvmInline;
|
||||
bool llvmAnnotate;
|
||||
bool useInlineAsm;
|
||||
|
||||
|
||||
@@ -73,8 +73,11 @@ struct Param
|
||||
bool link; // perform link
|
||||
bool verbose; // verbose compile
|
||||
char symdebug; // insert debug symbolic information
|
||||
#if !IN_LLVM
|
||||
// LDC uses a different mechanism
|
||||
bool optimize; // run optimizer
|
||||
char optimizeLevel; // optimization level
|
||||
#endif
|
||||
ARCH cpu; // target CPU
|
||||
OS os; // target OS
|
||||
bool is64bit; // generate 64 bit code
|
||||
@@ -145,7 +148,6 @@ struct Param
|
||||
OUTPUTFLAG output_bc;
|
||||
OUTPUTFLAG output_s;
|
||||
OUTPUTFLAG output_o;
|
||||
bool llvmInline;
|
||||
bool llvmAnnotate;
|
||||
bool useInlineAsm;
|
||||
|
||||
|
||||
@@ -20,16 +20,6 @@ cl::list<std::string> runargs("run",
|
||||
cl::PositionalEatsArgs);
|
||||
|
||||
|
||||
|
||||
// TODO: Replace this with a proper PassNameParser-based solution
|
||||
static cl::opt<bool, true> doInline("inline",
|
||||
cl::desc("Do function inlining"),
|
||||
cl::location(global.params.llvmInline),
|
||||
cl::ZeroOrMore,
|
||||
cl::init(false));
|
||||
|
||||
|
||||
|
||||
static cl::opt<bool, true> useDeprecated("d",
|
||||
cl::desc("Allow deprecated language features"),
|
||||
cl::ZeroOrMore,
|
||||
@@ -59,22 +49,6 @@ static cl::opt<bool, true> warnings("w",
|
||||
cl::ZeroOrMore,
|
||||
cl::location(global.params.warnings));
|
||||
|
||||
|
||||
static cl::opt<char, true> optimizeLevel(
|
||||
cl::desc("Setting the optimization level:"),
|
||||
cl::ZeroOrMore,
|
||||
cl::values(
|
||||
clEnumValN(2, "O", "Equivalent to -O2"),
|
||||
clEnumValN(0, "O0", "Trivial optimizations only"),
|
||||
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::location(global.params.optimizeLevel),
|
||||
cl::init(-1));
|
||||
|
||||
static cl::opt<char, true> debugInfo(
|
||||
cl::desc("Generating debug information:"),
|
||||
cl::ZeroOrMore,
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#define NO_COUT_LOGGER
|
||||
#include "gen/logger.h"
|
||||
#include "gen/cl_options.h"
|
||||
#include "gen/optimizer.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -111,12 +112,12 @@ int linkExecutable(const char* argv0)
|
||||
args.push_back("-strip-debug");
|
||||
|
||||
// optimization level
|
||||
if (!global.params.optimize)
|
||||
if (!optimize())
|
||||
args.push_back("-disable-opt");
|
||||
else
|
||||
{
|
||||
const char* s = 0;
|
||||
switch(global.params.optimizeLevel)
|
||||
switch(optLevel())
|
||||
{
|
||||
case 0:
|
||||
args.push_back("-disable-opt");
|
||||
@@ -138,7 +139,7 @@ int linkExecutable(const char* argv0)
|
||||
}
|
||||
|
||||
// inlining
|
||||
if (!(global.params.useInline || global.params.llvmInline))
|
||||
if (!(global.params.useInline || doInline()))
|
||||
{
|
||||
args.push_back("-disable-inlining");
|
||||
}
|
||||
|
||||
@@ -192,8 +192,6 @@ int main(int argc, char** argv)
|
||||
cl::SetVersionPrinter(&printVersion);
|
||||
cl::ParseCommandLineOptions(final_args.size(), (char**)&final_args[0], "LLVM-based D Compiler\n", true);
|
||||
|
||||
global.params.optimize = (global.params.optimizeLevel >= 0);
|
||||
|
||||
// Negated options
|
||||
global.params.link = !compileOnly;
|
||||
global.params.obj = !dontWriteObj;
|
||||
|
||||
@@ -1,32 +1,68 @@
|
||||
#include "gen/optimizer.h"
|
||||
|
||||
#include "llvm/PassManager.h"
|
||||
#include "llvm/LinkAllPasses.h"
|
||||
#include "llvm/Analysis/LoopPass.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/PassNameParser.h"
|
||||
|
||||
#include "root.h" // error() & fatal()
|
||||
#include "mars.h" // global flags
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
// this function runs some or all of the std-compile-opts passes depending on the
|
||||
static cl::opt<char> optimizeLevel(
|
||||
cl::desc("Setting the optimization level:"),
|
||||
cl::ZeroOrMore,
|
||||
cl::values(
|
||||
clEnumValN(2, "O", "Equivalent to -O2"),
|
||||
clEnumValN(0, "O0", "Trivial optimizations only"),
|
||||
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(-1));
|
||||
|
||||
static cl::opt<bool> enableInlining("enable-inlining",
|
||||
cl::desc("Enable function inlining (in -O<N>, if given)"),
|
||||
cl::ZeroOrMore,
|
||||
cl::init(false));
|
||||
|
||||
// Some accessors for the linker: (llvm-ld version only, currently unused?)
|
||||
bool doInline() {
|
||||
return enableInlining;
|
||||
}
|
||||
|
||||
int optLevel() {
|
||||
return optimizeLevel;
|
||||
}
|
||||
|
||||
bool optimize() {
|
||||
return (optimizeLevel != -1) || enableInlining || passList.empty();
|
||||
}
|
||||
|
||||
// this function inserts some or all of the std-compile-opts passes depending on the
|
||||
// optimization level given.
|
||||
|
||||
void ldc_optimize_module(Module* m, char lvl, bool doinline)
|
||||
{
|
||||
if (!doinline && lvl < 0)
|
||||
return;
|
||||
|
||||
PassManager pm;
|
||||
pm.add(new TargetData(m));
|
||||
|
||||
static void addPassesForOptLevel(PassManager& pm) {
|
||||
// -O0
|
||||
if (lvl >= 0)
|
||||
if (optimizeLevel >= 0)
|
||||
{
|
||||
//pm.add(createStripDeadPrototypesPass());
|
||||
pm.add(createGlobalDCEPass());
|
||||
}
|
||||
|
||||
// -O1
|
||||
if (lvl >= 1)
|
||||
if (optimizeLevel >= 1)
|
||||
{
|
||||
pm.add(createRaiseAllocationsPass());
|
||||
pm.add(createCFGSimplificationPass());
|
||||
@@ -36,7 +72,7 @@ void ldc_optimize_module(Module* m, char lvl, bool doinline)
|
||||
}
|
||||
|
||||
// -O2
|
||||
if (lvl >= 2)
|
||||
if (optimizeLevel >= 2)
|
||||
{
|
||||
pm.add(createIPConstantPropagationPass());
|
||||
pm.add(createDeadArgEliminationPass());
|
||||
@@ -46,12 +82,12 @@ void ldc_optimize_module(Module* m, char lvl, bool doinline)
|
||||
}
|
||||
|
||||
// -inline
|
||||
if (doinline) {
|
||||
if (enableInlining) {
|
||||
pm.add(createFunctionInliningPass());
|
||||
}
|
||||
|
||||
// -O3
|
||||
if (lvl >= 3)
|
||||
if (optimizeLevel >= 3)
|
||||
{
|
||||
pm.add(createArgumentPromotionPass());
|
||||
pm.add(createTailDuplicationPass());
|
||||
@@ -86,6 +122,48 @@ void ldc_optimize_module(Module* m, char lvl, bool doinline)
|
||||
}
|
||||
|
||||
// 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 (!enableInlining && optimizeLevel == -1 && passList.empty())
|
||||
return false;
|
||||
|
||||
PassManager pm;
|
||||
pm.add(new TargetData(m));
|
||||
|
||||
bool optimize = (optimizeLevel != -1) || enableInlining;
|
||||
|
||||
unsigned optPos = optimizeLevel != -1
|
||||
? 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()) {
|
||||
pm.add(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());
|
||||
fatal();
|
||||
}
|
||||
}
|
||||
// insert -O<N> / -enable-inlining if specified at the end,
|
||||
if (optimize)
|
||||
addPassesForOptLevel(pm);
|
||||
|
||||
pm.run(*m);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "gen/runtime.h"
|
||||
#include "gen/abi.h"
|
||||
#include "gen/cl_options.h"
|
||||
#include "gen/optimizer.h"
|
||||
|
||||
#include "ir/irvar.h"
|
||||
#include "ir/irmodule.h"
|
||||
@@ -61,9 +62,6 @@ static llvm::cl::opt<bool> noVerify("noverify",
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// in gen/optimize.cpp
|
||||
void ldc_optimize_module(llvm::Module* m, char lvl, bool doinline);
|
||||
|
||||
// fwd decl
|
||||
void write_asm_to_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_fd_ostream& Out);
|
||||
void assemble(const llvm::sys::Path& asmpath, const llvm::sys::Path& objpath);
|
||||
@@ -189,10 +187,10 @@ llvm::Module* Module::genLLVMModule(Ir* sir)
|
||||
void writeModule(llvm::Module* m, std::string filename)
|
||||
{
|
||||
// run optimizer
|
||||
ldc_optimize_module(m, global.params.optimizeLevel, global.params.llvmInline);
|
||||
bool reverify = ldc_optimize_module(m);
|
||||
|
||||
// verify the llvm
|
||||
if (!noVerify && (global.params.optimizeLevel >= 0 || global.params.llvmInline)) {
|
||||
if (!noVerify && reverify) {
|
||||
std::string verifyErr;
|
||||
Logger::println("Verifying module... again...");
|
||||
LOG_SCOPE;
|
||||
|
||||
Reference in New Issue
Block a user