Skip to content

Commit

Permalink
[llvm] Enable optimizations for LLVM 9 JIT. (#34555)
Browse files Browse the repository at this point in the history
Share more code between LLVM 6 and LLVM 9.

Mangler::getNameWithPrefix takes a Twine, not a std::string, so use a
StringRef to avoid an unnecessary allocation.

InstructionCombiningPass grew a dependency on
ProfileSummaryInfoWrapperPass in
dotnet/llvm-project@09e539f,
which depends on the enclosing FunctionPassManager having a valid
reference to a module. This commit adds a dummy module to satisfy this,
instead of recreating a new FunctionPassManager on every compilation.
(See also
http://lists.llvm.org/pipermail/llvm-dev/2019-March/130690.html.)

Co-authored-by: imhameed <imhameed@users.noreply.github.com>
  • Loading branch information
monojenkins and imhameed authored Apr 5, 2020
1 parent 6996928 commit 68625db
Showing 1 changed file with 78 additions and 61 deletions.
139 changes: 78 additions & 61 deletions src/mono/mono/mini/llvm-jit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <llvm/Support/Memory.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/IR/Mangler.h>
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/LegacyPassNameParser.h"
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
Expand Down Expand Up @@ -161,6 +162,38 @@ MonoJitMemoryManager::finalizeMemory(std::string *ErrMsg)
return false;
}

#if defined(TARGET_AMD64) || defined(TARGET_X86)
#define NO_CALL_FRAME_OPT " -no-x86-call-frame-opt"
#else
#define NO_CALL_FRAME_OPT ""
#endif

// The OptimizationList is automatically populated with registered Passes by the
// PassNameParser.
//
static cl::list<const PassInfo*, bool, PassNameParser>
PassList(cl::desc("Optimizations available:"));

static void
init_function_pass_manager (legacy::FunctionPassManager &fpm)
{
auto reg = PassRegistry::getPassRegistry ();
for (size_t i = 0; i < PassList.size(); i++) {
Pass *pass = PassList[i]->getNormalCtor()();
if (pass->getPassKind () == llvm::PT_Function || pass->getPassKind () == llvm::PT_Loop) {
fpm.add (pass);
} else {
auto info = reg->getPassInfo (pass->getPassID());
auto name = info->getPassArgument ();
printf("Opt pass is ignored: %.*s\n", name.size(), name.data());
}
}
// -place-safepoints pass is mandatory
fpm.add (createPlaceSafepointsPass ());

fpm.doInitialization();
}

#if LLVM_API_VERSION >= 900

struct MonoLLVMJIT {
Expand All @@ -171,8 +204,9 @@ struct MonoLLVMJIT {
LegacyRTDyldObjectLinkingLayer object_layer;
LegacyIRCompileLayer<decltype(object_layer), SimpleCompiler> compile_layer;
DataLayout data_layout;
legacy::FunctionPassManager fpm;

MonoLLVMJIT (TargetMachine *tm)
MonoLLVMJIT (TargetMachine *tm, Module *pgo_module)
: mmgr (std::make_shared<MonoJitMemoryManager>())
, target_machine (tm)
, object_layer (
Expand All @@ -185,10 +219,12 @@ struct MonoLLVMJIT {
AcknowledgeORCv1Deprecation, object_layer,
SimpleCompiler{*target_machine})
, data_layout (target_machine->createDataLayout())
, fpm (pgo_module)
{
compile_layer.setNotifyCompiled ([] (VModuleKey, std::unique_ptr<Module> module) {
module.release ();
});
init_function_pass_manager (fpm);
}

VModuleKey
Expand Down Expand Up @@ -232,7 +268,7 @@ struct MonoLLVMJIT {
}

std::string
mangle (const std::string &name)
mangle (llvm::StringRef name)
{
std::string ret;
raw_string_ostream out{ret};
Expand All @@ -256,8 +292,9 @@ struct MonoLLVMJIT {
{
auto module = func->getParent ();
module->setDataLayout (data_layout);
// The lifetime of this module is managed by the C API, and the
// `unique_ptr` created here will be released in the
fpm.run (*func);
// The lifetime of this module is managed by Mono, not LLVM, so
// the `unique_ptr` created here will be released in the
// NotifyCompiled callback.
auto k = add_module (std::unique_ptr<Module>(module));
auto bodysym = compile_layer.findSymbolIn (k, mangle (func), false);
Expand All @@ -279,25 +316,13 @@ struct MonoLLVMJIT {
};

static MonoLLVMJIT *
make_mono_llvm_jit (TargetMachine *target_machine)
make_mono_llvm_jit (TargetMachine *target_machine, llvm::Module *pgo_module)
{
return new MonoLLVMJIT{target_machine};
return new MonoLLVMJIT{target_machine, pgo_module};
}

#elif LLVM_API_VERSION > 600

#if defined(TARGET_AMD64) || defined(TARGET_X86)
#define NO_CALL_FRAME_OPT " -no-x86-call-frame-opt"
#else
#define NO_CALL_FRAME_OPT ""
#endif

// The OptimizationList is automatically populated with registered Passes by the
// PassNameParser.
//
static cl::list<const PassInfo*, bool, PassNameParser>
PassList(cl::desc("Optimizations available:"));

class MonoLLVMJIT {
public:
/* We use our own trampoline infrastructure instead of the Orc one */
Expand All @@ -309,46 +334,9 @@ class MonoLLVMJIT {
: TM(TM), ObjectLayer([=] { return std::shared_ptr<RuntimeDyld::MemoryManager> (mm); }),
CompileLayer (ObjectLayer, SimpleCompiler (*TM)),
modules(),
fpm (NULL) {
initPassManager ();
}

void initPassManager () {
PassRegistry &registry = *PassRegistry::getPassRegistry();
initializeCore(registry);
initializeScalarOpts(registry);
initializeInstCombine(registry);
initializeTarget(registry);
initializeLoopIdiomRecognizeLegacyPassPass(registry);

// FIXME: find optimal mono specific order of passes
// see https://llvm.org/docs/Frontend/PerformanceTips.html#pass-ordering
// the following order is based on a stripped version of "OPT -O2"
const char *default_opts = " -simplifycfg -sroa -lower-expect -instcombine -jump-threading -loop-rotate -licm -simplifycfg -lcssa -loop-idiom -indvars -loop-deletion -gvn -memcpyopt -sccp -bdce -instcombine -dse -simplifycfg -enable-implicit-null-checks" NO_CALL_FRAME_OPT;
const char *opts = g_getenv ("MONO_LLVM_OPT");
if (opts == NULL)
opts = default_opts;
else if (opts[0] == '+') // Append passes to the default order if starts with '+', overwrite otherwise
opts = g_strdup_printf ("%s %s", default_opts, opts + 1);
else if (opts[0] != ' ') // pass order has to start with a leading whitespace
opts = g_strdup_printf (" %s", opts);

char **args = g_strsplit (opts, " ", -1);
llvm::cl::ParseCommandLineOptions (g_strv_length (args), args, "");

for (size_t i = 0; i < PassList.size(); i++) {
Pass *pass = PassList[i]->getNormalCtor()();
if (pass->getPassKind () == llvm::PT_Function || pass->getPassKind () == llvm::PT_Loop) {
fpm.add (pass);
} else {
printf("Opt pass is ignored: %s\n", args[i + 1]);
}
}
// -place-safepoints pass is mandatory
fpm.add (createPlaceSafepointsPass ());

g_strfreev (args);
fpm.doInitialization();
fpm (nullptr)
{
init_function_pass_manager (fpm);
}

ModuleHandleT addModule(Function *F, std::shared_ptr<Module> M) {
Expand Down Expand Up @@ -445,16 +433,44 @@ class MonoLLVMJIT {
static MonoJitMemoryManager *mono_mm;

static MonoLLVMJIT *
make_mono_llvm_jit (TargetMachine *target_machine)
make_mono_llvm_jit (TargetMachine *target_machine, llvm::Module *)
{
mono_mm = new MonoJitMemoryManager ();
return new MonoLLVMJIT(target_machine, mono_mm);
}

#endif

static llvm::Module *dummy_pgo_module = nullptr;
static MonoLLVMJIT *jit;

static void
init_passes_and_options ()
{
PassRegistry &registry = *PassRegistry::getPassRegistry();
initializeCore(registry);
initializeScalarOpts(registry);
initializeInstCombine(registry);
initializeTarget(registry);
initializeLoopIdiomRecognizeLegacyPassPass(registry);

// FIXME: find optimal mono specific order of passes
// see https://llvm.org/docs/Frontend/PerformanceTips.html#pass-ordering
// the following order is based on a stripped version of "OPT -O2"
const char *default_opts = " -simplifycfg -sroa -lower-expect -instcombine -jump-threading -loop-rotate -licm -simplifycfg -lcssa -loop-idiom -indvars -loop-deletion -gvn -memcpyopt -sccp -bdce -instcombine -dse -simplifycfg -enable-implicit-null-checks" NO_CALL_FRAME_OPT;
const char *opts = g_getenv ("MONO_LLVM_OPT");
if (opts == NULL)
opts = default_opts;
else if (opts[0] == '+') // Append passes to the default order if starts with '+', overwrite otherwise
opts = g_strdup_printf ("%s %s", default_opts, opts + 1);
else if (opts[0] != ' ') // pass order has to start with a leading whitespace
opts = g_strdup_printf (" %s", opts);

char **args = g_strsplit (opts, " ", -1);
llvm::cl::ParseCommandLineOptions (g_strv_length (args), args, "");
g_strfreev (args);
}

void
mono_llvm_jit_init ()
{
Expand Down Expand Up @@ -499,8 +515,9 @@ mono_llvm_jit_init ()

auto TM = EB.selectTarget ();
assert (TM);

jit = make_mono_llvm_jit (TM);
dummy_pgo_module = unwrap (LLVMModuleCreateWithName("dummy-pgo-module"));
init_passes_and_options ();
jit = make_mono_llvm_jit (TM, dummy_pgo_module);
}

MonoEERef
Expand Down

0 comments on commit 68625db

Please sign in to comment.