From f59daf2104a8e08a49ab9e074e5dcd30fe5f0939 Mon Sep 17 00:00:00 2001
From: Anatol Belski <ab@php.net>
Date: Wed, 22 Oct 2014 15:28:54 +0200
Subject: [PATCH] micro optimized initial hash size calculation

most of the calls are with a size <= 8, so don't even bother any
bitshifts. For the bigger sizes, use an intrinsic (should be extended
with gcc ones though).
---
 Zend/zend_hash.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index dfd63aa7e1..d3423c842f 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -99,7 +99,6 @@ static const uint32_t uninitialized_bucket = {INVALID_IDX};
 
 ZEND_API void _zend_hash_init(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
 {
-	uint32_t i = 3;
 
 	SET_INCONSISTENT(HT_OK);
 
@@ -107,10 +106,23 @@ ZEND_API void _zend_hash_init(HashTable *ht, uint32_t nSize, dtor_func_t pDestru
 		/* prevent overflow */
 		ht->nTableSize = 0x80000000;
 	} else {
-		while ((1U << i) < nSize) {
-			i++;
+		if (nSize > 8) {
+#ifdef PHP_WIN32
+			ht->nTableSize = 1U << __lzcnt(nSize);
+			if (ht->nTableSize < nSize) {
+				ht->nTableSize <<= 1;
+			}
+#else
+			uint32_t i = 4;
+
+			while ((1U << i) < nSize) {
+				i++;
+			}
+			ht->nTableSize = 1 << i;
+#endif
+		} else {
+			ht->nTableSize = 8;
 		}
-		ht->nTableSize = 1 << i;
 	}
 
 	ht->nTableMask = 0;	/* 0 means that ht->arBuckets is uninitialized */
-- 
2.40.0