On Wednesday, February 7, 2018 3:54:05 PM CET Andres Freund wrote: > Hi, > > I've pushed v10.0. The big (and pretty painful to make) change is that > now all the LLVM specific code lives in src/backend/jit/llvm, which is > built as a shared library which is loaded on demand. > > The layout is now as follows: > > src/backend/jit/jit.c: > Part of JITing always linked into the server. Supports loading the > LLVM using JIT library. > > src/backend/jit/llvm/ > Infrastructure: > llvmjit.c: > General code generation and optimization infrastructure > llvmjit_error.cpp, llvmjit_wrap.cpp: > Error / backward compat wrappers > llvmjit_inline.cpp: > Cross module inlining support > Code-Gen: > llvmjit_expr.c > Expression compilation > llvmjit_deform.c > Deform compilation > > I generally like how this shaped out. There's a good amount of followup > cleanup needed, but I'd appreciate some early feedback.
Hi I also find it more readable and it looks cleaner, insane guys could be able to write their own JIT engines for PostgreSQL by patching a single file :) Since it's now in its own .so file, does it still make as much sense using mostly the LLVM C API ? I'll really look in the jit code itself later, right now I've just rebased my previous patches and did a quick check that everything worked for LLVM4 and 3.9. I included a small addition to the gitignore file, I'm surprised you were not bothered by the various .bc files generated. Anyway, great work, and I look forward exploring the code :) Pierre
>From f461c3d6d0deec52b66f3276a87cfdb3ab65b259 Mon Sep 17 00:00:00 2001 From: Pierre <pierre.ducroq...@people-doc.com> Date: Fri, 2 Feb 2018 09:11:55 +0100 Subject: [PATCH 1/8] Add support for LLVM4 in llvmjit.c --- src/backend/jit/llvm/llvmjit.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c index a1bc6449f7..e81764af98 100644 --- a/src/backend/jit/llvm/llvmjit.c +++ b/src/backend/jit/llvm/llvmjit.c @@ -215,12 +215,19 @@ llvm_get_function(LLVMJitContext *context, const char *funcname) addr = 0; if (LLVMOrcGetSymbolAddressIn(handle->stack, &addr, handle->orc_handle, mangled)) - elog(ERROR, "failed to lookup symbol"); + elog(ERROR, "failed to lookup symbol %s", mangled); if (addr) return (void *) addr; } #endif +#if LLVM_VERSION_MAJOR < 5 + if ((addr = LLVMOrcGetSymbolAddress(llvm_opt0_orc, mangled))) + return (void *) addr; + if ((addr = LLVMOrcGetSymbolAddress(llvm_opt3_orc, mangled))) + return (void *) addr; + elog(ERROR, "failed to lookup symbol %s for %s", mangled, funcname); +#else if (LLVMOrcGetSymbolAddress(llvm_opt0_orc, &addr, mangled)) elog(ERROR, "failed to lookup symbol"); if (addr) @@ -229,7 +236,7 @@ llvm_get_function(LLVMJitContext *context, const char *funcname) elog(ERROR, "failed to lookup symbol"); if (addr) return (void *) addr; - +#endif elog(ERROR, "failed to JIT: %s", funcname); return NULL; @@ -365,11 +372,18 @@ llvm_compile_module(LLVMJitContext *context) * faster instruction selection mechanism is used. */ { - LLVMSharedModuleRef smod; instr_time tb, ta; /* emit the code */ INSTR_TIME_SET_CURRENT(ta); +#if LLVM_VERSION_MAJOR < 5 + orc_handle = LLVMOrcAddEagerlyCompiledIR(compile_orc, context->module, + llvm_resolve_symbol, NULL); + // It seems there is no error return from that function in LLVM < 5. +#else + LLVMSharedModuleRef smod; + + LLVMSharedModuleRef smod; smod = LLVMOrcMakeSharedModule(context->module); if (LLVMOrcAddEagerlyCompiledIR(compile_orc, &orc_handle, smod, llvm_resolve_symbol, NULL)) @@ -377,6 +391,7 @@ llvm_compile_module(LLVMJitContext *context) elog(ERROR, "failed to jit module"); } LLVMOrcDisposeSharedModuleRef(smod); +#endif INSTR_TIME_SET_CURRENT(tb); INSTR_TIME_SUBTRACT(tb, ta); ereport(DEBUG1, (errmsg("time to emit: %.3fs", -- 2.16.1
>From 7c34e2264edad3d2d99ba2ba6fbf41ec3a73e0ed Mon Sep 17 00:00:00 2001 From: Pierre <pierre.ducroq...@people-doc.com> Date: Fri, 2 Feb 2018 09:13:40 +0100 Subject: [PATCH 2/8] Add LLVM4 support in llvmjit_error.cpp --- src/backend/jit/llvm/llvmjit_error.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/backend/jit/llvm/llvmjit_error.cpp b/src/backend/jit/llvm/llvmjit_error.cpp index 625ba2d25d..1c78bd956d 100644 --- a/src/backend/jit/llvm/llvmjit_error.cpp +++ b/src/backend/jit/llvm/llvmjit_error.cpp @@ -56,7 +56,9 @@ llvm_enter_fatal_on_oom(void) if (fatal_new_handler_depth == 0) { old_new_handler = std::set_new_handler(fatal_system_new_handler); +#if LLVM_VERSION_MAJOR > 4 llvm::install_bad_alloc_error_handler(fatal_llvm_new_handler); +#endif llvm::install_fatal_error_handler(fatal_llvm_error_handler); } fatal_new_handler_depth++; @@ -72,7 +74,9 @@ llvm_leave_fatal_on_oom(void) if (fatal_new_handler_depth == 0) { std::set_new_handler(old_new_handler); +#if LLVM_VERSION_MAJOR > 4 llvm::remove_bad_alloc_error_handler(); +#endif llvm::remove_fatal_error_handler(); } } @@ -87,7 +91,9 @@ llvm_reset_after_error(void) if (fatal_new_handler_depth != 0) { std::set_new_handler(old_new_handler); +#if LLVM_VERSION_MAJOR > 4 llvm::remove_bad_alloc_error_handler(); +#endif llvm::remove_fatal_error_handler(); } fatal_new_handler_depth = 0; -- 2.16.1
>From 57477cd2005e78b70d8409d422327b23eb71737a Mon Sep 17 00:00:00 2001 From: Pierre <pierre.ducroq...@people-doc.com> Date: Fri, 2 Feb 2018 09:23:56 +0100 Subject: [PATCH 3/8] Add LLVM4 support in llvmjit_inline.cpp --- src/backend/jit/llvm/llvmjit_inline.cpp | 36 +++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/backend/jit/llvm/llvmjit_inline.cpp b/src/backend/jit/llvm/llvmjit_inline.cpp index 7d0d18b43d..4fa0e5ab64 100644 --- a/src/backend/jit/llvm/llvmjit_inline.cpp +++ b/src/backend/jit/llvm/llvmjit_inline.cpp @@ -100,6 +100,13 @@ llvm_inline(LLVMModuleRef M) llvm_execute_inline_plan(mod, globalsToInline.get()); } +#if LLVM_VERSION_MAJOR < 5 +bool operator!(const llvm::ValueInfo &vi) { + return !( (vi.Kind == llvm::ValueInfo::VI_GUID && vi.TheValue.Id) + || (vi.Kind == llvm::ValueInfo::VI_Value && vi.TheValue.GV)); +} +#endif + /* * Build information necessary for inlining external function references in * mod. @@ -146,7 +153,14 @@ llvm_build_inline_plan(llvm::Module *mod) if (threshold == -1) continue; +#if LLVM_VERSION_MAJOR > 4 llvm::ValueInfo funcVI = llvm_index->getValueInfo(funcGUID); +#else + const llvm::const_gvsummary_iterator &I = llvm_index->findGlobalValueSummaryList(funcGUID); + if (I == llvm_index->end()) + continue; + llvm::ValueInfo funcVI = llvm::ValueInfo(I->first); +#endif /* if index doesn't know function, we don't have a body, continue */ if (!funcVI) @@ -157,7 +171,12 @@ llvm_build_inline_plan(llvm::Module *mod) * look up module(s), check if function actually is defined (there * could be hash conflicts). */ +#if LLVM_VERSION_MAJOR > 4 for (const auto &gvs : funcVI.getSummaryList()) +#else + auto it_gvs = llvm_index->findGlobalValueSummaryList(funcVI.getGUID()); + for (const auto &gvs: it_gvs->second) +#endif { const llvm::FunctionSummary *fs; llvm::StringRef modPath = gvs->modulePath(); @@ -318,9 +337,14 @@ llvm_execute_inline_plan(llvm::Module *mod, ImportMapTy *globalsToInline) } +#if LLVM_VERSION_MAJOR > 4 +#define IRMOVE_PARAMS , /*IsPerformingImport=*/false +#else +#define IRMOVE_PARAMS , /*LinkModuleInlineAsm=*/false, /*IsPerformingImport=*/false +#endif if (Mover.move(std::move(importMod), GlobalsToImport.getArrayRef(), - [](llvm::GlobalValue &, llvm::IRMover::ValueAdder) {}, - /*IsPerformingImport=*/false)) + [](llvm::GlobalValue &, llvm::IRMover::ValueAdder) {} + IRMOVE_PARAMS)) elog(ERROR, "function import failed with linker error"); } } @@ -619,9 +643,17 @@ llvm_load_index(void) elog(ERROR, "failed to open %s: %s", subpath, EC.message().c_str()); llvm::MemoryBufferRef ref(*MBOrErr.get().get()); +#if LLVM_VERSION_MAJOR > 4 llvm::Error e = llvm::readModuleSummaryIndex(ref, *index, 0); if (e) elog(ERROR, "could not load summary at %s", subpath); +#else + std::unique_ptr<llvm::ModuleSummaryIndex> subindex = std::move(llvm::getModuleSummaryIndex(ref).get()); + if (!subindex) + elog(ERROR, "could not load summary at %s", subpath); + else + index->mergeFrom(std::move(subindex), 0); +#endif } } -- 2.16.1
>From e0b3147fe7b4eec8593b62c78d7491796c9e9a2f Mon Sep 17 00:00:00 2001 From: Pierre <pierre.ducroq...@people-doc.com> Date: Fri, 2 Feb 2018 10:34:09 +0100 Subject: [PATCH 4/8] Don't emit bitcode depending on an LLVM 5+ function --- src/backend/jit/llvm/llvmjit_expr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c index a06319b1b6..4b3c5367e5 100644 --- a/src/backend/jit/llvm/llvmjit_expr.c +++ b/src/backend/jit/llvm/llvmjit_expr.c @@ -170,7 +170,11 @@ get_LifetimeEnd(LLVMModuleRef mod) LLVMTypeRef sig; LLVMValueRef fn; LLVMTypeRef param_types[2]; +#if LLVM_VERSION_MAJOR > 4 const char *nm = "llvm.lifetime.end.p0i8"; +#else + const char *nm = "llvm.lifetime.end"; +#endif fn = LLVMGetNamedFunction(mod, nm); if (fn) -- 2.16.1
>From 1df043c0345f02a58a68bae0c671dbbb4a5d97f1 Mon Sep 17 00:00:00 2001 From: Pierre Ducroquet <pina...@pinaraf.info> Date: Wed, 7 Feb 2018 20:22:37 +0100 Subject: [PATCH 5/8] Fix warning --- src/backend/jit/llvm/llvmjit_error.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/backend/jit/llvm/llvmjit_error.cpp b/src/backend/jit/llvm/llvmjit_error.cpp index 1c78bd956d..623a70a7cc 100644 --- a/src/backend/jit/llvm/llvmjit_error.cpp +++ b/src/backend/jit/llvm/llvmjit_error.cpp @@ -28,7 +28,9 @@ static int fatal_new_handler_depth = 0; static std::new_handler old_new_handler = NULL; static void fatal_system_new_handler(void); +#if LLVM_VERSION_MAJOR > 4 static void fatal_llvm_new_handler(void *user_data, const std::string& reason, bool gen_crash_diag); +#endif static void fatal_llvm_error_handler(void *user_data, const std::string& reason, bool gen_crash_diag); @@ -114,6 +116,7 @@ fatal_system_new_handler(void) errdetail("while in LLVM"))); } +#if LLVM_VERSION_MAJOR > 4 static void fatal_llvm_new_handler(void *user_data, const std::string& reason, @@ -124,6 +127,7 @@ fatal_llvm_new_handler(void *user_data, errmsg("out of memory"), errdetail("while in LLVM: %s", reason.c_str()))); } +#endif static void fatal_llvm_error_handler(void *user_data, -- 2.16.1
>From 8904b24bb4f9428bc5a18a55a9c2d879dafeb31a Mon Sep 17 00:00:00 2001 From: Pierre Ducroquet <pina...@pinaraf.info> Date: Wed, 7 Feb 2018 20:23:43 +0100 Subject: [PATCH 6/8] Ignore LLVM .bc files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a59e3da3be..794e35b73c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # Global excludes across all subdirectories *.o *.obj +*.bc *.so *.so.[0-9] *.so.[0-9].[0-9] -- 2.16.1
>From e10a1ae9a88406199665a3b010d44d5026d45ca8 Mon Sep 17 00:00:00 2001 From: Pierre <pierre.ducroq...@people-doc.com> Date: Fri, 2 Feb 2018 11:29:45 +0100 Subject: [PATCH 7/8] Fix building with LLVM 3.9 --- src/backend/jit/llvm/llvmjit_inline.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/backend/jit/llvm/llvmjit_inline.cpp b/src/backend/jit/llvm/llvmjit_inline.cpp index 4fa0e5ab64..8cfac20565 100644 --- a/src/backend/jit/llvm/llvmjit_inline.cpp +++ b/src/backend/jit/llvm/llvmjit_inline.cpp @@ -37,7 +37,12 @@ extern "C" #include <llvm/ADT/StringSet.h> #include <llvm/ADT/StringMap.h> #include <llvm/Analysis/ModuleSummaryAnalysis.h> +#if LLVM_VERSION_MAJOR > 3 #include <llvm/Bitcode/BitcodeReader.h> +#else +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Support/Error.h" +#endif #include <llvm/IR/CallSite.h> #include <llvm/IR/DebugInfo.h> #include <llvm/IR/IntrinsicInst.h> @@ -100,7 +105,12 @@ llvm_inline(LLVMModuleRef M) llvm_execute_inline_plan(mod, globalsToInline.get()); } -#if LLVM_VERSION_MAJOR < 5 +#if LLVM_VERSION_MAJOR < 4 +bool operator!(const llvm::ValueInfo &vi) { + return !( (vi.Kind == llvm::ValueInfo::VI_GUID && vi.TheValue.Id) + || (vi.Kind == llvm::ValueInfo::VI_Value && vi.TheValue.V)); +} +#elif LLVM_VERSION_MAJOR < 5 bool operator!(const llvm::ValueInfo &vi) { return !( (vi.Kind == llvm::ValueInfo::VI_GUID && vi.TheValue.Id) || (vi.Kind == llvm::ValueInfo::VI_Value && vi.TheValue.GV)); @@ -188,12 +198,15 @@ llvm_build_inline_plan(llvm::Module *mod) funcName.data(), modPath.data()); +// XXX Missing in LLVM < 4.0 ? +#if LLVM_VERSION_MAJOR > 3 if (gvs->notEligibleToImport()) { elog(DEBUG1, "uneligible to import %s due to summary", funcName.data()); continue; } +#endif if ((int) fs->instCount() > threshold) { @@ -339,8 +352,10 @@ llvm_execute_inline_plan(llvm::Module *mod, ImportMapTy *globalsToInline) #if LLVM_VERSION_MAJOR > 4 #define IRMOVE_PARAMS , /*IsPerformingImport=*/false -#else +#elif LLVM_VERSION_MAJOR > 3 #define IRMOVE_PARAMS , /*LinkModuleInlineAsm=*/false, /*IsPerformingImport=*/false +#else +#define IRMOVE_PARAMS #endif if (Mover.move(std::move(importMod), GlobalsToImport.getArrayRef(), [](llvm::GlobalValue &, llvm::IRMover::ValueAdder) {} @@ -648,7 +663,11 @@ llvm_load_index(void) if (e) elog(ERROR, "could not load summary at %s", subpath); #else +#if LLVM_VERSION_MAJOR > 3 std::unique_ptr<llvm::ModuleSummaryIndex> subindex = std::move(llvm::getModuleSummaryIndex(ref).get()); +#else + std::unique_ptr<llvm::ModuleSummaryIndex> subindex = std::move(llvm::getModuleSummaryIndex(ref, [](const llvm::DiagnosticInfo &) {}).get()); +#endif if (!subindex) elog(ERROR, "could not load summary at %s", subpath); else -- 2.16.1
>From 5e593b0f31227bc6d8e8f73f4cfbc525d7ed5e76 Mon Sep 17 00:00:00 2001 From: Pierre <pierre.ducroq...@people-doc.com> Date: Fri, 2 Feb 2018 11:29:57 +0100 Subject: [PATCH 8/8] Fix segfault with LLVM 3.9 --- src/backend/jit/llvm/llvmjit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c index e81764af98..0878c174ee 100644 --- a/src/backend/jit/llvm/llvmjit.c +++ b/src/backend/jit/llvm/llvmjit.c @@ -444,12 +444,12 @@ llvm_session_initialize(void) cpu = LLVMGetHostCPUName(); llvm_opt0_targetmachine = - LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, NULL, + LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, "", LLVMCodeGenLevelNone, LLVMRelocDefault, LLVMCodeModelJITDefault); llvm_opt3_targetmachine = - LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, NULL, + LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, "", LLVMCodeGenLevelAggressive, LLVMRelocDefault, LLVMCodeModelJITDefault); -- 2.16.1