diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c
index 5bc2a15160..25d1a3564c 100644
--- a/src/backend/utils/time/snapmgr.c
+++ b/src/backend/utils/time/snapmgr.c
@@ -45,6 +45,7 @@
  */
 #include "postgres.h"
 
+#include <nmmintrin.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
@@ -2271,6 +2272,40 @@ RestoreTransactionSnapshot(Snapshot snapshot, void *source_pgproc)
 	SetTransactionSnapshot(snapshot, NULL, InvalidPid, source_pgproc);
 }
 
+static inline bool
+XidInXip(TransactionId xid, TransactionId *xip, uint32 len)
+{
+	__m128i xids = _mm_set1_epi32(xid);
+	uint32  its = len & ~15;  /* round down to nearest multiple of 16 */
+	uint32	i;
+
+	for (i = 0; i < its; i += 16)
+	{
+		__m128i xips1 = _mm_loadu_si128((__m128i *) &xip[i]);
+		__m128i xips2 = _mm_loadu_si128((__m128i *) &xip[i + 4]);
+		__m128i xips3 = _mm_loadu_si128((__m128i *) &xip[i + 8]);
+		__m128i xips4 = _mm_loadu_si128((__m128i *) &xip[i + 12]);
+		__m128i result1 = _mm_cmpeq_epi32(xids, xips1);
+		__m128i result2 = _mm_cmpeq_epi32(xids, xips2);
+		__m128i result3 = _mm_cmpeq_epi32(xids, xips3);
+		__m128i result4 = _mm_cmpeq_epi32(xids, xips4);
+		__m128i tmp1 = _mm_packs_epi32(result1, result2);
+		__m128i tmp2 = _mm_packs_epi32(result3, result4);
+		__m128i result = _mm_packs_epi16(tmp1, tmp2);
+
+		if (_mm_movemask_epi8(result) != 0)
+			return true;
+	}
+
+	while (i < len)
+	{
+		if (TransactionIdEquals(xid, xip[i++]))
+			return true;
+	}
+
+	return false;
+}
+
 /*
  * XidInMVCCSnapshot
  *		Is the given XID still-in-progress according to the snapshot?
@@ -2284,8 +2319,6 @@ RestoreTransactionSnapshot(Snapshot snapshot, void *source_pgproc)
 bool
 XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
 {
-	uint32		i;
-
 	/*
 	 * Make a quick range check to eliminate most XIDs without looking at the
 	 * xip arrays.  Note that this is OK even if we convert a subxact XID to
@@ -2317,13 +2350,8 @@ XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
 		if (!snapshot->suboverflowed)
 		{
 			/* we have full data, so search subxip */
-			int32		j;
-
-			for (j = 0; j < snapshot->subxcnt; j++)
-			{
-				if (TransactionIdEquals(xid, snapshot->subxip[j]))
-					return true;
-			}
+			if (XidInXip(xid, snapshot->subxip, snapshot->subxcnt))
+				return true;
 
 			/* not there, fall through to search xip[] */
 		}
@@ -2344,16 +2372,11 @@ XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
 				return false;
 		}
 
-		for (i = 0; i < snapshot->xcnt; i++)
-		{
-			if (TransactionIdEquals(xid, snapshot->xip[i]))
-				return true;
-		}
+		if (XidInXip(xid, snapshot->xip, snapshot->xcnt))
+			return true;
 	}
 	else
 	{
-		int32		j;
-
 		/*
 		 * In recovery we store all xids in the subxact array because it is by
 		 * far the bigger array, and we mostly don't know which xids are
@@ -2383,11 +2406,8 @@ XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
 		 * indeterminate xid. We don't know whether it's top level or subxact
 		 * but it doesn't matter. If it's present, the xid is visible.
 		 */
-		for (j = 0; j < snapshot->subxcnt; j++)
-		{
-			if (TransactionIdEquals(xid, snapshot->subxip[j]))
-				return true;
-		}
+		if (XidInXip(xid, snapshot->subxip, snapshot->subxcnt))
+			return true;
 	}
 
 	return false;
