aboutsummaryrefslogtreecommitdiff
path: root/src/backend/jit/llvm/llvmjit_expr.c
diff options
context:
space:
mode:
authorAndres Freund <andres@anarazel.de>2020-02-24 14:39:22 -0800
committerAndres Freund <andres@anarazel.de>2020-02-24 15:09:09 -0800
commit2742c45080077ed3b08b810bb96341499b86d530 (patch)
tree84b13be23cc6f50af22d3656dd49576cf25f1dc5 /src/backend/jit/llvm/llvmjit_expr.c
parent7d672b76bf27327dc3527dabcd8be4e2dedf430f (diff)
downloadpostgresql-2742c45080077ed3b08b810bb96341499b86d530.tar.gz
postgresql-2742c45080077ed3b08b810bb96341499b86d530.zip
expression eval: Reduce number of steps for agg transition invocations.
Do so by combining the various steps that are part of aggregate transition function invocation into one larger step. As some of the current steps are only necessary for some aggregates, have one variant of the aggregate transition step for each possible combination. To avoid further manual copies of code in the different transition step implementations, move most of the code into helper functions marked as "always inline". The benefit of this change is an increase in performance when aggregating lots of rows. This comes in part due to the reduced number of indirect jumps due to the reduced number of steps, and in part by reducing redundant setup code across steps. This mainly benefits interpreted execution, but the code generated by JIT is also improved a bit. As a nice side-effect it also ends up making the code a bit simpler. A small additional optimization is removing the need to set aggstate->curaggcontext before calling ExecAggInitGroup, choosing to instead passign curaggcontext as an argument. It was, in contrast to other aggregate related functions, only needed to fetch a memory context to copy the transition value into. Author: Andres Freund Discussion: https://postgr.es/m/20191023163849.sosqbfs5yenocez3@alap3.anarazel.de https://postgr.es/m/5c371df7cee903e8cd4c685f90c6c72086d3a2dc.camel@j-davis.com
Diffstat (limited to 'src/backend/jit/llvm/llvmjit_expr.c')
-rw-r--r--src/backend/jit/llvm/llvmjit_expr.c229
1 files changed, 83 insertions, 146 deletions
diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c
index cea0d6fa5ce..dc16b399327 100644
--- a/src/backend/jit/llvm/llvmjit_expr.c
+++ b/src/backend/jit/llvm/llvmjit_expr.c
@@ -2046,152 +2046,12 @@ llvm_compile_expr(ExprState *state)
break;
}
- case EEOP_AGG_INIT_TRANS:
- {
- AggStatePerTrans pertrans;
-
- LLVMValueRef v_aggstatep;
- LLVMValueRef v_pertransp;
-
- LLVMValueRef v_allpergroupsp;
-
- LLVMValueRef v_pergroupp;
-
- LLVMValueRef v_setoff,
- v_transno;
-
- LLVMValueRef v_notransvalue;
-
- LLVMBasicBlockRef b_init;
-
- pertrans = op->d.agg_init_trans.pertrans;
-
- v_aggstatep =
- LLVMBuildBitCast(b, v_parent, l_ptr(StructAggState), "");
- v_pertransp = l_ptr_const(pertrans,
- l_ptr(StructAggStatePerTransData));
-
- /*
- * pergroup = &aggstate->all_pergroups
- * [op->d.agg_init_trans_check.setoff]
- * [op->d.agg_init_trans_check.transno];
- */
- v_allpergroupsp =
- l_load_struct_gep(b, v_aggstatep,
- FIELDNO_AGGSTATE_ALL_PERGROUPS,
- "aggstate.all_pergroups");
- v_setoff = l_int32_const(op->d.agg_init_trans.setoff);
- v_transno = l_int32_const(op->d.agg_init_trans.transno);
- v_pergroupp =
- LLVMBuildGEP(b,
- l_load_gep1(b, v_allpergroupsp, v_setoff, ""),
- &v_transno, 1, "");
-
- v_notransvalue =
- l_load_struct_gep(b, v_pergroupp,
- FIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE,
- "notransvalue");
-
- b_init = l_bb_before_v(opblocks[opno + 1],
- "op.%d.inittrans", opno);
-
- LLVMBuildCondBr(b,
- LLVMBuildICmp(b, LLVMIntEQ, v_notransvalue,
- l_sbool_const(1), ""),
- b_init,
- opblocks[opno + 1]);
-
- LLVMPositionBuilderAtEnd(b, b_init);
-
- {
- LLVMValueRef params[3];
- LLVMValueRef v_curaggcontext;
- LLVMValueRef v_current_set;
- LLVMValueRef v_aggcontext;
-
- v_aggcontext = l_ptr_const(op->d.agg_init_trans.aggcontext,
- l_ptr(StructExprContext));
-
- v_current_set =
- LLVMBuildStructGEP(b,
- v_aggstatep,
- FIELDNO_AGGSTATE_CURRENT_SET,
- "aggstate.current_set");
- v_curaggcontext =
- LLVMBuildStructGEP(b,
- v_aggstatep,
- FIELDNO_AGGSTATE_CURAGGCONTEXT,
- "aggstate.curaggcontext");
-
- LLVMBuildStore(b, l_int32_const(op->d.agg_init_trans.setno),
- v_current_set);
- LLVMBuildStore(b, v_aggcontext,
- v_curaggcontext);
-
- params[0] = v_aggstatep;
- params[1] = v_pertransp;
- params[2] = v_pergroupp;
-
- LLVMBuildCall(b,
- llvm_pg_func(mod, "ExecAggInitGroup"),
- params, lengthof(params),
- "");
- }
- LLVMBuildBr(b, opblocks[op->d.agg_init_trans.jumpnull]);
-
- break;
- }
-
- case EEOP_AGG_STRICT_TRANS_CHECK:
- {
- LLVMValueRef v_setoff,
- v_transno;
-
- LLVMValueRef v_aggstatep;
- LLVMValueRef v_allpergroupsp;
-
- LLVMValueRef v_transnull;
- LLVMValueRef v_pergroupp;
-
- int jumpnull = op->d.agg_strict_trans_check.jumpnull;
-
- v_aggstatep =
- LLVMBuildBitCast(b, v_parent, l_ptr(StructAggState), "");
-
- /*
- * pergroup = &aggstate->all_pergroups
- * [op->d.agg_strict_trans_check.setoff]
- * [op->d.agg_init_trans_check.transno];
- */
- v_allpergroupsp =
- l_load_struct_gep(b, v_aggstatep,
- FIELDNO_AGGSTATE_ALL_PERGROUPS,
- "aggstate.all_pergroups");
- v_setoff =
- l_int32_const(op->d.agg_strict_trans_check.setoff);
- v_transno =
- l_int32_const(op->d.agg_strict_trans_check.transno);
- v_pergroupp =
- LLVMBuildGEP(b,
- l_load_gep1(b, v_allpergroupsp, v_setoff, ""),
- &v_transno, 1, "");
-
- v_transnull =
- l_load_struct_gep(b, v_pergroupp,
- FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL,
- "transnull");
-
- LLVMBuildCondBr(b,
- LLVMBuildICmp(b, LLVMIntEQ, v_transnull,
- l_sbool_const(1), ""),
- opblocks[jumpnull],
- opblocks[opno + 1]);
-
- break;
- }
-
+ case EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL:
+ case EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL:
case EEOP_AGG_PLAIN_TRANS_BYVAL:
- case EEOP_AGG_PLAIN_TRANS:
+ case EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF:
+ case EEOP_AGG_PLAIN_TRANS_STRICT_BYREF:
+ case EEOP_AGG_PLAIN_TRANS_BYREF:
{
AggState *aggstate;
AggStatePerTrans pertrans;
@@ -2249,6 +2109,81 @@ llvm_compile_expr(ExprState *state)
l_load_gep1(b, v_allpergroupsp, v_setoff, ""),
&v_transno, 1, "");
+
+ if (opcode == EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL ||
+ opcode == EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF)
+ {
+ LLVMValueRef v_notransvalue;
+ LLVMBasicBlockRef b_init;
+ LLVMBasicBlockRef b_no_init;
+
+ v_notransvalue =
+ l_load_struct_gep(b, v_pergroupp,
+ FIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE,
+ "notransvalue");
+
+ b_init = l_bb_before_v(opblocks[opno + 1],
+ "op.%d.inittrans", opno);
+ b_no_init = l_bb_before_v(opblocks[opno + 1],
+ "op.%d.no_inittrans", opno);
+
+ LLVMBuildCondBr(b,
+ LLVMBuildICmp(b, LLVMIntEQ, v_notransvalue,
+ l_sbool_const(1), ""),
+ b_init,
+ b_no_init);
+
+ /* block to init the transition value if necessary */
+ {
+ LLVMValueRef params[4];
+
+ LLVMPositionBuilderAtEnd(b, b_init);
+
+ v_aggcontext = l_ptr_const(op->d.agg_trans.aggcontext,
+ l_ptr(StructExprContext));
+
+ params[0] = v_aggstatep;
+ params[1] = v_pertransp;
+ params[2] = v_pergroupp;
+ params[3] = v_aggcontext;
+
+ LLVMBuildCall(b,
+ llvm_pg_func(mod, "ExecAggInitGroup"),
+ params, lengthof(params),
+ "");
+
+ LLVMBuildBr(b, opblocks[opno + 1]);
+
+ }
+
+ LLVMPositionBuilderAtEnd(b, b_no_init);
+ }
+
+ if (opcode == EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL ||
+ opcode == EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF ||
+ opcode == EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL ||
+ opcode == EEOP_AGG_PLAIN_TRANS_STRICT_BYREF)
+ {
+ LLVMValueRef v_transnull;
+ LLVMBasicBlockRef b_strictpass;
+
+ b_strictpass = l_bb_before_v(opblocks[opno + 1],
+ "op.%d.strictpass", opno);
+ v_transnull =
+ l_load_struct_gep(b, v_pergroupp,
+ FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL,
+ "transnull");
+
+ LLVMBuildCondBr(b,
+ LLVMBuildICmp(b, LLVMIntEQ, v_transnull,
+ l_sbool_const(1), ""),
+ opblocks[opno + 1],
+ b_strictpass);
+
+ LLVMPositionBuilderAtEnd(b, b_strictpass);
+ }
+
+
v_fcinfo = l_ptr_const(fcinfo,
l_ptr(StructFunctionCallInfoData));
v_aggcontext = l_ptr_const(op->d.agg_trans.aggcontext,
@@ -2312,7 +2247,9 @@ llvm_compile_expr(ExprState *state)
* child of the aggcontext, assume we can adopt that value
* without copying it.
*/
- if (opcode == EEOP_AGG_PLAIN_TRANS)
+ if (opcode == EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF ||
+ opcode == EEOP_AGG_PLAIN_TRANS_STRICT_BYREF ||
+ opcode == EEOP_AGG_PLAIN_TRANS_BYREF)
{
LLVMBasicBlockRef b_call;
LLVMBasicBlockRef b_nocall;