Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2a0faed

Browse files
committed
Add expression compilation support to LLVM JIT provider.
In addition to the interpretation of expressions (which backevaluation of WHERE clauses, target list projection, aggregatestransition values etc) support compiling expressions to native code,using the infrastructure added in earlier commits.To avoid duplicating a lot of code, only support emitting code forcases that are likely to be performance critical. For expression stepsthat aren't deemed that, use the existing interpreter.The generated code isn't great - some architectural changes arerequired to address that. But this already yields a significantspeedup for some analytics queries, particularly with WHERE clausesfiltering a lot, or computing multiple aggregates.Author: Andres FreundTested-By: Thomas MunroDiscussion:https://postgr.es/m/20170901064131.tazjxwus3k2w3ybh@alap3.anarazel.deDisable JITing for VALUES() nodes.VALUES() nodes are only ever executed once. This is primarily helpfulfor debugging, when forcing JITing even for cheap queries.Author: Andres FreundDiscussion:https://postgr.es/m/20170901064131.tazjxwus3k2w3ybh@alap3.anarazel.de
1 parent7ced1d1 commit2a0faed

File tree

13 files changed

+2890
-3
lines changed

13 files changed

+2890
-3
lines changed

‎src/backend/executor/execExpr.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include"executor/execExpr.h"
3737
#include"executor/nodeSubplan.h"
3838
#include"funcapi.h"
39+
#include"jit/jit.h"
3940
#include"miscadmin.h"
4041
#include"nodes/makefuncs.h"
4142
#include"nodes/nodeFuncs.h"
@@ -623,6 +624,9 @@ ExecCheck(ExprState *state, ExprContext *econtext)
623624
staticvoid
624625
ExecReadyExpr(ExprState*state)
625626
{
627+
if (jit_compile_expr(state))
628+
return;
629+
626630
ExecReadyInterpretedExpr(state);
627631
}
628632

‎src/backend/executor/nodeValuesscan.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#include"executor/executor.h"
2727
#include"executor/nodeValuesscan.h"
28+
#include"jit/jit.h"
2829
#include"utils/expandeddatum.h"
2930

3031

@@ -98,6 +99,7 @@ ValuesNext(ValuesScanState *node)
9899
bool*isnull;
99100
ListCell*lc;
100101
intresind;
102+
intsaved_jit_flags;
101103

102104
/*
103105
* Get rid of any prior cycle's leftovers. We use ReScanExprContext
@@ -128,7 +130,15 @@ ValuesNext(ValuesScanState *node)
128130
oldsubplans=node->ss.ps.subPlan;
129131
node->ss.ps.subPlan=NIL;
130132

133+
/*
134+
* As the expressions are only ever used once, disable JIT for
135+
* them. This is worthwhile because it's common to insert significant
136+
* amounts of data via VALUES().
137+
*/
138+
saved_jit_flags=econtext->ecxt_estate->es_jit_flags;
139+
econtext->ecxt_estate->es_jit_flags=PGJIT_NONE;
131140
exprstatelist=ExecInitExprList(exprlist,&node->ss.ps);
141+
econtext->ecxt_estate->es_jit_flags=saved_jit_flags;
132142

133143
node->ss.ps.subPlan=oldsubplans;
134144

‎src/backend/jit/jit.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525

2626
#include"fmgr.h"
27+
#include"executor/execExpr.h"
2728
#include"jit/jit.h"
2829
#include"miscadmin.h"
2930
#include"utils/resowner_private.h"
@@ -35,6 +36,7 @@ booljit_enabled = true;
3536
char*jit_provider="llvmjit";
3637
booljit_debugging_support= false;
3738
booljit_dump_bitcode= false;
39+
booljit_expressions= true;
3840
booljit_profiling_support= false;
3941
doublejit_above_cost=100000;
4042
doublejit_optimize_above_cost=500000;
@@ -143,6 +145,41 @@ jit_release_context(JitContext *context)
143145
pfree(context);
144146
}
145147

