#include <llvm/Support/Host.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/IR/Mangler.h>
+#include "llvm/IR/LegacyPassNameParser.h"
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/Transforms/Scalar.h"
#include <cstdlib>
}
static MonoLLVMJIT *
-make_mono_llvm_jit (TargetMachine *target_machine)
+make_mono_llvm_jit (TargetMachine *target_machine, LLVMModuleProviderRef mp)
{
return new MonoLLVMJIT{target_machine};
}
#elif LLVM_API_VERSION > 600
+// 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 */
typedef IRCompileLayer<ObjLayerT, SimpleCompiler> CompileLayerT;
typedef CompileLayerT::ModuleHandleT ModuleHandleT;
- MonoLLVMJIT (TargetMachine *TM, MonoJitMemoryManager *mm)
+ MonoLLVMJIT (TargetMachine *TM, MonoJitMemoryManager *mm, LLVMModuleProviderRef mp)
: TM(TM), ObjectLayer([=] { return std::shared_ptr<RuntimeDyld::MemoryManager> (mm); }),
CompileLayer (ObjectLayer, SimpleCompiler (*TM)),
- modules() {
+ modules(),
+ fpm (unwrap (mp)) {
+ initPassManager ();
+ }
+
+ void initPassManager () {
+ // Initialize passes (copied from https://github.com/mono/llvm/blob/release_60/tools/opt/opt.cpp#L379)
+ PassRegistry ®istry = *PassRegistry::getPassRegistry();
+ initializeCore(registry);
+ //initializeCoroutines(registry);
+ initializeScalarOpts(registry);
+ //initializeObjCARCOpts(registry);
+ //initializeVectorization(registry);
+ //initializeIPO(registry);
+ initializeAnalysis(registry);
+ initializeTransformUtils(registry);
+ initializeInstCombine(registry);
+ //initializeInstrumentation(registry);
+ initializeTarget(registry);
+ //initializeExpandMemCmpPassPass(registry);
+ //initializeScalarizeMaskedMemIntrinPass(registry);
+ //initializeCodeGenPreparePass(registry);
+ //initializeAtomicExpandPass(registry);
+ //initializeRewriteSymbolsLegacyPassPass(registry);
+ //initializeWinEHPreparePass(registry);
+ //initializeDwarfEHPreparePass(registry);
+ //initializeSafeStackLegacyPassPass(registry);
+ //initializeSjLjEHPreparePass(registry);
+ //initializePreISelIntrinsicLoweringLegacyPassPass(registry);
+ //initializeGlobalMergePass(registry);
+ //initializeIndirectBrExpandPassPass(registry);
+ //initializeInterleavedAccessPass(registry);
+ //initializeEntryExitInstrumenterPass(registry);
+ //initializePostInlineEntryExitInstrumenterPass(registry);
+ //initializeUnreachableBlockElimLegacyPassPass(registry);
+ //initializeExpandReductionsPass(registry);
+ //initializeWriteBitcodePassPass(registry);
+
+ // FIXME: find optimal mono specific order of passes, see https://llvm.org/docs/Frontend/PerformanceTips.html#pass-ordering
+ const char *opts = "opt -simplifycfg -sroa -instcombine -early-cse-memssa -instcombine -gvn";
+ char **args = g_strsplit (opts, " ", -1);
+ llvm::cl::ParseCommandLineOptions (g_strv_length (args), args, "");
+
+ for (int 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 not supported: %s\n", args[i + 1]);
+ }
+ }
+ g_strfreev (args);
+ fpm.doInitialization();
}
ModuleHandleT addModule(Function *F, std::shared_ptr<Module> M) {
gpointer compile (Function *F, int nvars, LLVMValueRef *callee_vars, gpointer *callee_addrs, gpointer *eh_frame) {
F->getParent ()->setDataLayout (TM->createDataLayout ());
+ fpm.run(*F);
// Orc uses a shared_ptr to refer to modules so we have to save them ourselves to keep a ref
std::shared_ptr<Module> m (F->getParent ());
modules.push_back (m);
ObjLayerT ObjectLayer;
CompileLayerT CompileLayer;
std::vector<std::shared_ptr<Module>> modules;
+ legacy::FunctionPassManager fpm;
};
static MonoJitMemoryManager *mono_mm;
}
static MonoLLVMJIT *
-make_mono_llvm_jit (TargetMachine *target_machine)
+make_mono_llvm_jit (TargetMachine *target_machine, LLVMModuleProviderRef mp)
{
- return new MonoLLVMJIT(target_machine, mono_mm);
+ return new MonoLLVMJIT(target_machine, mono_mm, mp);
}
#endif
assert (TM);
init_mono_llvm_jit ();
- jit = make_mono_llvm_jit (TM);
+ jit = make_mono_llvm_jit (TM, MP);
return NULL;
}