Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 675af5c

Browse files
committed
Compute information about EEOP_*_FETCHSOME at expression init time.
Previously this information was computed when JIT compiling an expression. But the information is useful for assertions in the non-JIT case too (for assertions), therefore it makes sense to move it. This will, in a followup commit, allow to treat different slot types differently. E.g. for virtual slots there's no need to generate a JIT function to deform the slot. Author: Andres Freund Discussion: https://postgr.es/m/20181105210039.hh4vvi4vwoq5ba2q@alap3.anarazel.de
1 parent 1a0586d commit 675af5c

File tree

3 files changed

+124
-29
lines changed

3 files changed

+124
-29
lines changed

src/backend/executor/execExpr.c

+104
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ static void ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args,
6565
static void ExecInitExprSlots(ExprState *state, Node *node);
6666
static void ExecPushExprSlots(ExprState *state, LastAttnumInfo *info);
6767
static bool get_last_attnums_walker(Node *node, LastAttnumInfo *info);
68+
static void ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op);
6869
static void ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable,
6970
ExprState *state);
7071
static void ExecInitArrayRef(ExprEvalStep *scratch, ArrayRef *aref,
@@ -2288,21 +2289,30 @@ ExecPushExprSlots(ExprState *state, LastAttnumInfo *info)
22882289
{
22892290
scratch.opcode = EEOP_INNER_FETCHSOME;
22902291
scratch.d.fetch.last_var = info->last_inner;
2292+
scratch.d.fetch.fixed = false;
2293+
scratch.d.fetch.kind = NULL;
22912294
scratch.d.fetch.known_desc = NULL;
2295+
ExecComputeSlotInfo(state, &scratch);
22922296
ExprEvalPushStep(state, &scratch);
22932297
}
22942298
if (info->last_outer > 0)
22952299
{
22962300
scratch.opcode = EEOP_OUTER_FETCHSOME;
22972301
scratch.d.fetch.last_var = info->last_outer;
2302+
scratch.d.fetch.fixed = false;
2303+
scratch.d.fetch.kind = NULL;
22982304
scratch.d.fetch.known_desc = NULL;
2305+
ExecComputeSlotInfo(state, &scratch);
22992306
ExprEvalPushStep(state, &scratch);
23002307
}
23012308
if (info->last_scan > 0)
23022309
{
23032310
scratch.opcode = EEOP_SCAN_FETCHSOME;
23042311
scratch.d.fetch.last_var = info->last_scan;
2312+
scratch.d.fetch.fixed = false;
2313+
scratch.d.fetch.kind = NULL;
23052314
scratch.d.fetch.known_desc = NULL;
2315+
ExecComputeSlotInfo(state, &scratch);
23062316
ExprEvalPushStep(state, &scratch);
23072317
}
23082318
}
@@ -2355,6 +2365,94 @@ get_last_attnums_walker(Node *node, LastAttnumInfo *info)
23552365
(void *) info);
23562366
}
23572367

2368+
/*
2369+
* Compute additional information for EEOP_*_FETCHSOME ops.
2370+
*
2371+
* The goal is to determine whether a slot is 'fixed', that is, every
2372+
* evaluation of the the expression will have the same type of slot, with an
2373+
* equivalent descriptor.
2374+
*/
2375+
static void
2376+
ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op)
2377+
{
2378+
PlanState *parent = state->parent;
2379+
TupleDesc desc = NULL;
2380+
const TupleTableSlotOps *tts_ops = NULL;
2381+
bool isfixed = false;
2382+
2383+
if (op->d.fetch.known_desc != NULL)
2384+
{
2385+
desc = op->d.fetch.known_desc;
2386+
tts_ops = op->d.fetch.kind;
2387+
isfixed = op->d.fetch.kind != NULL;
2388+
}
2389+
else if (!parent)
2390+
{
2391+
isfixed = false;
2392+
}
2393+
else if (op->opcode == EEOP_INNER_FETCHSOME)
2394+
{
2395+
PlanState *is = innerPlanState(parent);
2396+
2397+
if (parent->inneropsset && !parent->inneropsfixed)
2398+
{
2399+
isfixed = false;
2400+
}
2401+
else if (parent->inneropsset && parent->innerops)
2402+
{
2403+
isfixed = true;
2404+
tts_ops = parent->innerops;
2405+
}
2406+
else if (is)
2407+
{
2408+
tts_ops = ExecGetResultSlotOps(is, &isfixed);
2409+
desc = ExecGetResultType(is);
2410+
}
2411+
}
2412+
else if (op->opcode == EEOP_OUTER_FETCHSOME)
2413+
{
2414+
PlanState *os = outerPlanState(parent);
2415+
2416+
if (parent->outeropsset && !parent->outeropsfixed)
2417+
{
2418+
isfixed = false;
2419+
}
2420+
else if (parent->outeropsset && parent->outerops)
2421+
{
2422+
isfixed = true;
2423+
tts_ops = parent->outerops;
2424+
}
2425+
else if (os)
2426+
{
2427+
tts_ops = ExecGetResultSlotOps(os, &isfixed);
2428+
desc = ExecGetResultType(os);
2429+
}
2430+
}
2431+
else if (op->opcode == EEOP_SCAN_FETCHSOME)
2432+
{
2433+
desc = parent->scandesc;
2434+
2435+
if (parent && parent->scanops)
2436+
tts_ops = parent->scanops;
2437+
2438+
if (parent->scanopsset)
2439+
isfixed = parent->scanopsfixed;
2440+
}
2441+
2442+
if (isfixed && desc != NULL && tts_ops != NULL)
2443+
{
2444+
op->d.fetch.fixed = true;
2445+
op->d.fetch.kind = tts_ops;
2446+
op->d.fetch.known_desc = desc;
2447+
}
2448+
else
2449+
{
2450+
op->d.fetch.fixed = false;
2451+
op->d.fetch.kind = NULL;
2452+
op->d.fetch.known_desc = NULL;
2453+
}
2454+
}
2455+
23582456
/*
23592457
* Prepare step for the evaluation of a whole-row variable.
23602458
* The caller still has to push the step.
@@ -3255,12 +3353,18 @@ ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
32553353
/* push deform steps */
32563354
scratch.opcode = EEOP_INNER_FETCHSOME;
32573355
scratch.d.fetch.last_var = maxatt;
3356+
scratch.d.fetch.fixed = false;
32583357
scratch.d.fetch.known_desc = ldesc;
3358+
scratch.d.fetch.kind = lops;
3359+
ExecComputeSlotInfo(state, &scratch);
32593360
ExprEvalPushStep(state, &scratch);
32603361

