public inbox for [email protected]
help / color / mirror / Atom feedFrom: Luc Vlaming <[email protected]>
Subject: [PATCH v1] generate JIT IR code lazily
Date: Mon, 28 Dec 2020 09:01:32 +0100
---
src/backend/jit/llvm/llvmjit_expr.c | 98 +++++++++++++++++------------
1 file changed, 59 insertions(+), 39 deletions(-)
diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c
index 3aa08a9743..2ac79b7571 100644
--- a/src/backend/jit/llvm/llvmjit_expr.c
+++ b/src/backend/jit/llvm/llvmjit_expr.c
@@ -52,6 +52,7 @@ typedef struct CompiledExprState
} CompiledExprState;
+static Datum ExecCompileExpr(ExprState *state, ExprContext *econtext, bool *isNull);
static Datum ExecRunCompiledExpr(ExprState *state, ExprContext *econtext, bool *isNull);
static LLVMValueRef BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
@@ -70,18 +71,66 @@ static LLVMValueRef create_LifetimeEnd(LLVMModuleRef mod);
lengthof(((LLVMValueRef[]){__VA_ARGS__})), \
((LLVMValueRef[]){__VA_ARGS__}))
-
/*
- * JIT compile expression.
+ * Prepare the JIT compile expression.
*/
bool
llvm_compile_expr(ExprState *state)
{
PlanState *parent = state->parent;
- char *funcname;
-
LLVMJitContext *context = NULL;
+
+ /*
+ * Right now we don't support compiling expressions without a parent, as
+ * we need access to the EState.
+ */
+ Assert(parent);
+
+ llvm_enter_fatal_on_oom();
+
+ /* get or create JIT context */
+ if (parent->state->es_jit)
+ context = (LLVMJitContext *) parent->state->es_jit;
+ else
+ {
+ context = llvm_create_context(parent->state->es_jit_flags);
+ parent->state->es_jit = &context->base;
+ }
+
+ /*
+ * Don't immediately emit nor actually generate the function.
+ * instead do so the first time the expression is actually evaluated.
+ * That allows to emit a lot of functions together, avoiding a lot of
+ * repeated llvm and memory remapping overhead. It also helps with not
+ * compiling functions that will never be evaluated, as can be the case
+ * if e.g. a parallel append node is distributing workers between its
+ * child nodes.
+ */
+ {
+
+ CompiledExprState *cstate = palloc0(sizeof(CompiledExprState));
+
+ cstate->context = context;
+
+ state->evalfunc = ExecCompileExpr;
+ state->evalfunc_private = cstate;
+ }
+
+ llvm_leave_fatal_on_oom();
+
+ return true;
+}
+
+/*
+ * JIT compile expression.
+ */
+static Datum
+ExecCompileExpr(ExprState *state, ExprContext *econtext, bool *isNull)
+{
+ CompiledExprState *cstate = state->evalfunc_private;
+ LLVMJitContext *context = cstate->context;
+
LLVMBuilderRef b;
LLVMModuleRef mod;
LLVMValueRef eval_fn;
@@ -125,31 +174,16 @@ llvm_compile_expr(ExprState *state)
llvm_enter_fatal_on_oom();
- /*
- * Right now we don't support compiling expressions without a parent, as
- * we need access to the EState.
- */
- Assert(parent);
-
- /* get or create JIT context */
- if (parent->state->es_jit)
- context = (LLVMJitContext *) parent->state->es_jit;
- else
- {
- context = llvm_create_context(parent->state->es_jit_flags);
- parent->state->es_jit = &context->base;
- }
-
INSTR_TIME_SET_CURRENT(starttime);
mod = llvm_mutable_module(context);
b = LLVMCreateBuilder();
- funcname = llvm_expand_funcname(context, "evalexpr");
+ cstate->funcname = llvm_expand_funcname(context, "evalexpr");
/* create function */
- eval_fn = LLVMAddFunction(mod, funcname,
+ eval_fn = LLVMAddFunction(mod, cstate->funcname,
llvm_pg_var_func_type("TypeExprStateEvalFunc"));
LLVMSetLinkage(eval_fn, LLVMExternalLinkage);
LLVMSetVisibility(eval_fn, LLVMDefaultVisibility);
@@ -2350,30 +2384,16 @@ llvm_compile_expr(ExprState *state)
LLVMDisposeBuilder(b);
- /*
- * Don't immediately emit function, instead do so the first time the
- * expression is actually evaluated. That allows to emit a lot of
- * functions together, avoiding a lot of repeated llvm and memory
- * remapping overhead.
- */
- {
-
- CompiledExprState *cstate = palloc0(sizeof(CompiledExprState));
-
- cstate->context = context;
- cstate->funcname = funcname;
-
- state->evalfunc = ExecRunCompiledExpr;
- state->evalfunc_private = cstate;
- }
-
llvm_leave_fatal_on_oom();
INSTR_TIME_SET_CURRENT(endtime);
INSTR_TIME_ACCUM_DIFF(context->base.instr.generation_counter,
endtime, starttime);
- return true;
+ /* remove indirection via this function for future calls */
+ state->evalfunc = ExecRunCompiledExpr;
+
+ return ExecRunCompiledExpr(state, econtext, isNull);
}
/*
--
2.25.1
--------------896D2E247913574437C36E84--
view thread (64+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected]
Subject: Re: [PATCH v1] generate JIT IR code lazily
In-Reply-To: <no-message-id-1863277@localhost>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox