From bf26010357d1dd2a797b672d1de231efca08f571 Mon Sep 17 00:00:00 2001
From: soumyadeep2007 <sochakraborty@pivotal.io>
Date: Wed, 25 Sep 2019 20:47:55 -0700
Subject: [PATCH v1] Skip deform expr step emission for virtual tuples

Virtual tuples need not be deformed. Thus, skip emitting any deform step
if the slot type is fixed and virtual.

Doing the optimization at this stage ensures that we get the benefit in
both JITed and non-JITed code.

Discussion: https://www.postgresql.org/message-id/20190925200210.aled756suzad674w%40alap3.anarazel.de
---
 src/backend/executor/execExpr.c     | 25 ++++++++++++++++++-------
 src/backend/jit/llvm/llvmjit_expr.c |  3 ---
 2 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index 39442f8866..92524f2391 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -2277,7 +2277,10 @@ ExecPushExprSlots(ExprState *state, LastAttnumInfo *info)
 	scratch.resvalue = NULL;
 	scratch.resnull = NULL;
 
-	/* Emit steps as needed */
+	/*
+	 * Push deform steps. We can skip pushing steps if the slot is virtual and
+	 * the slot type is fixed as virtual tuples don't need to be deformed.
+	 */
 	if (info->last_inner > 0)
 	{
 		scratch.opcode = EEOP_INNER_FETCHSOME;
@@ -2286,7 +2289,8 @@ ExecPushExprSlots(ExprState *state, LastAttnumInfo *info)
 		scratch.d.fetch.kind = NULL;
 		scratch.d.fetch.known_desc = NULL;
 		ExecComputeSlotInfo(state, &scratch);
-		ExprEvalPushStep(state, &scratch);
+		if (!(scratch.d.fetch.kind == &TTSOpsVirtual && scratch.d.fetch.fixed))
+			ExprEvalPushStep(state, &scratch);
 	}
 	if (info->last_outer > 0)
 	{
@@ -2296,7 +2300,8 @@ ExecPushExprSlots(ExprState *state, LastAttnumInfo *info)
 		scratch.d.fetch.kind = NULL;
 		scratch.d.fetch.known_desc = NULL;
 		ExecComputeSlotInfo(state, &scratch);
-		ExprEvalPushStep(state, &scratch);
+		if (!(scratch.d.fetch.kind == &TTSOpsVirtual && scratch.d.fetch.fixed))
+			ExprEvalPushStep(state, &scratch);
 	}
 	if (info->last_scan > 0)
 	{
@@ -2306,7 +2311,8 @@ ExecPushExprSlots(ExprState *state, LastAttnumInfo *info)
 		scratch.d.fetch.kind = NULL;
 		scratch.d.fetch.known_desc = NULL;
 		ExecComputeSlotInfo(state, &scratch);
-		ExprEvalPushStep(state, &scratch);
+		if (!(scratch.d.fetch.kind == &TTSOpsVirtual && scratch.d.fetch.fixed))
+			ExprEvalPushStep(state, &scratch);
 	}
 }
 
@@ -3352,14 +3358,18 @@ ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
 	}
 	Assert(maxatt >= 0);
 
-	/* push deform steps */
+	/*
+	 * Push deform steps. We can skip pushing steps if the slot is virtual and
+	 * the slot type is fixed as virtual tuples don't need to be deformed.
+	 */
 	scratch.opcode = EEOP_INNER_FETCHSOME;
 	scratch.d.fetch.last_var = maxatt;
 	scratch.d.fetch.fixed = false;
 	scratch.d.fetch.known_desc = ldesc;
 	scratch.d.fetch.kind = lops;
 	ExecComputeSlotInfo(state, &scratch);
-	ExprEvalPushStep(state, &scratch);
+	if (!(scratch.d.fetch.kind == &TTSOpsVirtual && scratch.d.fetch.fixed))
+		ExprEvalPushStep(state, &scratch);
 
 	scratch.opcode = EEOP_OUTER_FETCHSOME;
 	scratch.d.fetch.last_var = maxatt;
@@ -3367,7 +3377,8 @@ ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
 	scratch.d.fetch.known_desc = rdesc;
 	scratch.d.fetch.kind = rops;
 	ExecComputeSlotInfo(state, &scratch);
-	ExprEvalPushStep(state, &scratch);
+	if (!(scratch.d.fetch.kind == &TTSOpsVirtual && scratch.d.fetch.fixed))
+		ExprEvalPushStep(state, &scratch);
 
 	/*
 	 * Start comparing at the last field (least significant sort key). That's
diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c
index 30133634c7..10a55ce2b1 100644
--- a/src/backend/jit/llvm/llvmjit_expr.c
+++ b/src/backend/jit/llvm/llvmjit_expr.c
@@ -297,9 +297,6 @@ llvm_compile_expr(ExprState *state)
 					/*
 					 * Check if all required attributes are available, or
 					 * whether deforming is required.
-					 *
-					 * TODO: skip nvalid check if slot is fixed and known to
-					 * be a virtual slot.
 					 */
 					v_nvalid =
 						l_load_struct_gep(b, v_slot,
-- 
2.23.0

