Skip to content

Commit

Permalink
jit: Use the new pass manager only.
Browse files Browse the repository at this point in the history
XXX This doesn't work on LLVM < 16, because you need
PTO.InlinerThreshold:

llvm/llvm-project@4fa3280
  • Loading branch information
macdice committed Apr 23, 2024
1 parent feaaa5f commit 0d40abd
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 74 deletions.
74 changes: 0 additions & 74 deletions src/backend/jit/llvm/llvmjit.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,12 @@
#include <llvm-c/BitWriter.h>
#include <llvm-c/Core.h>
#include <llvm-c/ExecutionEngine.h>
#if LLVM_VERSION_MAJOR > 16
#include <llvm-c/Transforms/PassBuilder.h>
#endif
#include <llvm-c/Orc.h>
#include <llvm-c/OrcEE.h>
#include <llvm-c/LLJIT.h>
#include <llvm-c/Support.h>
#include <llvm-c/Target.h>
#if LLVM_VERSION_MAJOR < 17
#include <llvm-c/Transforms/IPO.h>
#include <llvm-c/Transforms/PassManagerBuilder.h>
#include <llvm-c/Transforms/Scalar.h>
#include <llvm-c/Transforms/Utils.h>
#endif

#include "jit/llvmjit.h"
#include "jit/llvmjit_emit.h"
Expand Down Expand Up @@ -598,71 +590,6 @@ llvm_function_reference(LLVMJitContext *context,
static void
llvm_optimize_module(LLVMJitContext *context, LLVMModuleRef module)
{
#if LLVM_VERSION_MAJOR < 17
LLVMPassManagerBuilderRef llvm_pmb;
LLVMPassManagerRef llvm_mpm;
LLVMPassManagerRef llvm_fpm;
LLVMValueRef func;
int compile_optlevel;

if (context->base.flags & PGJIT_OPT3)
compile_optlevel = 3;
else
compile_optlevel = 0;

/*
* Have to create a new pass manager builder every pass through, as the
* inliner has some per-builder state. Otherwise one ends up only inlining
* a function the first time though.
*/
llvm_pmb = LLVMPassManagerBuilderCreate();
LLVMPassManagerBuilderSetOptLevel(llvm_pmb, compile_optlevel);
llvm_fpm = LLVMCreateFunctionPassManagerForModule(module);

if (context->base.flags & PGJIT_OPT3)
{
/* TODO: Unscientifically determined threshold */
LLVMPassManagerBuilderUseInlinerWithThreshold(llvm_pmb, 512);
}
else
{
/* we rely on mem2reg heavily, so emit even in the O0 case */
LLVMAddPromoteMemoryToRegisterPass(llvm_fpm);
}

LLVMPassManagerBuilderPopulateFunctionPassManager(llvm_pmb, llvm_fpm);

/*
* Do function level optimization. This could be moved to the point where
* functions are emitted, to reduce memory usage a bit.
*/
LLVMInitializeFunctionPassManager(llvm_fpm);
for (func = LLVMGetFirstFunction(context->module);
func != NULL;
func = LLVMGetNextFunction(func))
LLVMRunFunctionPassManager(llvm_fpm, func);
LLVMFinalizeFunctionPassManager(llvm_fpm);
LLVMDisposePassManager(llvm_fpm);

/*
* Perform module level optimization. We do so even in the non-optimized
* case, so always-inline functions etc get inlined. It's cheap enough.
*/
llvm_mpm = LLVMCreatePassManager();
LLVMPassManagerBuilderPopulateModulePassManager(llvm_pmb,
llvm_mpm);
/* always use always-inliner pass */
if (!(context->base.flags & PGJIT_OPT3))
LLVMAddAlwaysInlinerPass(llvm_mpm);
/* if doing inlining, but no expensive optimization, add inlining pass */
if (context->base.flags & PGJIT_INLINE
&& !(context->base.flags & PGJIT_OPT3))
LLVMAddFunctionInliningPass(llvm_mpm);
LLVMRunPassManager(llvm_mpm, context->module);
LLVMDisposePassManager(llvm_mpm);

LLVMPassManagerBuilderDispose(llvm_pmb);
#else
LLVMPassBuilderOptionsRef options;
LLVMErrorRef err;
const char *passes;
Expand All @@ -686,7 +613,6 @@ llvm_optimize_module(LLVMJitContext *context, LLVMModuleRef module)
elog(ERROR, "failed to JIT module: %s", llvm_error_message(err));

LLVMDisposePassBuilderOptions(options);
#endif
}

/*
Expand Down
32 changes: 32 additions & 0 deletions src/backend/jit/llvm/llvmjit_wrap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ extern "C"
#include <llvm-c/Core.h>
#include <llvm/IR/Function.h>

#if LLVM_VERSION_MAJOR < 17
#undef PIC /* an unfortunately chosen identifier */
#include <llvm/Passes/PassBuilder.h>
#endif

#include "jit/llvmjit.h"


Expand All @@ -37,3 +42,30 @@ LLVMGetFunctionType(LLVMValueRef r)
{
return llvm::wrap(llvm::unwrap<llvm::Function>(r)->getFunctionType());
}

#if LLVM_VERSION_MAJOR < 17
void
LLVMPassBuilderOptionsSetInlinerThreshold(LLVMPassBuilderOptionsRef Options,
int Threshold)
{
/*
* A struct that is layout compatible with:
*
* https://github.com/llvm/llvm-project/blob/release/14.x/llvm/lib/Passes/PassBuilderBindings.cpp#L26
* https://github.com/llvm/llvm-project/blob/release/15.x/llvm/lib/Passes/PassBuilderBindings.cpp#L26
* https://github.com/llvm/llvm-project/blob/release/16.x/llvm/lib/Passes/PassBuilderBindings.cpp#L26
*
* This function that we needed was upstreamed in LLVM 17, but
* unfortunately we can't see the class definition from here.
*
* https://github.com/llvm/llvm-project/commit/c20a9bb001855da5d14721ce2894e3be77a999fe
*/
struct FakePassBuilderOptions {
bool DebugLogging;
bool VerifyEach;
llvm::PipelineTuningOptions PTO;
};

reinterpret_cast<FakePassBuilderOptions *>(Options)->PTO.InlinerThreshold = Threshold;
}
#endif
6 changes: 6 additions & 0 deletions src/include/jit/llvmjit.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#ifdef USE_LLVM

#include <llvm-c/Types.h>
#include <llvm-c/Transforms/PassBuilder.h>


/*
Expand Down Expand Up @@ -133,6 +134,11 @@ extern LLVMValueRef slot_compile_deform(struct LLVMJitContext *context, TupleDes
extern LLVMTypeRef LLVMGetFunctionReturnType(LLVMValueRef r);
extern LLVMTypeRef LLVMGetFunctionType(LLVMValueRef r);

#if LLVM_VERSION_MAJOR < 17
extern void LLVMPassBuilderOptionsSetInlinerThreshold(LLVMPassBuilderOptionsRef Options,
int Threshold);
#endif

#ifdef __cplusplus
} /* extern "C" */
#endif
Expand Down

0 comments on commit 0d40abd

Please sign in to comment.