#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"
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 {
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 (
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
}
std::string
- mangle (const std::string &name)
+ mangle (llvm::StringRef name)
{
std::string ret;
raw_string_ostream out{ret};
{
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);
};
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 */
: TM(TM), ObjectLayer([=] { return std::shared_ptr<RuntimeDyld::MemoryManager> (mm); }),
CompileLayer (ObjectLayer, SimpleCompiler (*TM)),
modules(),
- fpm (NULL) {
- initPassManager ();
- }
-
- void initPassManager () {
- PassRegistry ®istry = *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) {
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 ®istry = *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 ()
{
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