32613362
scratch.opcode = EEOP_OUTER_FETCHSOME;
32623363
scratch.d.fetch.last_var = maxatt;
3364+
scratch.d.fetch.fixed = false;
32633365
scratch.d.fetch.known_desc = rdesc;
3366+
scratch.d.fetch.kind = rops;
3367+
ExecComputeSlotInfo(state, &scratch);
32643368
ExprEvalPushStep(state, &scratch);
32653369

32663370
/*

src/backend/jit/llvm/llvmjit_expr.c

+15-29
Original file line numberDiff line numberDiff line change
@@ -276,47 +276,31 @@ llvm_compile_expr(ExprState *state)
276276
LLVMValueRef v_slot;
277277
LLVMBasicBlockRef b_fetch;
278278
LLVMValueRef v_nvalid;
279+
LLVMValueRef l_jit_deform = NULL;
280+
const TupleTableSlotOps *tts_ops = NULL;
279281

280282
b_fetch = l_bb_before_v(opblocks[i + 1],
281283
"op.%d.fetch", i);
282284

283285
if (op->d.fetch.known_desc)
284286
desc = op->d.fetch.known_desc;
285287

286-
if (opcode == EEOP_INNER_FETCHSOME)
287-
{
288-
PlanState *is = innerPlanState(parent);
288+
if (op->d.fetch.fixed)
289+
tts_ops = op->d.fetch.kind;
289290

291+
if (opcode == EEOP_INNER_FETCHSOME)
290292
v_slot = v_innerslot;
291-
292-
if (!desc &&
293-
is &&
294-
is->ps_ResultTupleSlot &&
295-
TTS_FIXED(is->ps_ResultTupleSlot))
296-
desc = is->ps_ResultTupleSlot->tts_tupleDescriptor;
297-
}
298293
else if (opcode == EEOP_OUTER_FETCHSOME)
299-
{
300-
PlanState *os = outerPlanState(parent);
301-
302294
v_slot = v_outerslot;
303-
304-
if (!desc &&
305-
os &&
306-
os->ps_ResultTupleSlot &&
307-
TTS_FIXED(os->ps_ResultTupleSlot))
308-
desc = os->ps_ResultTupleSlot->tts_tupleDescriptor;
309-
}
310295
else
311-
{
312296
v_slot = v_scanslot;
313-
if (!desc && parent)
314-
desc = parent->scandesc;
315-
}
316297

317298
/*
318299
* Check if all required attributes are available, or
319300
* whether deforming is required.
301+
*
302+
* TODO: skip nvalid check if slot is fixed and known to
303+
* be a virtual slot.
320304
*/
321305
v_nvalid =
322306
l_load_struct_gep(b, v_slot,
@@ -336,19 +320,21 @@ llvm_compile_expr(ExprState *state)
336320
* function specific to tupledesc and the exact number of
337321
* to-be-extracted attributes.
338322
*/
339-
if (desc && (context->base.flags & PGJIT_DEFORM))
323+
if (tts_ops && desc && (context->base.flags & PGJIT_DEFORM))
340324
{
341-
LLVMValueRef params[1];
342-
LLVMValueRef l_jit_deform;
343-
344325
l_jit_deform =
345326
slot_compile_deform(context, desc,
346327
op->d.fetch.last_var);
328+
}
329+
330+
if (l_jit_deform)
331+
{
332+
LLVMValueRef params[1];
333+
347334
params[0] = v_slot;
348335

349336
LLVMBuildCall(b, l_jit_deform,
350337
params, lengthof(params), "");
351-
352338
}
353339
else
354340
{

src/include/executor/execExpr.h

+5
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,12 @@ typedef struct ExprEvalStep
262262
{
263263
/* attribute number up to which to fetch (inclusive) */
264264
int last_var;
265+
/* will the type of slot be the same for every invocation */
266+
bool fixed;
267+
/* tuple descriptor, if known */
265268
TupleDesc known_desc;
269+
/* type of slot, can only be relied upon if fixed is set */
270+
const TupleTableSlotOps *kind;
266271
} fetch;
267272

268273
/* for EEOP_INNER/OUTER/SCAN_[SYS]VAR[_FIRST] */

0 commit comments

Comments
 (0)