148+
/*
149+
* Ask provider to JIT compile an expression.
150+
*
151+
* Returns true if successful, false if not.
152+
*/
153+
bool
154+
jit_compile_expr(structExprState*state)
155+
{
156+
/*
157+
* We can easily create a one-off context for functions without an
158+
* associated PlanState (and thus EState). But because there's no executor
159+
* shutdown callback that could deallocate the created function, they'd
160+
* live to the end of the transactions, where they'd be cleaned up by the
161+
* resowner machinery. That can lead to a noticeable amount of memory
162+
* usage, and worse, trigger some quadratic behaviour in gdb. Therefore,
163+
* at least for now, don't create a JITed function in those circumstances.
164+
*/
165+
if (!state->parent)
166+
return false;
167+
168+
/* if no jitting should be performed at all */
169+
if (!(state->parent->state->es_jit_flags&PGJIT_PERFORM))
170+
return false;
171+
172+
/* or if expressions aren't JITed */
173+
if (!(state->parent->state->es_jit_flags&PGJIT_EXPR))
174+
return false;
175+
176+
/* this also takes !jit_enabled into account */
177+
if (provider_init())
178+
returnprovider.compile_expr(state);
179+
180+
return false;
181+
}
182+
146183
staticbool
147184
file_exists(constchar*name)
148185
{

‎src/backend/jit/llvm/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ OBJS=$(WIN32RES)
3939
# Infrastructure
4040
OBJS += llvmjit.o llvmjit_error.o llvmjit_wrap.o
4141
# Code generation
42-
OBJS +=
42+
OBJS += llvmjit_expr.o
4343

4444
all: all-shared-lib llvmjit_types.bc
4545

‎src/backend/jit/llvm/llvmjit.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include"postgres.h"
1515

1616
#include"jit/llvmjit.h"
17+
#include"jit/llvmjit_emit.h"
1718

1819
#include"miscadmin.h"
1920

@@ -114,6 +115,7 @@ _PG_jit_provider_init(JitProviderCallbacks *cb)
114115
{
115116
cb->reset_after_error=llvm_reset_after_error;
116117
cb->release_context=llvm_release_context;
118+
cb->compile_expr=llvm_compile_expr;
117119
}
118120

119121
/*
@@ -339,6 +341,68 @@ llvm_copy_attributes(LLVMValueRef v_from, LLVMValueRef v_to)
339341
}
340342
}
341343

344+
/*
345+
* Return a callable LLVMValueRef for fcinfo.
346+
*/
347+
LLVMValueRef
348+
llvm_function_reference(LLVMJitContext*context,
349+
LLVMBuilderRefbuilder,
350+
LLVMModuleRefmod,
351+
FunctionCallInfofcinfo)
352+
{
353+
char*modname;
354+
char*basename;
355+
char*funcname;
356+
357+
LLVMValueRefv_fn;
358+
359+
fmgr_symbol(fcinfo->flinfo->fn_oid,&modname,&basename);
360+
361+
if (modname!=NULL&&basename!=NULL)
362+
{
363+
/* external function in loadable library */
364+
funcname=psprintf("pgextern.%s.%s",modname,basename);
365+
}
366+
elseif (basename!=NULL)
367+
{
368+
/* internal function */
369+
funcname=psprintf("%s",basename);
370+
}
371+
else
372+
{
373+
/*
374+
* Function we don't know to handle, return pointer. We do so by
375+
* creating a global constant containing a pointer to the function.
376+
* Makes IR more readable.
377+
*/
378+
LLVMValueRefv_fn_addr;
379+
380+
funcname=psprintf("pgoidextern.%u",
381+
fcinfo->flinfo->fn_oid);
382+
v_fn=LLVMGetNamedGlobal(mod,funcname);
383+
if (v_fn!=0)
384+
returnLLVMBuildLoad(builder,v_fn,"");
385+
386+
v_fn_addr=l_ptr_const(fcinfo->flinfo->fn_addr,TypePGFunction);
387+
388+
v_fn=LLVMAddGlobal(mod,TypePGFunction,funcname);
389+
LLVMSetInitializer(v_fn,v_fn_addr);
390+
LLVMSetGlobalConstant(v_fn, true);
391+
392+
returnLLVMBuildLoad(builder,v_fn,"");
393+
returnv_fn;
394+
}
395+
396+
/* check if function already has been added */
397+
v_fn=LLVMGetNamedFunction(mod,funcname);
398+
if (v_fn!=0)
399+
returnv_fn;
400+
401+
v_fn=LLVMAddFunction(mod,funcname,LLVMGetElementType(TypePGFunction));
402+
403+
returnv_fn;
404+
}
405+
342406
/*
343407
* Optimize code in module using the flags set in context.
344408
*/

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp