diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c
index a47dc328c4b07504489f9bf55e887dd5beaa839f..5e05ec3df37011fbeb2859310e638c1be8513385 100644
--- a/src/backend/executor/nodeHash.c
+++ b/src/backend/executor/nodeHash.c
@@ -415,6 +415,7 @@ ExecChooseHashTableSize(double ntuples, int tupwidth, bool useskew,
 	long		hash_table_bytes;
 	long		skew_table_bytes;
 	long		max_pointers;
+	long		mppow2;
 	int			nbatch = 1;
 	int			nbuckets;
 	double		dbuckets;
@@ -485,14 +486,20 @@ ExecChooseHashTableSize(double ntuples, int tupwidth, bool useskew,
 	 */
 	max_pointers = (work_mem * 1024L) / sizeof(HashJoinTuple);
 	max_pointers = Min(max_pointers, MaxAllocSize / sizeof(HashJoinTuple));
-	/* also ensure we avoid integer overflow in nbatch and nbuckets */
+	/* If max_pointers isn't a power of 2, must round it down to one */
+	mppow2 = 1L << my_log2(max_pointers);
+	if (max_pointers != mppow2)
+		max_pointers = mppow2 / 2;
+
+	/* Also ensure we avoid integer overflow in nbatch and nbuckets */
 	/* (this step is redundant given the current value of MaxAllocSize) */
 	max_pointers = Min(max_pointers, INT_MAX / 2);
 
 	dbuckets = ceil(ntuples / NTUP_PER_BUCKET);
 	dbuckets = Min(dbuckets, max_pointers);
+	nbuckets = (int) dbuckets;
 	/* don't let nbuckets be really small, though ... */
-	nbuckets = Max((int) dbuckets, 1024);
+	nbuckets = Max(nbuckets, 1024);
 	/* ... and force it to be a power of 2. */
 	nbuckets = 1 << my_log2(nbuckets);