From f4f5845b3182ab930e525b1419bca47ac611604e Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Tue, 27 Mar 2018 21:03:10 -0700 Subject: [PATCH] Quick adaption of JIT tuple deforming to the fast default patch. Instead using memset to set tts_isnull, call the new slot_getmissingattrs(). Also fix a bug (= instead of >=) in the code generation. Normally = is correct, but when repeatedly deforming fields not in a tuple (e.g. deform up to natts + 1 and then natts + 2) >= is needed. Discussion: https://postgr.es/m/20180328010053.i2qvsuuusst4lgmc@alap3.anarazel.de --- src/backend/access/common/heaptuple.c | 8 ++- src/backend/jit/llvm/llvmjit.c | 2 + src/backend/jit/llvm/llvmjit_deform.c | 85 ++++++++++----------------- src/backend/jit/llvm/llvmjit_types.c | 1 + src/include/executor/tuptable.h | 1 + src/include/jit/llvmjit.h | 1 + 6 files changed, 41 insertions(+), 57 deletions(-) diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c index b6ad735671..960bbe4203 100644 --- a/src/backend/access/common/heaptuple.c +++ b/src/backend/access/common/heaptuple.c @@ -112,9 +112,13 @@ getmissingattr(TupleDesc tupleDesc, } /* - * Fill in missing values for a TupleTableSlot + * Fill in missing values for a TupleTableSlot. + * + * This is only exposed because it's needed for JIT compiled tuple + * deforming. That exception aside, there should be no callers outside of this + * file. */ -static void +void slot_getmissingattrs(TupleTableSlot *slot, int startAttNum, int lastAttNum) { AttrMissing *attrmiss = NULL; diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c index bbb2360232..5a33e52e1d 100644 --- a/src/backend/jit/llvm/llvmjit.c +++ b/src/backend/jit/llvm/llvmjit.c @@ -76,6 +76,7 @@ LLVMValueRef AttributeTemplate; LLVMValueRef FuncStrlen; LLVMValueRef FuncVarsizeAny; LLVMValueRef FuncSlotGetsomeattrs; +LLVMValueRef FuncSlotGetmissingattrs; LLVMValueRef FuncHeapGetsysattr; LLVMValueRef FuncMakeExpandedObjectReadOnlyInternal; LLVMValueRef FuncExecEvalArrayRefSubscript; @@ -798,6 +799,7 @@ llvm_create_types(void) FuncStrlen = LLVMGetNamedFunction(mod, "strlen"); FuncVarsizeAny = LLVMGetNamedFunction(mod, "varsize_any"); FuncSlotGetsomeattrs = LLVMGetNamedFunction(mod, "slot_getsomeattrs"); + FuncSlotGetmissingattrs = LLVMGetNamedFunction(mod, "slot_getmissingattrs"); FuncHeapGetsysattr = LLVMGetNamedFunction(mod, "heap_getsysattr"); FuncMakeExpandedObjectReadOnlyInternal = LLVMGetNamedFunction(mod, "MakeExpandedObjectReadOnlyInternal"); FuncExecEvalArrayRefSubscript = LLVMGetNamedFunction(mod, "ExecEvalArrayRefSubscript"); diff --git a/src/backend/jit/llvm/llvmjit_deform.c b/src/backend/jit/llvm/llvmjit_deform.c index 0762ab6786..795f67114e 100644 --- a/src/backend/jit/llvm/llvmjit_deform.c +++ b/src/backend/jit/llvm/llvmjit_deform.c @@ -21,14 +21,12 @@ #include #include "access/htup_details.h" +#include "access/tupdesc_details.h" #include "executor/tuptable.h" #include "jit/llvmjit.h" #include "jit/llvmjit_emit.h" -static LLVMValueRef get_memset(LLVMModuleRef mod); - - /* * Create a function that deforms a tuple of type desc up to natts columns. */ @@ -100,10 +98,23 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts) */ for (attnum = 0; attnum < desc->natts; attnum++) { - if (TupleDescAttr(desc, attnum)->attnotnull) - { + Form_pg_attribute att = TupleDescAttr(desc, attnum); + + /* + * If the column is possibly missing, we can't rely on its (or + * subsequent) NOT NULL constraints to indicate minimum attributes in + * the tuple, so stop here. + */ + if (att->atthasmissing) + break; + + /* + * Column is NOT NULL and there've been no preceding missing columns, + * it's guaranteed that all columns up to here exist at least in the + * NULL bitmap. + */ + if (att->attnotnull) guaranteed_column_number = attnum; - } } /* Create the signature and function */ @@ -242,9 +253,8 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts) /* * Check if's guaranteed the all the desired attributes are available in - * tuple. If so, we can start deforming. If not, need to make sure - * tts_values/isnull is set appropriately for columns not available in the - * tuple. + * tuple. If so, we can start deforming. If not, need to make sure to + * fetch the missing columns. */ if ((natts - 1) <= guaranteed_column_number) { @@ -255,9 +265,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts) } else { - LLVMValueRef v_set; - LLVMValueRef v_startset; - LLVMValueRef v_params[5]; + LLVMValueRef v_params[3]; /* branch if not all columns available */ LLVMBuildCondBr(b, @@ -271,19 +279,10 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts) /* if not, memset tts_isnull of relevant cols to true */ LLVMPositionBuilderAtEnd(b, b_adjust_unavail_cols); - v_set = LLVMBuildSub(b, - l_int16_const(attnum), - v_maxatt, ""); - - v_startset = LLVMBuildGEP(b, v_tts_nulls, &v_maxatt, 1, ""); - - v_params[0] = v_startset; - v_params[1] = l_int8_const(1); - v_params[2] = LLVMBuildZExt(b, v_set, LLVMInt32Type(), ""); - v_params[3] = l_int32_const(1); - v_params[4] = LLVMConstInt(LLVMInt1Type(), 0, false); - - LLVMBuildCall(b, get_memset(mod), + v_params[0] = v_slot; + v_params[1] = LLVMBuildZExt(b, v_maxatt, LLVMInt32Type(), ""); + v_params[2] = l_int32_const(natts); + LLVMBuildCall(b, llvm_get_decl(mod, FuncSlotGetmissingattrs), v_params, lengthof(v_params), ""); LLVMBuildBr(b, b_find_start); } @@ -358,7 +357,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts) { LLVMValueRef v_islast; - v_islast = LLVMBuildICmp(b, LLVMIntEQ, + v_islast = LLVMBuildICmp(b, LLVMIntUGE, l_attno, v_maxatt, "heap_natts"); @@ -366,7 +365,11 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts) } LLVMPositionBuilderAtEnd(b, attstartblocks[attnum]); - /* check for nulls if necessary */ + /* + * Check for nulls if necessary. No need to take missing attributes + * into account, because in case they're present the heaptuple's natts + * would have indicated that a slot_getmissingattrs() is needed. + */ if (!att->attnotnull) { LLVMBasicBlockRef b_ifnotnull; @@ -699,31 +702,3 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts) return v_deform_fn; } - -static LLVMValueRef -get_memset(LLVMModuleRef mod) -{ - LLVMTypeRef sig; - LLVMValueRef v_fn; - LLVMTypeRef param_types[5]; - const char *nm = "llvm.memset.p0i8.i32"; - - v_fn = LLVMGetNamedFunction(mod, nm); - if (v_fn) - return v_fn; - - param_types[0] = LLVMPointerType(LLVMInt8Type(), 0); /* addr */ - param_types[1] = LLVMInt8Type(); /* val */ - param_types[2] = LLVMInt32Type(); /* len */ - param_types[3] = LLVMInt32Type(); /* align */ - param_types[4] = LLVMInt1Type(); /* volatile */ - - sig = LLVMFunctionType(LLVMVoidType(), param_types, lengthof(param_types), 0); - v_fn = LLVMAddFunction(mod, nm, sig); - - LLVMSetFunctionCallConv(v_fn, LLVMCCallConv); - - Assert(LLVMGetIntrinsicID(v_fn)); - - return v_fn; -} diff --git a/src/backend/jit/llvm/llvmjit_types.c b/src/backend/jit/llvm/llvmjit_types.c index 0e06160c2a..42304d0640 100644 --- a/src/backend/jit/llvm/llvmjit_types.c +++ b/src/backend/jit/llvm/llvmjit_types.c @@ -98,6 +98,7 @@ void *referenced_functions[] = strlen, varsize_any, slot_getsomeattrs, + slot_getmissingattrs, heap_getsysattr, MakeExpandedObjectReadOnlyInternal, ExecEvalArrayRefSubscript, diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h index 3c1cf67d8f..b71ec8e069 100644 --- a/src/include/executor/tuptable.h +++ b/src/include/executor/tuptable.h @@ -179,5 +179,6 @@ extern void slot_getsomeattrs(TupleTableSlot *slot, int attnum); extern bool slot_attisnull(TupleTableSlot *slot, int attnum); extern bool slot_getsysattr(TupleTableSlot *slot, int attnum, Datum *value, bool *isnull); +extern void slot_getmissingattrs(TupleTableSlot *slot, int startAttNum, int lastAttNum); #endif /* TUPTABLE_H */ diff --git a/src/include/jit/llvmjit.h b/src/include/jit/llvmjit.h index 9443a568d8..f6aed64d8d 100644 --- a/src/include/jit/llvmjit.h +++ b/src/include/jit/llvmjit.h @@ -78,6 +78,7 @@ extern LLVMValueRef AttributeTemplate; extern LLVMValueRef FuncStrlen; extern LLVMValueRef FuncVarsizeAny; extern LLVMValueRef FuncSlotGetsomeattrs; +extern LLVMValueRef FuncSlotGetmissingattrs; extern LLVMValueRef FuncHeapGetsysattr; extern LLVMValueRef FuncMakeExpandedObjectReadOnlyInternal; extern LLVMValueRef FuncExecEvalArrayRefSubscript;