/*****************************************************************************/
/* static */
-const size_t Compiler::s_optCSEhashSize = EXPSET_SZ * 2;
+const size_t Compiler::s_optCSEhashSizeInitial = EXPSET_SZ * 2;
+const size_t Compiler::s_optCSEhashGrowthFactor = 2;
+const size_t Compiler::s_optCSEhashBucketSize = 4;
/*****************************************************************************
*
CSEdsc* dsc;
CSEdsc** ptr;
- unsigned cnt;
+ size_t cnt;
optCSEtab = new (this, CMK_CSE) CSEdsc*[optCSECandidateCount]();
- for (cnt = s_optCSEhashSize, ptr = optCSEhash; cnt; cnt--, ptr++)
+ for (cnt = optCSEhashSize, ptr = optCSEhash; cnt; cnt--, ptr++)
{
for (dsc = *ptr; dsc; dsc = dsc->csdNextInBucket)
{
cseMaskTraits = nullptr;
// Allocate and clear the hash bucket table
- optCSEhash = new (this, CMK_CSE) CSEdsc*[s_optCSEhashSize]();
+ optCSEhash = new (this, CMK_CSE) CSEdsc*[s_optCSEhashSizeInitial]();
+
+ optCSEhashSize = s_optCSEhashSizeInitial;
+ optCSEhashMaxCountBeforeResize = optCSEhashSize * s_optCSEhashBucketSize;
+ optCSEhashCount = 0;
optCSECandidateCount = 0;
optDoCSE = false; // Stays false until we find duplicate CSE tree
optCseCheckedBoundMap = nullptr;
}
+unsigned optCSEKeyToHashIndex(size_t key, size_t optCSEhashSize)
+{
+ unsigned hash;
+
+ hash = (unsigned)key;
+#ifdef TARGET_64BIT
+ hash ^= (unsigned)(key >> 32);
+#endif
+ hash *= (unsigned)(optCSEhashSize + 1);
+ hash >>= 7;
+
+ return hash % optCSEhashSize;
+}
+
//---------------------------------------------------------------------------
// optValnumCSE_Index:
// - Returns the CSE index to use for this tree,
unsigned Compiler::optValnumCSE_Index(GenTree* tree, Statement* stmt)
{
size_t key;
- unsigned hash;
unsigned hval;
CSEdsc* hashDsc;
bool isIntConstHash = false;
// Compute the hash value for the expression
- hash = (unsigned)key;
-#ifdef TARGET_64BIT
- hash ^= (unsigned)(key >> 32);
-#endif
- hash *= (unsigned)(s_optCSEhashSize + 1);
- hash >>= 7;
-
- hval = hash % s_optCSEhashSize;
+ hval = optCSEKeyToHashIndex(key, optCSEhashSize);
/* Look for a matching index in the hash table */
if (optCSECandidateCount < MAX_CSE_CNT)
{
+ if (optCSEhashCount == optCSEhashMaxCountBeforeResize)
+ {
+ size_t newOptCSEhashSize = optCSEhashSize * s_optCSEhashGrowthFactor;
+ CSEdsc** newOptCSEhash = new (this, CMK_CSE) CSEdsc*[newOptCSEhashSize]();
+
+ // Iterate through each existing entry, moving to the new table
+ CSEdsc** ptr;
+ CSEdsc* dsc;
+ size_t cnt;
+ for (cnt = optCSEhashSize, ptr = optCSEhash; cnt; cnt--, ptr++)
+ {
+ for (dsc = *ptr; dsc;)
+ {
+ CSEdsc* nextDsc = dsc->csdNextInBucket;
+
+ size_t newHval = optCSEKeyToHashIndex(dsc->csdHashKey, newOptCSEhashSize);
+
+ // Move CSEdsc to bucket in enlarged table
+ dsc->csdNextInBucket = newOptCSEhash[newHval];
+ newOptCSEhash[newHval] = dsc;
+
+ dsc = nextDsc;
+ }
+ }
+
+ optCSEhash = newOptCSEhash;
+ optCSEhashSize = newOptCSEhashSize;
+ optCSEhashMaxCountBeforeResize = optCSEhashMaxCountBeforeResize * s_optCSEhashGrowthFactor;
+ }
+
+ ++optCSEhashCount;
hashDsc = new (this, CMK_CSE) CSEdsc;
hashDsc->csdHashKey = key;