diff --git a/src/backend/access/gist/gistsplit.c b/src/backend/access/gist/gistsplit.c
index a96b881cf1d..fd35dd2e52d 100644
--- a/src/backend/access/gist/gistsplit.c
+++ b/src/backend/access/gist/gistsplit.c
@@ -19,21 +19,21 @@
 
 typedef struct
 {
-	Datum	   *attr;
-	int			len;
 	OffsetNumber *entries;
+	int			len;
+	Datum	   *attr;
 	bool	   *isnull;
 	bool	   *equiv;
 } GistSplitUnion;
 
 
 /*
- * Forms unions of subkeys after page split, but
- * uses only tuples that aren't in groups of equivalent tuples
+ * Form unions of subkeys after a page split, ignoring any tuples
+ * that are marked in gsvp->equiv[]
  */
 static void
 gistunionsubkeyvec(GISTSTATE *giststate, IndexTuple *itvec,
-				   GistSplitUnion *gsvp, int startkey)
+				   GistSplitUnion *gsvp)
 {
 	IndexTuple *cleanedItVec;
 	int			i,
@@ -49,35 +49,36 @@ gistunionsubkeyvec(GISTSTATE *giststate, IndexTuple *itvec,
 		cleanedItVec[cleanedLen++] = itvec[gsvp->entries[i] - 1];
 	}
 
-	gistMakeUnionItVec(giststate, cleanedItVec, cleanedLen, startkey,
+	gistMakeUnionItVec(giststate, cleanedItVec, cleanedLen,
 					   gsvp->attr, gsvp->isnull);
 
 	pfree(cleanedItVec);
 }
 
 /*
- * unions subkeys for after user picksplit over attno-1 column
+ * Recompute unions of subkeys after a page split, ignoring any tuples
+ * that are marked in spl->spl_equiv[]
  */
 static void
-gistunionsubkey(GISTSTATE *giststate, IndexTuple *itvec, GistSplitVector *spl, int attno)
+gistunionsubkey(GISTSTATE *giststate, IndexTuple *itvec, GistSplitVector *spl)
 {
 	GistSplitUnion gsvp;
 
 	gsvp.equiv = spl->spl_equiv;
 
-	gsvp.attr = spl->spl_lattr;
-	gsvp.len = spl->splitVector.spl_nleft;
 	gsvp.entries = spl->splitVector.spl_left;
+	gsvp.len = spl->splitVector.spl_nleft;
+	gsvp.attr = spl->spl_lattr;
 	gsvp.isnull = spl->spl_lisnull;
 
-	gistunionsubkeyvec(giststate, itvec, &gsvp, attno);
+	gistunionsubkeyvec(giststate, itvec, &gsvp);
 
-	gsvp.attr = spl->spl_rattr;
-	gsvp.len = spl->splitVector.spl_nright;
 	gsvp.entries = spl->splitVector.spl_right;
+	gsvp.len = spl->splitVector.spl_nright;
+	gsvp.attr = spl->spl_rattr;
 	gsvp.isnull = spl->spl_risnull;
 
-	gistunionsubkeyvec(giststate, itvec, &gsvp, attno);
+	gistunionsubkeyvec(giststate, itvec, &gsvp);
 }
 
 /*
@@ -443,14 +444,14 @@ gistUserPicksplit(Relation r, GistEntryVector *entryvec, int attno, GistSplitVec
 			 */
 			if (LenEquiv == 0)
 			{
-				gistunionsubkey(giststate, itup, v, attno + 1);
+				gistunionsubkey(giststate, itup, v);
 			}
 			else
 			{
 				cleanupOffsets(sv->spl_left, &sv->spl_nleft, v->spl_equiv, &LenEquiv);
 				cleanupOffsets(sv->spl_right, &sv->spl_nright, v->spl_equiv, &LenEquiv);
 
-				gistunionsubkey(giststate, itup, v, attno + 1);
+				gistunionsubkey(giststate, itup, v);
 				if (LenEquiv == 1)
 				{
 					/*
@@ -471,7 +472,7 @@ gistUserPicksplit(Relation r, GistEntryVector *entryvec, int attno, GistSplitVec
 					 * performance, because it's very rarely
 					 */
 					v->spl_equiv = NULL;
-					gistunionsubkey(giststate, itup, v, attno + 1);
+					gistunionsubkey(giststate, itup, v);
 
 					return false;
 				}
@@ -562,7 +563,7 @@ gistSplitByKey(Relation r, Page page, IndexTuple *itup, int len, GISTSTATE *gist
 				v->splitVector.spl_left[v->splitVector.spl_nleft++] = i;
 
 		v->spl_equiv = NULL;
-		gistunionsubkey(giststate, itup, v, attno);
+		gistunionsubkey(giststate, itup, v);
 	}
 	else
 	{
@@ -617,7 +618,7 @@ gistSplitByKey(Relation r, Page page, IndexTuple *itup, int len, GISTSTATE *gist
 
 				v->splitVector = backupSplit;
 				/* reunion left and right datums */
-				gistunionsubkey(giststate, itup, v, attno);
+				gistunionsubkey(giststate, itup, v);
 			}
 		}
 	}
diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c
index a127627334e..e5c3d69fca7 100644
--- a/src/backend/access/gist/gistutil.c
+++ b/src/backend/access/gist/gistutil.c
@@ -21,12 +21,6 @@
 #include "storage/lmgr.h"
 #include "utils/builtins.h"
 
-/*
- * static *S used for temporary storage (saves stack and palloc() call)
- */
-
-static Datum attrS[INDEX_MAX_KEYS];
-static bool isnullS[INDEX_MAX_KEYS];
 
 /*
  * Write itup vector to page, has no control of free space.
@@ -148,12 +142,12 @@ gistfillitupvec(IndexTuple *vec, int veclen, int *memlen)
 }
 
 /*
- * Make unions of keys in IndexTuple vector.
+ * Make unions of keys in IndexTuple vector (one union datum per index column).
+ * Union Datums are returned into the attr/isnull arrays.
  * Resulting Datums aren't compressed.
  */
-
 void
-gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len, int startkey,
+gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len,
 				   Datum *attr, bool *isnull)
 {
 	int			i;
@@ -162,19 +156,12 @@ gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len, int startke
 
 	evec = (GistEntryVector *) palloc((len + 2) * sizeof(GISTENTRY) + GEVHDRSZ);
 
-	for (i = startkey; i < giststate->tupdesc->natts; i++)
+	for (i = 0; i < giststate->tupdesc->natts; i++)
 	{
 		int			j;
 
+		/* Collect non-null datums for this column */
 		evec->n = 0;
-		if (!isnull[i])
-		{
-			gistentryinit(evec->vector[evec->n], attr[i],
-						  NULL, NULL, (OffsetNumber) 0,
-						  FALSE);
-			evec->n++;
-		}
-
 		for (j = 0; j < len; j++)
 		{
 			Datum		datum;
@@ -192,7 +179,7 @@ gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len, int startke
 			evec->n++;
 		}
 
-		/* If this tuple vector was all NULLs, the union is NULL */
+		/* If this column was all NULLs, the union is NULL */
 		if (evec->n == 0)
 		{
 			attr[i] = (Datum) 0;
@@ -202,6 +189,7 @@ gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len, int startke
 		{
 			if (evec->n == 1)
 			{
+				/* unionFn may expect at least two inputs */
 				evec->n = 2;
 				evec->vector[1] = evec->vector[0];
 			}
@@ -224,11 +212,12 @@ gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len, int startke
 IndexTuple
 gistunion(Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate)
 {
-	memset(isnullS, TRUE, sizeof(bool) * giststate->tupdesc->natts);
+	Datum		attr[INDEX_MAX_KEYS];
+	bool		isnull[INDEX_MAX_KEYS];
 
-	gistMakeUnionItVec(giststate, itvec, len, 0, attrS, isnullS);
+	gistMakeUnionItVec(giststate, itvec, len, attr, isnull);
 
-	return gistFormTuple(giststate, r, attrS, isnullS, false);
+	return gistFormTuple(giststate, r, attr, isnull, false);
 }
 
 /*
@@ -240,12 +229,15 @@ gistMakeUnionKey(GISTSTATE *giststate, int attno,
 				 GISTENTRY *entry2, bool isnull2,
 				 Datum *dst, bool *dstisnull)
 {
-
+	/* we need a GistEntryVector with room for exactly 2 elements */
+	union
+	{
+		GistEntryVector gev;
+		char		padding[2 * sizeof(GISTENTRY) + GEVHDRSZ];
+	}			storage;
+	GistEntryVector *evec = &storage.gev;
 	int			dstsize;
 
-	static char storage[2 * sizeof(GISTENTRY) + GEVHDRSZ];
-	GistEntryVector *evec = (GistEntryVector *) storage;
-
 	evec->n = 2;
 
 	if (isnull1 && isnull2)
@@ -321,6 +313,8 @@ gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *gis
 				addentries[INDEX_MAX_KEYS];
 	bool		oldisnull[INDEX_MAX_KEYS],
 				addisnull[INDEX_MAX_KEYS];
+	Datum		attr[INDEX_MAX_KEYS];
+	bool		isnull[INDEX_MAX_KEYS];
 	IndexTuple	newtup = NULL;
 	int			i;
 
@@ -335,19 +329,20 @@ gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *gis
 		gistMakeUnionKey(giststate, i,
 						 oldentries + i, oldisnull[i],
 						 addentries + i, addisnull[i],
-						 attrS + i, isnullS + i);
+						 attr + i, isnull + i);
 
 		if (neednew)
 			/* we already need new key, so we can skip check */
 			continue;
 
-		if (isnullS[i])
+		if (isnull[i])
 			/* union of key may be NULL if and only if both keys are NULL */
 			continue;
 
 		if (!addisnull[i])
 		{
-			if (oldisnull[i] || gistKeyIsEQ(giststate, i, oldentries[i].key, attrS[i]) == false)
+			if (oldisnull[i] ||
+				!gistKeyIsEQ(giststate, i, oldentries[i].key, attr[i]))
 				neednew = true;
 		}
 	}
@@ -355,7 +350,7 @@ gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *gis
 	if (neednew)
 	{
 		/* need to update key */
-		newtup = gistFormTuple(giststate, r, attrS, isnullS, false);
+		newtup = gistFormTuple(giststate, r, attr, isnull, false);
 		newtup->t_tid = oldtup->t_tid;
 	}
 
diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h
index 357b8c9d431..b35268508a4 100644
--- a/src/include/access/gist_private.h
+++ b/src/include/access/gist_private.h
@@ -500,7 +500,7 @@ extern void gistdentryinit(GISTSTATE *giststate, int nkey, GISTENTRY *e,
 extern float gistpenalty(GISTSTATE *giststate, int attno,
 			GISTENTRY *key1, bool isNull1,
 			GISTENTRY *key2, bool isNull2);
-extern void gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len, int startkey,
+extern void gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len,
 				   Datum *attr, bool *isnull);
 extern bool gistKeyIsEQ(GISTSTATE *giststate, int attno, Datum a, Datum b);
 extern void gistDeCompressAtt(GISTSTATE *giststate, Relation r, IndexTuple tuple, Page p,