From 6eb1a88c9c9974a59b8fe1a08ae47170ff22e1c8 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Wed, 20 Jul 2022 17:41:39 -0700 Subject: [PATCH 01/29] wip: assertionProp hashtable --- src/coreclr/jit/assertionprop.cpp | 29 +++++++- src/coreclr/jit/compiler.h | 110 ++++++++++++++++++++++++++++++ src/coreclr/jit/compiler.hpp | 6 ++ 3 files changed, 144 insertions(+), 1 deletion(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index be3a8cc7af8a3f..549bdedf30683e 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -944,6 +944,8 @@ void Compiler::optAssertionTraitsInit(AssertionIndex assertionCount) * Initialize the assertion prop tracking logic. */ +bool Compiler::AssertionDscKeyFuncs::isLocalProp = false; + void Compiler::optAssertionInit(bool isLocalProp) { // Use a function countFunc to determine a proper maximum assertion count for the @@ -956,11 +958,14 @@ void Compiler::optAssertionInit(bool isLocalProp) static const unsigned upperBound = ArrLen(countFunc) - 1; const unsigned codeSize = info.compILCodeSize / 512; optMaxAssertionCount = countFunc[isLocalProp ? lowerBound : min(upperBound, codeSize)]; + AssertionDscKeyFuncs::isLocalProp = isLocalProp; optLocalAssertionProp = isLocalProp; optAssertionTabPrivate = new (this, CMK_AssertionProp) AssertionDsc[optMaxAssertionCount]; optComplementaryAssertionMap = new (this, CMK_AssertionProp) AssertionIndex[optMaxAssertionCount + 1](); // zero-inited (NO_ASSERTION_INDEX) + optAssertionDscMap = AssertionDscMap(getAllocator()); + assert(NO_ASSERTION_INDEX == 0); if (!isLocalProp) @@ -1967,22 +1972,44 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) return NO_ASSERTION_INDEX; } + bool found = false; + AssertionIndex slowAnswer = NO_ASSERTION_INDEX; + AssertionIndex fastAnswer = NO_ASSERTION_INDEX; + // Check if exists already, so we can skip adding new one. Search backwards. for (AssertionIndex index = optAssertionCount; index >= 1; index--) { AssertionDsc* curAssertion = optGetAssertion(index); if (curAssertion->Equals(newAssertion, !optLocalAssertionProp)) { - return index; + found = true; + slowAnswer = index; + break; } } + if (optAssertionDscMap.Lookup(*newAssertion, &fastAnswer)) + { + assert(slowAnswer == fastAnswer); + } + else + { + assert(!found); + } + + if (found) + { + return slowAnswer; + } + // Check if we are within max count. if (optAssertionCount >= optMaxAssertionCount) { return NO_ASSERTION_INDEX; } + optAssertionDscMap.Set(*newAssertion, optAssertionCount + 1); + optAssertionTabPrivate[optAssertionCount] = *newAssertion; optAssertionCount++; diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index f397d4bcd9e883..cb6c962566833e 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7144,6 +7144,23 @@ class Compiler } bool HasSameOp2(AssertionDsc* that, bool vnBased) + { + if (op1.kind != that.op1.kind) + { + return false; + } + else if (op1.kind == O1K_ARR_BND) + { + assert(vnBased); + return (op1.bnd.vnIdx == that.op1.bnd.vnIdx) && (op1.bnd.vnLen == that.op1.bnd.vnLen); + } + else + { + return ((vnBased && (op1.vn == that.op1.vn)) || + (!vnBased && (op1.lcl.lclNum == that.op1.lcl.lclNum))); + } + } + { if (op2.kind != that->op2.kind) { @@ -7189,6 +7206,44 @@ class Compiler { return ComplementaryKind(assertionKind, that->assertionKind) && HasSameOp1(that, vnBased) && HasSameOp2(that, vnBased); + } + + switch (op2.kind) + { + case O2K_IND_CNS_INT: + case O2K_CONST_INT: + return ((op2.u1.iconVal == that.op2.u1.iconVal) && (op2.u1.iconFlags == that.op2.u1.iconFlags)); + + case O2K_CONST_LONG: + return (op2.lconVal == that.op2.lconVal); + + case O2K_CONST_DOUBLE: + // exact match because of positive and negative zero. + return (memcmp(&op2.dconVal, &that.op2.dconVal, sizeof(double)) == 0); + + case O2K_ZEROOBJ: + return true; + + case O2K_LCLVAR_COPY: + return (op2.lcl.lclNum == that.op2.lcl.lclNum) && + (!vnBased || (op2.lcl.ssaNum == that.op2.lcl.ssaNum)); + + case O2K_SUBRANGE: + return op2.u2.Equals(that.op2.u2); + + case O2K_INVALID: + // we will return false + break; + + default: + assert(!"Unexpected value for op2.kind in AssertionDsc."); + break; + } + + return false; + } + + { } bool Equals(AssertionDsc* that, bool vnBased) @@ -7207,6 +7262,30 @@ class Compiler return HasSameOp1(that, vnBased) && HasSameOp2(that, vnBased); } } + + static bool isLocalProp; + + static bool Equals(AssertionDsc dsc1, AssertionDsc dsc2, bool vnBased) + { + if (dsc1.assertionKind != dsc2.assertionKind) + { + return false; + } + else if (dsc1.assertionKind == OAK_NO_THROW) + { + assert(dsc1.op2.kind == O2K_INVALID); + return dsc1.HasSameOp1(dsc2, vnBased); + } + else + { + return dsc1.HasSameOp1(dsc2, vnBased) && dsc1.HasSameOp2(dsc2, vnBased); + } + } + + /*static bool Equals(AssertionDsc* dsc1, AssertionDsc* dsc2, bool vnBased) + { + return dsc1->Equals(dsc2, vnBased); + }*/ }; protected: @@ -7228,6 +7307,37 @@ class Compiler AssertionIndex optAssertionCount; // total number of assertions in the assertion table AssertionIndex optMaxAssertionCount; + struct AssertionDscKeyFuncs + { + public: + + static bool isLocalProp; + + static bool Equals(/*const */AssertionDsc x, /*const */AssertionDsc y) + { + return AssertionDsc::Equals(x, y, !isLocalProp); + } + + static unsigned GetHashCode(const AssertionDsc dsc) + { + /* + * 0 ~ 2 : assertionKind + * 3 ~ 6 : op1Kind + * 7 ~ 11: op2Kind + */ + //byte assertionKind = dsc->assertionKind; + //byte op1Kind = dsc->op1.kind; + //byte op2Kind = dsc->op2.kind; + unsigned result = ((dsc.op2.kind << 7) | (dsc.op1.kind << 3) | (dsc.assertionKind)); + //printf("hash= %u", result); + return result; + } + }; + + // Map from Block to Block. Used for a variety of purposes. + typedef JitHashTable AssertionDscMap; + AssertionDscMap optAssertionDscMap; + public: void optVnNonNullPropCurStmt(BasicBlock* block, Statement* stmt, GenTree* tree); fgWalkResult optVNConstantPropCurStmt(BasicBlock* block, Statement* stmt, GenTree* tree); diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index ae3da0f8b0d9c9..f55c78766c28d9 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -3254,6 +3254,9 @@ inline void Compiler::optAssertionReset(AssertionIndex limit) { AssertionIndex index = optAssertionCount; AssertionDsc* curAssertion = optGetAssertion(index); + optAssertionDscMap.Remove(*curAssertion); + //printf(", Removing optAssertionCount=%d\n", optAssertionCount); + optAssertionCount--; unsigned lclNum = curAssertion->op1.lcl.lclNum; assert(lclNum < lvaCount); @@ -3335,6 +3338,9 @@ inline void Compiler::optAssertionRemove(AssertionIndex index) BitVecOps::RemoveElemD(apTraits, GetAssertionDep(lclNum), index - 1); } + optAssertionDscMap.Remove(*curAssertion); + //printf(", Removing optAssertionCount=%d\n", optAssertionCount); + optAssertionCount--; } else From 40adb9d6c73db789b1d4692a8b9b22fb0eec3140 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Wed, 20 Jul 2022 17:51:54 -0700 Subject: [PATCH 02/29] code cleanup --- src/coreclr/jit/assertionprop.cpp | 23 ++++++++++++++++------- src/coreclr/jit/compiler.h | 15 ++------------- src/coreclr/jit/compiler.hpp | 11 ++++++++--- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 549bdedf30683e..7abd8be1b613dd 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -958,13 +958,15 @@ void Compiler::optAssertionInit(bool isLocalProp) static const unsigned upperBound = ArrLen(countFunc) - 1; const unsigned codeSize = info.compILCodeSize / 512; optMaxAssertionCount = countFunc[isLocalProp ? lowerBound : min(upperBound, codeSize)]; - AssertionDscKeyFuncs::isLocalProp = isLocalProp; + AssertionDscKeyFuncs::isLocalProp = isLocalProp; - optLocalAssertionProp = isLocalProp; + optLocalAssertionProp = isLocalProp; optAssertionTabPrivate = new (this, CMK_AssertionProp) AssertionDsc[optMaxAssertionCount]; optComplementaryAssertionMap = new (this, CMK_AssertionProp) AssertionIndex[optMaxAssertionCount + 1](); // zero-inited (NO_ASSERTION_INDEX) +#ifdef DEBUG optAssertionDscMap = AssertionDscMap(getAllocator()); +#endif assert(NO_ASSERTION_INDEX == 0); @@ -1973,8 +1975,11 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) } bool found = false; + +#ifdef DEBUG AssertionIndex slowAnswer = NO_ASSERTION_INDEX; AssertionIndex fastAnswer = NO_ASSERTION_INDEX; +#endif // Check if exists already, so we can skip adding new one. Search backwards. for (AssertionIndex index = optAssertionCount; index >= 1; index--) @@ -1982,25 +1987,27 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) AssertionDsc* curAssertion = optGetAssertion(index); if (curAssertion->Equals(newAssertion, !optLocalAssertionProp)) { +#ifdef DEBUG found = true; slowAnswer = index; break; +#else + return index; +#endif } } +#ifdef DEBUG if (optAssertionDscMap.Lookup(*newAssertion, &fastAnswer)) { assert(slowAnswer == fastAnswer); + return slowAnswer; } else { assert(!found); } - - if (found) - { - return slowAnswer; - } +#endif // DEBUG // Check if we are within max count. if (optAssertionCount >= optMaxAssertionCount) @@ -2008,7 +2015,9 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) return NO_ASSERTION_INDEX; } +#ifdef DEBUG optAssertionDscMap.Set(*newAssertion, optAssertionCount + 1); +#endif optAssertionTabPrivate[optAssertionCount] = *newAssertion; optAssertionCount++; diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index cb6c962566833e..a83136f209a5e7 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7156,8 +7156,7 @@ class Compiler } else { - return ((vnBased && (op1.vn == that.op1.vn)) || - (!vnBased && (op1.lcl.lclNum == that.op1.lcl.lclNum))); + return ((vnBased && (op1.vn == that.op1.vn)) || (!vnBased && (op1.lcl.lclNum == that.op1.lcl.lclNum))); } } @@ -7281,11 +7280,6 @@ class Compiler return dsc1.HasSameOp1(dsc2, vnBased) && dsc1.HasSameOp2(dsc2, vnBased); } } - - /*static bool Equals(AssertionDsc* dsc1, AssertionDsc* dsc2, bool vnBased) - { - return dsc1->Equals(dsc2, vnBased); - }*/ }; protected: @@ -7310,10 +7304,9 @@ class Compiler struct AssertionDscKeyFuncs { public: - static bool isLocalProp; - static bool Equals(/*const */AssertionDsc x, /*const */AssertionDsc y) + static bool Equals(const AssertionDsc x, const AssertionDsc y) { return AssertionDsc::Equals(x, y, !isLocalProp); } @@ -7325,11 +7318,7 @@ class Compiler * 3 ~ 6 : op1Kind * 7 ~ 11: op2Kind */ - //byte assertionKind = dsc->assertionKind; - //byte op1Kind = dsc->op1.kind; - //byte op2Kind = dsc->op2.kind; unsigned result = ((dsc.op2.kind << 7) | (dsc.op1.kind << 3) | (dsc.assertionKind)); - //printf("hash= %u", result); return result; } }; diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index f55c78766c28d9..f813277c91da87 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -3254,8 +3254,9 @@ inline void Compiler::optAssertionReset(AssertionIndex limit) { AssertionIndex index = optAssertionCount; AssertionDsc* curAssertion = optGetAssertion(index); +#ifdef DEBUG optAssertionDscMap.Remove(*curAssertion); - //printf(", Removing optAssertionCount=%d\n", optAssertionCount); +#endif optAssertionCount--; unsigned lclNum = curAssertion->op1.lcl.lclNum; @@ -3279,6 +3280,10 @@ inline void Compiler::optAssertionReset(AssertionIndex limit) { AssertionIndex index = ++optAssertionCount; AssertionDsc* curAssertion = optGetAssertion(index); + +#ifdef DEBUG + optAssertionDscMap.Set(*curAssertion, optAssertionCount); +#endif unsigned lclNum = curAssertion->op1.lcl.lclNum; BitVecOps::AddElemD(apTraits, GetAssertionDep(lclNum), index - 1); @@ -3338,9 +3343,9 @@ inline void Compiler::optAssertionRemove(AssertionIndex index) BitVecOps::RemoveElemD(apTraits, GetAssertionDep(lclNum), index - 1); } +#ifdef DEBUG optAssertionDscMap.Remove(*curAssertion); - //printf(", Removing optAssertionCount=%d\n", optAssertionCount); - +#endif optAssertionCount--; } else From aa30e03d6989e9c7146dd2681ec62763924dbac7 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Thu, 21 Jul 2022 11:17:29 -0700 Subject: [PATCH 03/29] wip for global/local --- src/coreclr/jit/assertionprop.cpp | 24 ++++++++-- src/coreclr/jit/compiler.h | 77 ++++++++++++++++++++++++++++++- src/coreclr/jit/compiler.hpp | 31 ++++++++++++- 3 files changed, 125 insertions(+), 7 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 7abd8be1b613dd..1c02c3bfafe20e 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -944,10 +944,11 @@ void Compiler::optAssertionTraitsInit(AssertionIndex assertionCount) * Initialize the assertion prop tracking logic. */ -bool Compiler::AssertionDscKeyFuncs::isLocalProp = false; +//bool Compiler::AssertionDscKeyFuncs::isLocalProp = false; void Compiler::optAssertionInit(bool isLocalProp) { + printf("optAssertionInit= %d\n", isLocalProp); // Use a function countFunc to determine a proper maximum assertion count for the // method being compiled. The function is linear to the IL size for small and // moderate methods. For large methods, considering throughput impact, we track no @@ -958,14 +959,21 @@ void Compiler::optAssertionInit(bool isLocalProp) static const unsigned upperBound = ArrLen(countFunc) - 1; const unsigned codeSize = info.compILCodeSize / 512; optMaxAssertionCount = countFunc[isLocalProp ? lowerBound : min(upperBound, codeSize)]; - AssertionDscKeyFuncs::isLocalProp = isLocalProp; + //AssertionDscKeyFuncs::isLocalProp = isLocalProp; optLocalAssertionProp = isLocalProp; optAssertionTabPrivate = new (this, CMK_AssertionProp) AssertionDsc[optMaxAssertionCount]; optComplementaryAssertionMap = new (this, CMK_AssertionProp) AssertionIndex[optMaxAssertionCount + 1](); // zero-inited (NO_ASSERTION_INDEX) #ifdef DEBUG - optAssertionDscMap = AssertionDscMap(getAllocator()); + if (isLocalProp) + { + optAssertionDscMap = AssertionDscMap(getAllocator()); + } + else + { + optAssertionDscMap = AssertionDscMap(getAllocator()); + } #endif assert(NO_ASSERTION_INDEX == 0); @@ -2005,6 +2013,7 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) } else { + //printf("%u not found\n", AssertionDscKeyFuncs::GetHashCode(*newAssertion)); assert(!found); } #endif // DEBUG @@ -2018,7 +2027,14 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) #ifdef DEBUG optAssertionDscMap.Set(*newAssertion, optAssertionCount + 1); #endif - + if (optLocalAssertionProp) + { + printf("++ Added map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs::GetHashCode(*newAssertion)); + } + else + { + printf("++ Added map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs::GetHashCode(*newAssertion)); + } optAssertionTabPrivate[optAssertionCount] = *newAssertion; optAssertionCount++; diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index a83136f209a5e7..30a92b95e482a6 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7301,6 +7301,68 @@ class Compiler AssertionIndex optAssertionCount; // total number of assertions in the assertion table AssertionIndex optMaxAssertionCount; + + struct AssertionDscKeyFuncs_Local + { + public: + static bool Equals(const AssertionDsc x, const AssertionDsc y) + { + return AssertionDsc::Equals(x, y, false); + } + + static unsigned GetHashCode(const AssertionDsc dsc) + { + /* + * 0 ~ 2 : assertionKind + * 3 ~ 6 : op1Kind + * 7 ~ 11: op2Kind + */ + unsigned result = ((dsc.op2.kind << 7) | (dsc.op1.kind << 3) | (dsc.assertionKind)); + return result; + } + }; + + struct AssertionDscKeyFuncs_Global + { + public: + static bool Equals(const AssertionDsc x, const AssertionDsc y) + { + return AssertionDsc::Equals(x, y, true); + } + + static unsigned GetHashCode(const AssertionDsc dsc) + { + /* + * 0 ~ 2 : assertionKind + * 3 ~ 6 : op1Kind + * 7 ~ 11: op2Kind + */ + unsigned result = ((dsc.op2.kind << 7) | (dsc.op1.kind << 3) | (dsc.assertionKind)); + return result; + } + }; + + template + class AssertionDscHashTable : JitHashTable + { + + }; + + template + class AssertionDscHashTable_Local : AssertionDscHashTable + { + }; + + template + class AssertionDscHashTable_Global : AssertionDscHashTable + { + }; + + template struct AssertionDscKeyFuncs { public: @@ -7308,7 +7370,7 @@ class Compiler static bool Equals(const AssertionDsc x, const AssertionDsc y) { - return AssertionDsc::Equals(x, y, !isLocalProp); + return AssertionDsc::Equals(x, y, !isLocal); } static unsigned GetHashCode(const AssertionDsc dsc) @@ -7324,7 +7386,18 @@ class Compiler }; // Map from Block to Block. Used for a variety of purposes. - typedef JitHashTable AssertionDscMap; + //typedef JitHashTable, AssertionIndex> AssertionDscMap; + //typedef JitHashTable, AssertionIndex> AssertionDscMap; + + //template + /*using AssertionDscMap_Local = JitHashTable, AssertionIndex>; + using AssertionDscMap_Global = JitHashTable, AssertionIndex>;*/ + + //typedef AssertionDscMap + typedef JitHashTable, AssertionIndex> AssertionDscMap; + + + //TODO: Use pointer AssertionDscMap optAssertionDscMap; public: diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index f813277c91da87..934e9a1fa38d63 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -3257,8 +3257,16 @@ inline void Compiler::optAssertionReset(AssertionIndex limit) #ifdef DEBUG optAssertionDscMap.Remove(*curAssertion); #endif - + optAssertionCount--; + if (optLocalAssertionProp) + { + printf("-- Removed map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs::GetHashCode(*curAssertion)); + } + else + { + printf("-- Removed map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs::GetHashCode(*curAssertion)); + } unsigned lclNum = curAssertion->op1.lcl.lclNum; assert(lclNum < lvaCount); BitVecOps::RemoveElemD(apTraits, GetAssertionDep(lclNum), index - 1); @@ -3284,6 +3292,17 @@ inline void Compiler::optAssertionReset(AssertionIndex limit) #ifdef DEBUG optAssertionDscMap.Set(*curAssertion, optAssertionCount); #endif + if (optLocalAssertionProp) + { + printf("++ Added map[%d] = %u\n", optAssertionCount - 1, + AssertionDscKeyFuncs::GetHashCode(*curAssertion)); + } + else + { + printf("++ Added map[%d] = %u\n", optAssertionCount - 1, + AssertionDscKeyFuncs::GetHashCode(*curAssertion)); + } + unsigned lclNum = curAssertion->op1.lcl.lclNum; BitVecOps::AddElemD(apTraits, GetAssertionDep(lclNum), index - 1); @@ -3347,6 +3366,16 @@ inline void Compiler::optAssertionRemove(AssertionIndex index) optAssertionDscMap.Remove(*curAssertion); #endif optAssertionCount--; + if (optLocalAssertionProp) + { + printf("-- Removed map[%d] = %u\n", optAssertionCount, + AssertionDscKeyFuncs::GetHashCode(*curAssertion)); + } + else + { + printf("-- Removed map[%d] = %u\n", optAssertionCount, + AssertionDscKeyFuncs::GetHashCode(*curAssertion)); + } } else { From 3c4f5f9d6fdf01a2eca77fd858d48a019d40389c Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Thu, 21 Jul 2022 13:51:01 -0700 Subject: [PATCH 04/29] wip --- src/coreclr/jit/assertionprop.cpp | 16 ++++++++-------- src/coreclr/jit/compiler.h | 8 ++++---- src/coreclr/jit/compiler.hpp | 12 ++++++------ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 1c02c3bfafe20e..faedc21fc08be2 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -944,7 +944,7 @@ void Compiler::optAssertionTraitsInit(AssertionIndex assertionCount) * Initialize the assertion prop tracking logic. */ -//bool Compiler::AssertionDscKeyFuncs::isLocalProp = false; +bool Compiler::AssertionDscKeyFuncs::isLocalProp = false; void Compiler::optAssertionInit(bool isLocalProp) { @@ -959,21 +959,21 @@ void Compiler::optAssertionInit(bool isLocalProp) static const unsigned upperBound = ArrLen(countFunc) - 1; const unsigned codeSize = info.compILCodeSize / 512; optMaxAssertionCount = countFunc[isLocalProp ? lowerBound : min(upperBound, codeSize)]; - //AssertionDscKeyFuncs::isLocalProp = isLocalProp; + AssertionDscKeyFuncs::isLocalProp = isLocalProp; optLocalAssertionProp = isLocalProp; optAssertionTabPrivate = new (this, CMK_AssertionProp) AssertionDsc[optMaxAssertionCount]; optComplementaryAssertionMap = new (this, CMK_AssertionProp) AssertionIndex[optMaxAssertionCount + 1](); // zero-inited (NO_ASSERTION_INDEX) #ifdef DEBUG - if (isLocalProp) + //if (isLocalProp) { - optAssertionDscMap = AssertionDscMap(getAllocator()); + optAssertionDscMap = AssertionDscMap(getAllocator()); } - else + /*else { optAssertionDscMap = AssertionDscMap(getAllocator()); - } + }*/ #endif assert(NO_ASSERTION_INDEX == 0); @@ -2029,11 +2029,11 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) #endif if (optLocalAssertionProp) { - printf("++ Added map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs::GetHashCode(*newAssertion)); + printf("++ Added map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs/**/::GetHashCode(*newAssertion)); } else { - printf("++ Added map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs::GetHashCode(*newAssertion)); + printf("++ Added map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs/**/::GetHashCode(*newAssertion)); } optAssertionTabPrivate[optAssertionCount] = *newAssertion; optAssertionCount++; diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 30a92b95e482a6..35a08d9cd95512 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7345,7 +7345,7 @@ class Compiler template - class AssertionDscHashTable : JitHashTable + class AssertionDscHashTable : JitHashTable { }; @@ -7362,7 +7362,7 @@ class Compiler { }; - template + //template struct AssertionDscKeyFuncs { public: @@ -7370,7 +7370,7 @@ class Compiler static bool Equals(const AssertionDsc x, const AssertionDsc y) { - return AssertionDsc::Equals(x, y, !isLocal); + return AssertionDsc::Equals(x, y, !isLocalProp); } static unsigned GetHashCode(const AssertionDsc dsc) @@ -7394,7 +7394,7 @@ class Compiler using AssertionDscMap_Global = JitHashTable, AssertionIndex>;*/ //typedef AssertionDscMap - typedef JitHashTable, AssertionIndex> AssertionDscMap; + typedef JitHashTable AssertionDscMap; //TODO: Use pointer diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index 934e9a1fa38d63..c03a3a54ac128b 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -3261,11 +3261,11 @@ inline void Compiler::optAssertionReset(AssertionIndex limit) optAssertionCount--; if (optLocalAssertionProp) { - printf("-- Removed map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs::GetHashCode(*curAssertion)); + printf("-- Removed map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs::GetHashCode(*curAssertion)); } else { - printf("-- Removed map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs::GetHashCode(*curAssertion)); + printf("-- Removed map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs::GetHashCode(*curAssertion)); } unsigned lclNum = curAssertion->op1.lcl.lclNum; assert(lclNum < lvaCount); @@ -3295,12 +3295,12 @@ inline void Compiler::optAssertionReset(AssertionIndex limit) if (optLocalAssertionProp) { printf("++ Added map[%d] = %u\n", optAssertionCount - 1, - AssertionDscKeyFuncs::GetHashCode(*curAssertion)); + AssertionDscKeyFuncs/**/::GetHashCode(*curAssertion)); } else { printf("++ Added map[%d] = %u\n", optAssertionCount - 1, - AssertionDscKeyFuncs::GetHashCode(*curAssertion)); + AssertionDscKeyFuncs/**/::GetHashCode(*curAssertion)); } unsigned lclNum = curAssertion->op1.lcl.lclNum; @@ -3369,12 +3369,12 @@ inline void Compiler::optAssertionRemove(AssertionIndex index) if (optLocalAssertionProp) { printf("-- Removed map[%d] = %u\n", optAssertionCount, - AssertionDscKeyFuncs::GetHashCode(*curAssertion)); + AssertionDscKeyFuncs/**/::GetHashCode(*curAssertion)); } else { printf("-- Removed map[%d] = %u\n", optAssertionCount, - AssertionDscKeyFuncs::GetHashCode(*curAssertion)); + AssertionDscKeyFuncs/**/::GetHashCode(*curAssertion)); } } else From c43208a0d5a49728f5821bcd7445bca3ee455cf9 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Thu, 21 Jul 2022 14:25:08 -0700 Subject: [PATCH 05/29] more wip funcs_global/funcs_local --- src/coreclr/jit/assertionprop.cpp | 10 ++--- src/coreclr/jit/compiler.h | 74 +++++++++++++++---------------- src/coreclr/jit/compiler.hpp | 6 +-- 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index faedc21fc08be2..7c74c299215c6c 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -966,14 +966,14 @@ void Compiler::optAssertionInit(bool isLocalProp) optComplementaryAssertionMap = new (this, CMK_AssertionProp) AssertionIndex[optMaxAssertionCount + 1](); // zero-inited (NO_ASSERTION_INDEX) #ifdef DEBUG - //if (isLocalProp) + if (isLocalProp) { - optAssertionDscMap = AssertionDscMap(getAllocator()); + optAssertionDscMap = new (getAllocator()) AssertionDscHashTable_Local(); } - /*else + else { - optAssertionDscMap = AssertionDscMap(getAllocator()); - }*/ + optAssertionDscMap = new (getAllocator()) AssertionDscHashTable_Global(); + } #endif assert(NO_ASSERTION_INDEX == 0); diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 35a08d9cd95512..b5d0ff048c85ca 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7301,8 +7301,30 @@ class Compiler AssertionIndex optAssertionCount; // total number of assertions in the assertion table AssertionIndex optMaxAssertionCount; + //template + struct AssertionDscKeyFuncs + { + public: + static bool isLocalProp; + + static bool Equals(const AssertionDsc x, const AssertionDsc y) + { + return AssertionDsc::Equals(x, y, !isLocalProp); + } + + static unsigned GetHashCode(const AssertionDsc dsc) + { + /* + * 0 ~ 2 : assertionKind + * 3 ~ 6 : op1Kind + * 7 ~ 11: op2Kind + */ + unsigned result = ((dsc.op2.kind << 7) | (dsc.op1.kind << 3) | (dsc.assertionKind)); + return result; + } + }; - struct AssertionDscKeyFuncs_Local + struct AssertionDscKeyFuncs_Local : AssertionDscKeyFuncs { public: static bool Equals(const AssertionDsc x, const AssertionDsc y) @@ -7322,7 +7344,7 @@ class Compiler } }; - struct AssertionDscKeyFuncs_Global + struct AssertionDscKeyFuncs_Global: AssertionDscKeyFuncs { public: static bool Equals(const AssertionDsc x, const AssertionDsc y) @@ -7342,48 +7364,24 @@ class Compiler } }; - template - class AssertionDscHashTable : JitHashTable + template + class AssertionDscHashTable : public JitHashTable { - + public: + AssertionDscHashTable() : JitHashTable(getAllocator()) + { + } }; - template - class AssertionDscHashTable_Local : AssertionDscHashTable + class AssertionDscHashTable_Local : AssertionDscHashTable { }; - template - class AssertionDscHashTable_Global : AssertionDscHashTable + class AssertionDscHashTable_Global : AssertionDscHashTable { }; - //template - struct AssertionDscKeyFuncs - { - public: - static bool isLocalProp; - - static bool Equals(const AssertionDsc x, const AssertionDsc y) - { - return AssertionDsc::Equals(x, y, !isLocalProp); - } - - static unsigned GetHashCode(const AssertionDsc dsc) - { - /* - * 0 ~ 2 : assertionKind - * 3 ~ 6 : op1Kind - * 7 ~ 11: op2Kind - */ - unsigned result = ((dsc.op2.kind << 7) | (dsc.op1.kind << 3) | (dsc.assertionKind)); - return result; - } - }; + // Map from Block to Block. Used for a variety of purposes. //typedef JitHashTable, AssertionIndex> AssertionDscMap; @@ -7394,11 +7392,13 @@ class Compiler using AssertionDscMap_Global = JitHashTable, AssertionIndex>;*/ //typedef AssertionDscMap - typedef JitHashTable AssertionDscMap; + //typedef JitHashTable AssertionDscMap; //TODO: Use pointer - AssertionDscMap optAssertionDscMap; + //AssertionDscMap optAssertionDscMap; + + AssertionDscHashTable<>* optAssertionDscMap; public: void optVnNonNullPropCurStmt(BasicBlock* block, Statement* stmt, GenTree* tree); diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index c03a3a54ac128b..41ac4f83578acd 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -3255,7 +3255,7 @@ inline void Compiler::optAssertionReset(AssertionIndex limit) AssertionIndex index = optAssertionCount; AssertionDsc* curAssertion = optGetAssertion(index); #ifdef DEBUG - optAssertionDscMap.Remove(*curAssertion); + optAssertionDscMap->Remove(*curAssertion); #endif optAssertionCount--; @@ -3290,7 +3290,7 @@ inline void Compiler::optAssertionReset(AssertionIndex limit) AssertionDsc* curAssertion = optGetAssertion(index); #ifdef DEBUG - optAssertionDscMap.Set(*curAssertion, optAssertionCount); + optAssertionDscMap->Set(*curAssertion, optAssertionCount); #endif if (optLocalAssertionProp) { @@ -3363,7 +3363,7 @@ inline void Compiler::optAssertionRemove(AssertionIndex index) } #ifdef DEBUG - optAssertionDscMap.Remove(*curAssertion); + optAssertionDscMap->Remove(*curAssertion); #endif optAssertionCount--; if (optLocalAssertionProp) From b6f0f9ae98adf59abc956ab7aa5db7b6ade592b3 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Thu, 21 Jul 2022 15:41:34 -0700 Subject: [PATCH 06/29] more wip funcs_global/funcs_local --- src/coreclr/jit/assertionprop.cpp | 29 ++-- src/coreclr/jit/compiler.h | 224 ++++++++++++------------------ 2 files changed, 103 insertions(+), 150 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 7c74c299215c6c..7711887eb834c6 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -960,21 +960,26 @@ void Compiler::optAssertionInit(bool isLocalProp) const unsigned codeSize = info.compILCodeSize / 512; optMaxAssertionCount = countFunc[isLocalProp ? lowerBound : min(upperBound, codeSize)]; AssertionDscKeyFuncs::isLocalProp = isLocalProp; + AssertionDscKeyFuncs::hashCodeFn = &AssertionDscKeyFuncs::GetHashCodeGlobal; + optLocalAssertionProp = isLocalProp; optAssertionTabPrivate = new (this, CMK_AssertionProp) AssertionDsc[optMaxAssertionCount]; optComplementaryAssertionMap = new (this, CMK_AssertionProp) AssertionIndex[optMaxAssertionCount + 1](); // zero-inited (NO_ASSERTION_INDEX) -#ifdef DEBUG - if (isLocalProp) - { - optAssertionDscMap = new (getAllocator()) AssertionDscHashTable_Local(); - } - else - { - optAssertionDscMap = new (getAllocator()) AssertionDscHashTable_Global(); - } -#endif + + optAssertionDscMap = new (getAllocator()) AssertionDscMap(getAllocator()); + +//#ifdef DEBUG +// if (isLocalProp) +// { +// optAssertionDscMap = new (getAllocator()) AssertionDscMap(); +// } +// else +// { +// optAssertionDscMap = new (getAllocator()) AssertionDscHashTable_Global(); +// } +//#endif assert(NO_ASSERTION_INDEX == 0); @@ -2006,7 +2011,7 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) } #ifdef DEBUG - if (optAssertionDscMap.Lookup(*newAssertion, &fastAnswer)) + if (optAssertionDscMap->Lookup(*newAssertion, &fastAnswer)) { assert(slowAnswer == fastAnswer); return slowAnswer; @@ -2025,7 +2030,7 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) } #ifdef DEBUG - optAssertionDscMap.Set(*newAssertion, optAssertionCount + 1); + optAssertionDscMap->Set(*newAssertion, optAssertionCount + 1); #endif if (optLocalAssertionProp) { diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index b5d0ff048c85ca..c9b6cfaa77eb64 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7126,6 +7126,17 @@ class Compiler } bool HasSameOp1(AssertionDsc* that, bool vnBased) + + unsigned GetHashCode() + { + /* + * 0 ~ 2 : assertionKind + * 3 ~ 6 : op1Kind + * 7 ~ 11: op2Kind + */ + unsigned result = ((op2.kind << 7) | (op1.kind << 3) | (assertionKind)); + return result; + } { if (op1.kind != that->op1.kind) { @@ -7144,22 +7155,6 @@ class Compiler } bool HasSameOp2(AssertionDsc* that, bool vnBased) - { - if (op1.kind != that.op1.kind) - { - return false; - } - else if (op1.kind == O1K_ARR_BND) - { - assert(vnBased); - return (op1.bnd.vnIdx == that.op1.bnd.vnIdx) && (op1.bnd.vnLen == that.op1.bnd.vnLen); - } - else - { - return ((vnBased && (op1.vn == that.op1.vn)) || (!vnBased && (op1.lcl.lclNum == that.op1.lcl.lclNum))); - } - } - { if (op2.kind != that->op2.kind) { @@ -7205,44 +7200,6 @@ class Compiler { return ComplementaryKind(assertionKind, that->assertionKind) && HasSameOp1(that, vnBased) && HasSameOp2(that, vnBased); - } - - switch (op2.kind) - { - case O2K_IND_CNS_INT: - case O2K_CONST_INT: - return ((op2.u1.iconVal == that.op2.u1.iconVal) && (op2.u1.iconFlags == that.op2.u1.iconFlags)); - - case O2K_CONST_LONG: - return (op2.lconVal == that.op2.lconVal); - - case O2K_CONST_DOUBLE: - // exact match because of positive and negative zero. - return (memcmp(&op2.dconVal, &that.op2.dconVal, sizeof(double)) == 0); - - case O2K_ZEROOBJ: - return true; - - case O2K_LCLVAR_COPY: - return (op2.lcl.lclNum == that.op2.lcl.lclNum) && - (!vnBased || (op2.lcl.ssaNum == that.op2.lcl.ssaNum)); - - case O2K_SUBRANGE: - return op2.u2.Equals(that.op2.u2); - - case O2K_INVALID: - // we will return false - break; - - default: - assert(!"Unexpected value for op2.kind in AssertionDsc."); - break; - } - - return false; - } - - { } bool Equals(AssertionDsc* that, bool vnBased) @@ -7262,23 +7219,16 @@ class Compiler } } - static bool isLocalProp; - - static bool Equals(AssertionDsc dsc1, AssertionDsc dsc2, bool vnBased) + public: + unsigned GetHashCode() { - if (dsc1.assertionKind != dsc2.assertionKind) - { - return false; - } - else if (dsc1.assertionKind == OAK_NO_THROW) - { - assert(dsc1.op2.kind == O2K_INVALID); - return dsc1.HasSameOp1(dsc2, vnBased); - } - else - { - return dsc1.HasSameOp1(dsc2, vnBased) && dsc1.HasSameOp2(dsc2, vnBased); - } + /* + * 0 ~ 2 : assertionKind + * 3 ~ 6 : op1Kind + * 7 ~ 11: op2Kind + */ + unsigned result = ((op2.kind << 7) | (op1.kind << 3) | (assertionKind)); + return result; } }; @@ -7306,82 +7256,85 @@ class Compiler { public: static bool isLocalProp; + static unsigned (*hashCodeFn)(AssertionDsc); - static bool Equals(const AssertionDsc x, const AssertionDsc y) + static bool Equals(AssertionDsc x, AssertionDsc y) { - return AssertionDsc::Equals(x, y, !isLocalProp); + AssertionDsc* _x = &x; + return _x->Equals(&y); } - static unsigned GetHashCode(const AssertionDsc dsc) + static unsigned GetHashCode(AssertionDsc dsc) { - /* - * 0 ~ 2 : assertionKind - * 3 ~ 6 : op1Kind - * 7 ~ 11: op2Kind - */ - unsigned result = ((dsc.op2.kind << 7) | (dsc.op1.kind << 3) | (dsc.assertionKind)); - return result; + AssertionDsc* _dsc = &dsc; + return _dsc->GetHashCode(); } - }; - struct AssertionDscKeyFuncs_Local : AssertionDscKeyFuncs - { - public: - static bool Equals(const AssertionDsc x, const AssertionDsc y) - { - return AssertionDsc::Equals(x, y, false); - } - static unsigned GetHashCode(const AssertionDsc dsc) + static unsigned GetHashCodeGlobal(AssertionDsc dsc) { - /* - * 0 ~ 2 : assertionKind - * 3 ~ 6 : op1Kind - * 7 ~ 11: op2Kind - */ - unsigned result = ((dsc.op2.kind << 7) | (dsc.op1.kind << 3) | (dsc.assertionKind)); - return result; + AssertionDsc* _dsc = &dsc; + return _dsc->GetHashCode(); } - }; - struct AssertionDscKeyFuncs_Global: AssertionDscKeyFuncs - { - public: - static bool Equals(const AssertionDsc x, const AssertionDsc y) + static unsigned GetHashCodeLocal(AssertionDsc dsc) { - return AssertionDsc::Equals(x, y, true); - } - - static unsigned GetHashCode(const AssertionDsc dsc) - { - /* - * 0 ~ 2 : assertionKind - * 3 ~ 6 : op1Kind - * 7 ~ 11: op2Kind - */ - unsigned result = ((dsc.op2.kind << 7) | (dsc.op1.kind << 3) | (dsc.assertionKind)); - return result; + return hashCodeFn(dsc); + /*AssertionDsc* _dsc = &dsc; + return _dsc->GetHashCode();*/ } }; - template - class AssertionDscHashTable : public JitHashTable - { - public: - AssertionDscHashTable() : JitHashTable(getAllocator()) - { - } - }; - - class AssertionDscHashTable_Local : AssertionDscHashTable - { - }; - - class AssertionDscHashTable_Global : AssertionDscHashTable - { - }; - - + //struct AssertionDscKeyFuncs_Local : AssertionDscKeyFuncs + //{ + //public: + // static bool Equals(const AssertionDsc x, const AssertionDsc y) + // { + // return AssertionDsc::Equals(x, y, false); + // } + + // static unsigned GetHashCode(const AssertionDsc dsc) + // { + // /* + // * 0 ~ 2 : assertionKind + // * 3 ~ 6 : op1Kind + // * 7 ~ 11: op2Kind + // */ + // unsigned result = ((dsc.op2.kind << 7) | (dsc.op1.kind << 3) | (dsc.assertionKind)); + // return result; + // } + //}; + + //struct AssertionDscKeyFuncs_Global: AssertionDscKeyFuncs + //{ + //public: + // static bool Equals(const AssertionDsc x, const AssertionDsc y) + // { + // return AssertionDsc::Equals(x, y, true); + // } + + // static unsigned GetHashCode(const AssertionDsc dsc) + // { + // return dsc + // } + //}; + + //template + //class AssertionDscHashTable : public JitHashTable + //{ + //public: + // AssertionDscHashTable() : JitHashTable(getAllocator()) + // { + // } + //}; + + //class AssertionDscHashTable_Local : AssertionDscHashTable + //{ + //}; + + //class AssertionDscHashTable_Global : AssertionDscHashTable + //{ + //}; // Map from Block to Block. Used for a variety of purposes. //typedef JitHashTable, AssertionIndex> AssertionDscMap; @@ -7392,13 +7345,8 @@ class Compiler using AssertionDscMap_Global = JitHashTable, AssertionIndex>;*/ //typedef AssertionDscMap - //typedef JitHashTable AssertionDscMap; - - - //TODO: Use pointer - //AssertionDscMap optAssertionDscMap; - - AssertionDscHashTable<>* optAssertionDscMap; + typedef JitHashTable AssertionDscMap; + AssertionDscMap* optAssertionDscMap; public: void optVnNonNullPropCurStmt(BasicBlock* block, Statement* stmt, GenTree* tree); From c32940d0d4624705f74c6eb831ec8f2bc1f5d02f Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Thu, 21 Jul 2022 16:05:38 -0700 Subject: [PATCH 07/29] working model --- src/coreclr/jit/assertionprop.cpp | 6 ++-- src/coreclr/jit/compiler.h | 57 ++++++++++++++++++------------- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 7711887eb834c6..47a98f2c8c458d 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -944,7 +944,8 @@ void Compiler::optAssertionTraitsInit(AssertionIndex assertionCount) * Initialize the assertion prop tracking logic. */ -bool Compiler::AssertionDscKeyFuncs::isLocalProp = false; +bool Compiler::AssertionDscKeyFuncs::vnBased = false; +Compiler::AssertionDscKeyFuncs::HashCodeFn Compiler::AssertionDscKeyFuncs::assertionHashCodeFn = &Compiler::AssertionDscKeyFuncs::GetHashCodeLocal; void Compiler::optAssertionInit(bool isLocalProp) { @@ -959,9 +960,8 @@ void Compiler::optAssertionInit(bool isLocalProp) static const unsigned upperBound = ArrLen(countFunc) - 1; const unsigned codeSize = info.compILCodeSize / 512; optMaxAssertionCount = countFunc[isLocalProp ? lowerBound : min(upperBound, codeSize)]; - AssertionDscKeyFuncs::isLocalProp = isLocalProp; - AssertionDscKeyFuncs::hashCodeFn = &AssertionDscKeyFuncs::GetHashCodeGlobal; + AssertionDscKeyFuncs::InitAssertionDscKey(isLocalProp); optLocalAssertionProp = isLocalProp; optAssertionTabPrivate = new (this, CMK_AssertionProp) AssertionDsc[optMaxAssertionCount]; diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index c9b6cfaa77eb64..3d78f06ea6c4a1 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7126,17 +7126,6 @@ class Compiler } bool HasSameOp1(AssertionDsc* that, bool vnBased) - - unsigned GetHashCode() - { - /* - * 0 ~ 2 : assertionKind - * 3 ~ 6 : op1Kind - * 7 ~ 11: op2Kind - */ - unsigned result = ((op2.kind << 7) | (op1.kind << 3) | (assertionKind)); - return result; - } { if (op1.kind != that->op1.kind) { @@ -7254,34 +7243,56 @@ class Compiler //template struct AssertionDscKeyFuncs { - public: - static bool isLocalProp; - static unsigned (*hashCodeFn)(AssertionDsc); + typedef unsigned (*HashCodeFn)(AssertionDsc); + + static bool vnBased; + static HashCodeFn assertionHashCodeFn; + + static void InitAssertionDscKey(bool isLocalProp) + { + vnBased = !isLocalProp; + if (isLocalProp) + { + assertionHashCodeFn = &GetHashCodeLocal; + } + else + { + assertionHashCodeFn = &GetHashCodeGlobal; + } + } static bool Equals(AssertionDsc x, AssertionDsc y) { AssertionDsc* _x = &x; - return _x->Equals(&y); + AssertionDsc* _y = &y; + return _x->Equals(_y, vnBased); } static unsigned GetHashCode(AssertionDsc dsc) { - AssertionDsc* _dsc = &dsc; - return _dsc->GetHashCode(); + return assertionHashCodeFn(dsc); } - static unsigned GetHashCodeGlobal(AssertionDsc dsc) { - AssertionDsc* _dsc = &dsc; - return _dsc->GetHashCode(); + /* + * 0 ~ 2 : assertionKind + * 3 ~ 6 : op1Kind + * 7 ~ 11: op2Kind + */ + unsigned result = ((dsc.op2.kind << 7) | (dsc.op1.kind << 3) | (dsc.assertionKind)); + return result; } static unsigned GetHashCodeLocal(AssertionDsc dsc) { - return hashCodeFn(dsc); - /*AssertionDsc* _dsc = &dsc; - return _dsc->GetHashCode();*/ + /* + * 0 ~ 2 : assertionKind + * 3 ~ 6 : op1Kind + * 7 ~ 11: op2Kind + */ + unsigned result = ((dsc.op2.kind << 7) | (dsc.op1.kind << 3) | (dsc.assertionKind)); + return result; } }; From e8cd8730107a205e7925b2ebb4b30e58a16d351f Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Thu, 21 Jul 2022 23:47:43 -0700 Subject: [PATCH 08/29] better hash code function --- src/coreclr/jit/assertionprop.cpp | 15 ++-- src/coreclr/jit/compiler.h | 119 ++++++++++++++++++++++-------- src/coreclr/jit/compiler.hpp | 32 ++------ 3 files changed, 100 insertions(+), 66 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 47a98f2c8c458d..f2e46ddd529c8a 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -2018,8 +2018,12 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) } else { + if (found) + { + printf("%u not found.\n", AssertionDscKeyFuncs/**/::GetHashCode(*newAssertion)); + assert(false); + } //printf("%u not found\n", AssertionDscKeyFuncs::GetHashCode(*newAssertion)); - assert(!found); } #endif // DEBUG @@ -2032,14 +2036,7 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) #ifdef DEBUG optAssertionDscMap->Set(*newAssertion, optAssertionCount + 1); #endif - if (optLocalAssertionProp) - { - printf("++ Added map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs/**/::GetHashCode(*newAssertion)); - } - else - { - printf("++ Added map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs/**/::GetHashCode(*newAssertion)); - } + printf("++ Added map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs/**/::GetHashCode(*newAssertion)); optAssertionTabPrivate[optAssertionCount] = *newAssertion; optAssertionCount++; diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 3d78f06ea6c4a1..570ecd9287255e 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7209,15 +7209,80 @@ class Compiler } public: - unsigned GetHashCode() + unsigned GetHashCode(bool vnBased) { - /* - * 0 ~ 2 : assertionKind - * 3 ~ 6 : op1Kind - * 7 ~ 11: op2Kind - */ - unsigned result = ((op2.kind << 7) | (op1.kind << 3) | (assertionKind)); - return result; + assert(assertionKind != OAK_INVALID); + unsigned op2Valid = op2.kind ^ O2K_INVALID; + unsigned op1Valid = op1.kind ^ O1K_INVALID; + unsigned hashCode = 0; + + if (vnBased) + { + if (op2Valid) + { + /* op2.lcl's lclNum combined 9-bits will take care of 9-bits of other members + of union like u1.iconVal, lconVal, dconVal. + */ + hashCode |= + ((op2.lcl.lclNum & 0x1FF) << 23) | /* 31 ~ 23 : op2.lcl.lclNum (low 9-bits) */ + (op2.kind << 18); /* 22 ~ 18 : op2Kind (5-bits) */ + } + + if (op1.kind == O1K_ARR_BND) + { + hashCode |= + ((op1.lcl.lclNum & 0x7FF) << 7) | /* 17 ~ 07 : op1.lcl.lclNum (low 11-bits) */ + (op1.kind << 3); /* 06 ~ 03 : op1Kind (4-bits) */ + } + else if (op1Valid) + { + hashCode |= + ((op1.vn & 0x7FF) << 7) | /* 17 ~ 07 : op1.vn (low 11-bits) */ + (op1.kind << 3); /* 06 ~ 03 : op1Kind (4-bits) */ + } + + return hashCode | + (assertionKind); /* 02 ~ 00 : assertionKind (3-bits)*/ + + //return ( + // ((op2.lcl.lclNum & 0x1FF) << 23) | /* 31 ~ 23 : op2.lcl.lclNum (low 9-bits) */ + // (op2.kind << 18) | /* 22 ~ 18 : op2Kind (5-bits) */ + // ((op1.vn & 0x7FF) << 7) | /* 17 ~ 07 : op1.vn (low 11-bits) */ + // (op1.kind << 3) | /* 06 ~ 03 : op1Kind (4-bits) */ + // (assertionKind)); /* 02 ~ 00 : assertionKind (3-bits)*/ + //return GetHashCodeGlobal(&dsc); + } + else + { + if (op2Valid) + { + /* op2.lcl's lclNum combined 15-bits will take care of 15-bits of other members + of union like u1.iconVal, lconVal, dconVal. + */ + hashCode |= + ((op2.lcl.lclNum & 0x7FFF) << 17) | /* 31 ~ 17 : op2.lcl.lclNum (low 15-bits) */ + (op2.kind << 12); /* 16 ~ 12 : op2Kind (5-bits) */ + } + + if (op1Valid) + { + hashCode |= + ((op1.lcl.lclNum & 0x1F) << 7) | /* 11 ~ 07 : op1.lcl.lclNum (low 5-bits) */ + (op1.kind << 3); /* 06 ~ 03 : op1Kind (4-bits) */ + } + + return hashCode | + (assertionKind); /* 02 ~ 00 : assertionKind (3-bits)*/ + + //return ( + // ((op2.lcl.lclNum & 0x7FFF) << 17) | /* 31 ~ 17 : op2.lcl.lclNum (low 15-bits) */ + // (op2.kind << 12) | /* 16 ~ 12 : op2Kind (5-bits) */ + // ((op1.lcl.lclNum & 0x1F) << 7) | /* 11 ~ 07 : op1.lcl.lclNum (low 5-bits) */ + // (op1.kind << 3) | /* 06 ~ 03 : op1Kind (4-bits) */ + // (assertionKind)); /* 02 ~ 00 : assertionKind (3-bits) */ + //return GetHashCodeLocal(&dsc); + } + //return assertionHashCodeFn(dsc); } }; @@ -7240,10 +7305,9 @@ class Compiler AssertionIndex optAssertionCount; // total number of assertions in the assertion table AssertionIndex optMaxAssertionCount; - //template struct AssertionDscKeyFuncs { - typedef unsigned (*HashCodeFn)(AssertionDsc); + typedef unsigned (*HashCodeFn)(AssertionDsc*); static bool vnBased; static HashCodeFn assertionHashCodeFn; @@ -7263,36 +7327,31 @@ class Compiler static bool Equals(AssertionDsc x, AssertionDsc y) { - AssertionDsc* _x = &x; - AssertionDsc* _y = &y; - return _x->Equals(_y, vnBased); + return (&x)->Equals(&y, vnBased); } static unsigned GetHashCode(AssertionDsc dsc) { - return assertionHashCodeFn(dsc); + return dsc.GetHashCode(vnBased); + //if (vnBased) + //{ + // //return GetHashCodeGlobal(&dsc); + //} + //else + //{ + // //return GetHashCodeLocal(&dsc); + //} + ////return assertionHashCodeFn(dsc); } - static unsigned GetHashCodeGlobal(AssertionDsc dsc) + static unsigned GetHashCodeGlobal(AssertionDsc* dsc) { - /* - * 0 ~ 2 : assertionKind - * 3 ~ 6 : op1Kind - * 7 ~ 11: op2Kind - */ - unsigned result = ((dsc.op2.kind << 7) | (dsc.op1.kind << 3) | (dsc.assertionKind)); - return result; + return 0; } - static unsigned GetHashCodeLocal(AssertionDsc dsc) + static unsigned GetHashCodeLocal(AssertionDsc* dsc) { - /* - * 0 ~ 2 : assertionKind - * 3 ~ 6 : op1Kind - * 7 ~ 11: op2Kind - */ - unsigned result = ((dsc.op2.kind << 7) | (dsc.op1.kind << 3) | (dsc.assertionKind)); - return result; + return 0; } }; diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index 41ac4f83578acd..cf88e72bf725e9 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -3259,14 +3259,8 @@ inline void Compiler::optAssertionReset(AssertionIndex limit) #endif optAssertionCount--; - if (optLocalAssertionProp) - { - printf("-- Removed map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs::GetHashCode(*curAssertion)); - } - else - { - printf("-- Removed map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs::GetHashCode(*curAssertion)); - } + printf("-- Removed map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs::GetHashCode(*curAssertion)); + unsigned lclNum = curAssertion->op1.lcl.lclNum; assert(lclNum < lvaCount); BitVecOps::RemoveElemD(apTraits, GetAssertionDep(lclNum), index - 1); @@ -3292,16 +3286,8 @@ inline void Compiler::optAssertionReset(AssertionIndex limit) #ifdef DEBUG optAssertionDscMap->Set(*curAssertion, optAssertionCount); #endif - if (optLocalAssertionProp) - { - printf("++ Added map[%d] = %u\n", optAssertionCount - 1, - AssertionDscKeyFuncs/**/::GetHashCode(*curAssertion)); - } - else - { - printf("++ Added map[%d] = %u\n", optAssertionCount - 1, - AssertionDscKeyFuncs/**/::GetHashCode(*curAssertion)); - } + printf("++ Added map[%d] = %u\n", optAssertionCount - 1, + AssertionDscKeyFuncs /**/ ::GetHashCode(*curAssertion)); unsigned lclNum = curAssertion->op1.lcl.lclNum; BitVecOps::AddElemD(apTraits, GetAssertionDep(lclNum), index - 1); @@ -3366,16 +3352,8 @@ inline void Compiler::optAssertionRemove(AssertionIndex index) optAssertionDscMap->Remove(*curAssertion); #endif optAssertionCount--; - if (optLocalAssertionProp) - { - printf("-- Removed map[%d] = %u\n", optAssertionCount, + printf("-- Removed map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs/**/::GetHashCode(*curAssertion)); - } - else - { - printf("-- Removed map[%d] = %u\n", optAssertionCount, - AssertionDscKeyFuncs/**/::GetHashCode(*curAssertion)); - } } else { From 31f62d5d35da09376ad27352cfbbcc28ee23b51a Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Fri, 22 Jul 2022 09:06:53 -0700 Subject: [PATCH 09/29] working better SkipIfExist --- src/coreclr/jit/assertionprop.cpp | 55 ++++++++++++++++++++++++++----- src/coreclr/jit/jithashtable.h | 28 +++++++++++++--- 2 files changed, 70 insertions(+), 13 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index f2e46ddd529c8a..cee1a3af951696 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -949,7 +949,7 @@ Compiler::AssertionDscKeyFuncs::HashCodeFn Compiler::AssertionDscKeyFuncs::asser void Compiler::optAssertionInit(bool isLocalProp) { - printf("optAssertionInit= %d\n", isLocalProp); + printf("*** vnBased= %d\n", !isLocalProp); // Use a function countFunc to determine a proper maximum assertion count for the // method being compiled. The function is linear to the IL size for small and // moderate methods. For large methods, considering throughput impact, we track no @@ -2011,7 +2011,32 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) } #ifdef DEBUG - if (optAssertionDscMap->Lookup(*newAssertion, &fastAnswer)) + + // Check if we are within max count. + if (optAssertionCount >= optMaxAssertionCount) + { + // If we don't want to add more assertions, just see if `newAssertion` already + // exists, and return the corresponding assertionIndex. + if (optAssertionDscMap->Lookup(*newAssertion, &fastAnswer)) + { + assert(slowAnswer == fastAnswer); + return slowAnswer; + } + else + { + if (found) + { + printf("HashCode= %u not found in map.\n", AssertionDscKeyFuncs/**/::GetHashCode(*newAssertion)); + assert(false); + } + return NO_ASSERTION_INDEX; + } + } + + // Check if newAssertion already exists and return the corresponding assertionIndex + // Otherwise, set it in the map. + if (optAssertionDscMap->Set(*newAssertion, optAssertionCount + 1, AssertionDscMap::SetKind::SkipIfExist, + &fastAnswer)) { assert(slowAnswer == fastAnswer); return slowAnswer; @@ -2020,22 +2045,36 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) { if (found) { - printf("%u not found.\n", AssertionDscKeyFuncs/**/::GetHashCode(*newAssertion)); + printf("HashCode=%u not found in map and we added it.\n", AssertionDscKeyFuncs/**/::GetHashCode(*newAssertion)); assert(false); } - //printf("%u not found\n", AssertionDscKeyFuncs::GetHashCode(*newAssertion)); } -#endif // DEBUG + //if (optAssertionDscMap->Lookup(*newAssertion, &fastAnswer)) + //{ + // assert(slowAnswer == fastAnswer); + // return slowAnswer; + //} + //else + //{ + // if (found) + // { + // printf("%u not found.\n", AssertionDscKeyFuncs/**/::GetHashCode(*newAssertion)); + // assert(false); + // } + // //printf("%u not found\n", AssertionDscKeyFuncs::GetHashCode(*newAssertion)); + //} +#else // Check if we are within max count. if (optAssertionCount >= optMaxAssertionCount) { return NO_ASSERTION_INDEX; } +#endif // DEBUG -#ifdef DEBUG - optAssertionDscMap->Set(*newAssertion, optAssertionCount + 1); -#endif +//#ifdef DEBUG +// optAssertionDscMap->Set(*newAssertion, optAssertionCount + 1); +//#endif printf("++ Added map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs/**/::GetHashCode(*newAssertion)); optAssertionTabPrivate[optAssertionCount] = *newAssertion; optAssertionCount++; diff --git a/src/coreclr/jit/jithashtable.h b/src/coreclr/jit/jithashtable.h index 85186dfb508e66..1999595c12dc71 100644 --- a/src/coreclr/jit/jithashtable.h +++ b/src/coreclr/jit/jithashtable.h @@ -204,10 +204,13 @@ class JitHashTable // v - the value // kind - Normal, we are not allowed to overwrite // Overwrite, we are allowed to overwrite + // SkipIfExist, skip if value exists. // currently only used by CHK/DBG builds in an assert. + // pVal - If SkipIfExist is passed, returns the value that + // was already present in the table. Otherwise, unchanged. // // Return Value: - // `true` if the key exists and was overwritten, + // `true` if the key exists and was overwritten/skipped. // `false` otherwise. // // Notes: @@ -217,10 +220,14 @@ class JitHashTable enum SetKind { None, - Overwrite + Overwrite, + + //Skip setting if it exists. Useful to find node just once instead of + //Lookup() and Set + SkipIfExist }; - bool Set(Key k, Value v, SetKind kind = None) + bool Set(Key k, Value v, SetKind kind = None, Value *pVal = nullptr) { CheckGrowth(); @@ -235,8 +242,19 @@ class JitHashTable } if (pN != nullptr) { - assert(kind == Overwrite); - pN->m_val = v; + if (kind == SkipIfExist) + { + assert(KeyFuncs::Equals(k, pN->m_key)); + if (pVal != nullptr) + { + *pVal = pN->m_val; + } + } + else + { + assert(kind == Overwrite); + pN->m_val = v; + } return true; } else From a4a2f31ae8a1e0256f315450806c569f12aa4961 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Fri, 22 Jul 2022 14:26:31 -0700 Subject: [PATCH 10/29] Add vnBased in AssertionDsc --- src/coreclr/jit/assertionprop.cpp | 31 +++++++++---------- src/coreclr/jit/compiler.h | 49 +++++++++++++------------------ 2 files changed, 34 insertions(+), 46 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index cee1a3af951696..19fd529cfb7484 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -944,8 +944,6 @@ void Compiler::optAssertionTraitsInit(AssertionIndex assertionCount) * Initialize the assertion prop tracking logic. */ -bool Compiler::AssertionDscKeyFuncs::vnBased = false; -Compiler::AssertionDscKeyFuncs::HashCodeFn Compiler::AssertionDscKeyFuncs::assertionHashCodeFn = &Compiler::AssertionDscKeyFuncs::GetHashCodeLocal; void Compiler::optAssertionInit(bool isLocalProp) { @@ -961,10 +959,15 @@ void Compiler::optAssertionInit(bool isLocalProp) const unsigned codeSize = info.compILCodeSize / 512; optMaxAssertionCount = countFunc[isLocalProp ? lowerBound : min(upperBound, codeSize)]; - AssertionDscKeyFuncs::InitAssertionDscKey(isLocalProp); - optLocalAssertionProp = isLocalProp; optAssertionTabPrivate = new (this, CMK_AssertionProp) AssertionDsc[optMaxAssertionCount]; + + for (int i = 0; i < optMaxAssertionCount; i++) + { + optAssertionTabPrivate[i].vnBased = !isLocalProp; + } + + //memset(optAssertionTabPrivate, 0, optMaxAssertionCount * (sizeof())) optComplementaryAssertionMap = new (this, CMK_AssertionProp) AssertionIndex[optMaxAssertionCount + 1](); // zero-inited (NO_ASSERTION_INDEX) @@ -1358,7 +1361,7 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, assert(op1 != nullptr); assert(!helperCallArgs || (op2 != nullptr)); - AssertionDsc assertion = {OAK_INVALID}; + AssertionDsc assertion(optLocalAssertionProp); assert(assertion.assertionKind == OAK_INVALID); if (op1->OperIs(GT_BOUNDS_CHECK)) @@ -1998,7 +2001,7 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) for (AssertionIndex index = optAssertionCount; index >= 1; index--) { AssertionDsc* curAssertion = optGetAssertion(index); - if (curAssertion->Equals(newAssertion, !optLocalAssertionProp)) + if (curAssertion->Equals(newAssertion)) { #ifdef DEBUG found = true; @@ -2314,7 +2317,8 @@ AssertionIndex Compiler::optAssertionGenCast(GenTreeCast* cast) return NO_ASSERTION_INDEX; } - AssertionDsc assertion = {OAK_SUBRANGE}; + AssertionDsc assertion(optLocalAssertionProp); + assertion.assertionKind = OAK_SUBRANGE; assertion.op1.kind = O1K_LCLVAR; assertion.op1.vn = vnStore->VNConservativeNormalValue(lclVar->gtVNPair); assertion.op1.lcl.lclNum = lclVar->GetLclNum(); @@ -2374,6 +2378,7 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) ValueNum op1VN = vnStore->VNConservativeNormalValue(op1->gtVNPair); ValueNum op2VN = vnStore->VNConservativeNormalValue(op2->gtVNPair); ValueNum relopVN = vnStore->VNConservativeNormalValue(relop->gtVNPair); + AssertionDsc dsc(optLocalAssertionProp); bool hasTestAgainstZero = (relop->gtOper == GT_EQ || relop->gtOper == GT_NE) && (op2VN == vnStore->VNZeroForType(op2->TypeGet())); @@ -2384,7 +2389,6 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) // Assertion: "i < bnd +/- k == 0" if (hasTestAgainstZero && vnStore->IsVNCompareCheckedBoundArith(op1VN)) { - AssertionDsc dsc; dsc.assertionKind = relop->gtOper == GT_EQ ? OAK_EQUAL : OAK_NOT_EQUAL; dsc.op1.kind = O1K_BOUND_OPER_BND; dsc.op1.vn = op1VN; @@ -2401,7 +2405,6 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) // Assertion: "i < bnd +/- k != 0" else if (vnStore->IsVNCompareCheckedBoundArith(relopVN)) { - AssertionDsc dsc; dsc.assertionKind = OAK_NOT_EQUAL; dsc.op1.kind = O1K_BOUND_OPER_BND; dsc.op1.vn = relopVN; @@ -2418,7 +2421,6 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) // Assertion: "i < bnd == false" else if (hasTestAgainstZero && vnStore->IsVNCompareCheckedBound(op1VN)) { - AssertionDsc dsc; dsc.assertionKind = relop->gtOper == GT_EQ ? OAK_EQUAL : OAK_NOT_EQUAL; dsc.op1.kind = O1K_BOUND_LOOP_BND; dsc.op1.vn = op1VN; @@ -2435,7 +2437,6 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) // Assertion: "i < bnd != 0" else if (vnStore->IsVNCompareCheckedBound(relopVN)) { - AssertionDsc dsc; dsc.assertionKind = OAK_NOT_EQUAL; dsc.op1.kind = O1K_BOUND_LOOP_BND; dsc.op1.vn = relopVN; @@ -2455,7 +2456,6 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) assert((unsignedCompareBnd.cmpOper == VNF_LT_UN) || (unsignedCompareBnd.cmpOper == VNF_GE_UN)); assert(vnStore->IsVNCheckedBound(unsignedCompareBnd.vnBound)); - AssertionDsc dsc; dsc.assertionKind = OAK_NO_THROW; dsc.op1.kind = O1K_ARR_BND; dsc.op1.vn = relopVN; @@ -2478,7 +2478,6 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) // Assertion: "i < 100 == false" else if (hasTestAgainstZero && vnStore->IsVNConstantBound(op1VN)) { - AssertionDsc dsc; dsc.assertionKind = relop->gtOper == GT_EQ ? OAK_EQUAL : OAK_NOT_EQUAL; dsc.op1.kind = O1K_CONSTANT_LOOP_BND; dsc.op1.vn = op1VN; @@ -2495,7 +2494,6 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) // Assertion: "i < 100 != 0" else if (vnStore->IsVNConstantBound(relopVN)) { - AssertionDsc dsc; dsc.assertionKind = OAK_NOT_EQUAL; dsc.op1.kind = O1K_CONSTANT_LOOP_BND; dsc.op1.vn = relopVN; @@ -2509,7 +2507,6 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) } else if (vnStore->IsVNConstantBoundUnsigned(relopVN)) { - AssertionDsc dsc; dsc.assertionKind = OAK_NOT_EQUAL; dsc.op1.kind = O1K_CONSTANT_LOOP_BND_UN; dsc.op1.vn = relopVN; @@ -2591,7 +2588,7 @@ AssertionInfo Compiler::optAssertionGenJtrue(GenTree* tree) int con = vnStore->ConstantValue(op2VN); if (con >= 0) { - AssertionDsc dsc; + AssertionDsc dsc(optLocalAssertionProp); // For arr.Length != 0, we know that 0 is a valid index // For arr.Length == con, we know that con - 1 is the greatest valid index @@ -2893,7 +2890,7 @@ AssertionIndex Compiler::optFindComplementary(AssertionIndex assertIndex) { // Make sure assertion kinds are complementary and op1, op2 kinds match. AssertionDsc* curAssertion = optGetAssertion(index); - if (curAssertion->Complementary(inputAssertion, !optLocalAssertionProp)) + if (curAssertion->Complementary(inputAssertion)) { optMapComplementary(assertIndex, index); return index; diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 570ecd9287255e..e5941a49624c45 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7072,6 +7072,7 @@ class Compiler IntegralRange u2; }; } op2; + bool vnBased : 1; bool IsCheckedBoundArithBound() { @@ -7125,7 +7126,7 @@ class Compiler return false; } - bool HasSameOp1(AssertionDsc* that, bool vnBased) + bool HasSameOp1(AssertionDsc* that) { if (op1.kind != that->op1.kind) { @@ -7143,7 +7144,7 @@ class Compiler } } - bool HasSameOp2(AssertionDsc* that, bool vnBased) + bool HasSameOp2(AssertionDsc* that) { if (op2.kind != that->op2.kind) { @@ -7185,13 +7186,13 @@ class Compiler return false; } - bool Complementary(AssertionDsc* that, bool vnBased) + bool Complementary(AssertionDsc* that) { - return ComplementaryKind(assertionKind, that->assertionKind) && HasSameOp1(that, vnBased) && - HasSameOp2(that, vnBased); + return ComplementaryKind(assertionKind, that->assertionKind) && HasSameOp1(that) && + HasSameOp2(that); } - bool Equals(AssertionDsc* that, bool vnBased) + bool Equals(AssertionDsc* that) { if (assertionKind != that->assertionKind) { @@ -7200,16 +7201,16 @@ class Compiler else if (assertionKind == OAK_NO_THROW) { assert(op2.kind == O2K_INVALID); - return HasSameOp1(that, vnBased); + return HasSameOp1(that); } else { - return HasSameOp1(that, vnBased) && HasSameOp2(that, vnBased); + return HasSameOp1(that) && HasSameOp2(that); } } public: - unsigned GetHashCode(bool vnBased) + unsigned GetHashCode() { assert(assertionKind != OAK_INVALID); unsigned op2Valid = op2.kind ^ O2K_INVALID; @@ -7284,6 +7285,14 @@ class Compiler } //return assertionHashCodeFn(dsc); } + + AssertionDsc(bool isLocalProp = false) + { + assertionKind = OAK_INVALID; + op1 = AssertionDscOp1(); + op2 = AssertionDscOp2(); + vnBased = !isLocalProp; + } }; protected: @@ -7307,32 +7316,14 @@ class Compiler struct AssertionDscKeyFuncs { - typedef unsigned (*HashCodeFn)(AssertionDsc*); - - static bool vnBased; - static HashCodeFn assertionHashCodeFn; - - static void InitAssertionDscKey(bool isLocalProp) - { - vnBased = !isLocalProp; - if (isLocalProp) - { - assertionHashCodeFn = &GetHashCodeLocal; - } - else - { - assertionHashCodeFn = &GetHashCodeGlobal; - } - } - static bool Equals(AssertionDsc x, AssertionDsc y) { - return (&x)->Equals(&y, vnBased); + return (&x)->Equals(&y); } static unsigned GetHashCode(AssertionDsc dsc) { - return dsc.GetHashCode(vnBased); + return dsc.GetHashCode(); //if (vnBased) //{ // //return GetHashCodeGlobal(&dsc); From 27004afa78a479705d7ab2deb4e78b884485f55e Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Fri, 22 Jul 2022 14:28:33 -0700 Subject: [PATCH 11/29] Remove comments --- src/coreclr/jit/assertionprop.cpp | 38 ++---------- src/coreclr/jit/compiler.h | 96 ------------------------------- src/coreclr/jit/compiler.hpp | 6 +- 3 files changed, 7 insertions(+), 133 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 19fd529cfb7484..54e4728977f0ac 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -947,7 +947,6 @@ void Compiler::optAssertionTraitsInit(AssertionIndex assertionCount) void Compiler::optAssertionInit(bool isLocalProp) { - printf("*** vnBased= %d\n", !isLocalProp); // Use a function countFunc to determine a proper maximum assertion count for the // method being compiled. The function is linear to the IL size for small and // moderate methods. For large methods, considering throughput impact, we track no @@ -967,23 +966,11 @@ void Compiler::optAssertionInit(bool isLocalProp) optAssertionTabPrivate[i].vnBased = !isLocalProp; } - //memset(optAssertionTabPrivate, 0, optMaxAssertionCount * (sizeof())) optComplementaryAssertionMap = new (this, CMK_AssertionProp) AssertionIndex[optMaxAssertionCount + 1](); // zero-inited (NO_ASSERTION_INDEX) optAssertionDscMap = new (getAllocator()) AssertionDscMap(getAllocator()); -//#ifdef DEBUG -// if (isLocalProp) -// { -// optAssertionDscMap = new (getAllocator()) AssertionDscMap(); -// } -// else -// { -// optAssertionDscMap = new (getAllocator()) AssertionDscHashTable_Global(); -// } -//#endif - assert(NO_ASSERTION_INDEX == 0); if (!isLocalProp) @@ -2029,7 +2016,7 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) { if (found) { - printf("HashCode= %u not found in map.\n", AssertionDscKeyFuncs/**/::GetHashCode(*newAssertion)); + JITDUMP("HashCode= %u not found in map.\n", AssertionDscKeyFuncs/**/::GetHashCode(*newAssertion)); assert(false); } return NO_ASSERTION_INDEX; @@ -2048,25 +2035,11 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) { if (found) { - printf("HashCode=%u not found in map and we added it.\n", AssertionDscKeyFuncs/**/::GetHashCode(*newAssertion)); + JITDUMP("HashCode=%u not found in map and we added it.\n", + AssertionDscKeyFuncs /**/ ::GetHashCode(*newAssertion)); assert(false); } } - - //if (optAssertionDscMap->Lookup(*newAssertion, &fastAnswer)) - //{ - // assert(slowAnswer == fastAnswer); - // return slowAnswer; - //} - //else - //{ - // if (found) - // { - // printf("%u not found.\n", AssertionDscKeyFuncs/**/::GetHashCode(*newAssertion)); - // assert(false); - // } - // //printf("%u not found\n", AssertionDscKeyFuncs::GetHashCode(*newAssertion)); - //} #else // Check if we are within max count. if (optAssertionCount >= optMaxAssertionCount) @@ -2075,10 +2048,7 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) } #endif // DEBUG -//#ifdef DEBUG -// optAssertionDscMap->Set(*newAssertion, optAssertionCount + 1); -//#endif - printf("++ Added map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs/**/::GetHashCode(*newAssertion)); + JITDUMP("++ Added map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs /**/ ::GetHashCode(*newAssertion)); optAssertionTabPrivate[optAssertionCount] = *newAssertion; optAssertionCount++; diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index e5941a49624c45..8b957990d5f79a 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7244,14 +7244,6 @@ class Compiler return hashCode | (assertionKind); /* 02 ~ 00 : assertionKind (3-bits)*/ - - //return ( - // ((op2.lcl.lclNum & 0x1FF) << 23) | /* 31 ~ 23 : op2.lcl.lclNum (low 9-bits) */ - // (op2.kind << 18) | /* 22 ~ 18 : op2Kind (5-bits) */ - // ((op1.vn & 0x7FF) << 7) | /* 17 ~ 07 : op1.vn (low 11-bits) */ - // (op1.kind << 3) | /* 06 ~ 03 : op1Kind (4-bits) */ - // (assertionKind)); /* 02 ~ 00 : assertionKind (3-bits)*/ - //return GetHashCodeGlobal(&dsc); } else { @@ -7274,16 +7266,7 @@ class Compiler return hashCode | (assertionKind); /* 02 ~ 00 : assertionKind (3-bits)*/ - - //return ( - // ((op2.lcl.lclNum & 0x7FFF) << 17) | /* 31 ~ 17 : op2.lcl.lclNum (low 15-bits) */ - // (op2.kind << 12) | /* 16 ~ 12 : op2Kind (5-bits) */ - // ((op1.lcl.lclNum & 0x1F) << 7) | /* 11 ~ 07 : op1.lcl.lclNum (low 5-bits) */ - // (op1.kind << 3) | /* 06 ~ 03 : op1Kind (4-bits) */ - // (assertionKind)); /* 02 ~ 00 : assertionKind (3-bits) */ - //return GetHashCodeLocal(&dsc); } - //return assertionHashCodeFn(dsc); } AssertionDsc(bool isLocalProp = false) @@ -7324,88 +7307,9 @@ class Compiler static unsigned GetHashCode(AssertionDsc dsc) { return dsc.GetHashCode(); - //if (vnBased) - //{ - // //return GetHashCodeGlobal(&dsc); - //} - //else - //{ - // //return GetHashCodeLocal(&dsc); - //} - ////return assertionHashCodeFn(dsc); - } - - static unsigned GetHashCodeGlobal(AssertionDsc* dsc) - { - return 0; - } - - static unsigned GetHashCodeLocal(AssertionDsc* dsc) - { - return 0; } }; - //struct AssertionDscKeyFuncs_Local : AssertionDscKeyFuncs - //{ - //public: - // static bool Equals(const AssertionDsc x, const AssertionDsc y) - // { - // return AssertionDsc::Equals(x, y, false); - // } - - // static unsigned GetHashCode(const AssertionDsc dsc) - // { - // /* - // * 0 ~ 2 : assertionKind - // * 3 ~ 6 : op1Kind - // * 7 ~ 11: op2Kind - // */ - // unsigned result = ((dsc.op2.kind << 7) | (dsc.op1.kind << 3) | (dsc.assertionKind)); - // return result; - // } - //}; - - //struct AssertionDscKeyFuncs_Global: AssertionDscKeyFuncs - //{ - //public: - // static bool Equals(const AssertionDsc x, const AssertionDsc y) - // { - // return AssertionDsc::Equals(x, y, true); - // } - - // static unsigned GetHashCode(const AssertionDsc dsc) - // { - // return dsc - // } - //}; - - //template - //class AssertionDscHashTable : public JitHashTable - //{ - //public: - // AssertionDscHashTable() : JitHashTable(getAllocator()) - // { - // } - //}; - - //class AssertionDscHashTable_Local : AssertionDscHashTable - //{ - //}; - - //class AssertionDscHashTable_Global : AssertionDscHashTable - //{ - //}; - - // Map from Block to Block. Used for a variety of purposes. - //typedef JitHashTable, AssertionIndex> AssertionDscMap; - //typedef JitHashTable, AssertionIndex> AssertionDscMap; - - //template - /*using AssertionDscMap_Local = JitHashTable, AssertionIndex>; - using AssertionDscMap_Global = JitHashTable, AssertionIndex>;*/ - - //typedef AssertionDscMap typedef JitHashTable AssertionDscMap; AssertionDscMap* optAssertionDscMap; diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index cf88e72bf725e9..7a930cfc49ab49 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -3259,7 +3259,7 @@ inline void Compiler::optAssertionReset(AssertionIndex limit) #endif optAssertionCount--; - printf("-- Removed map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs::GetHashCode(*curAssertion)); + JITDUMP("-- Removed map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs::GetHashCode(*curAssertion)); unsigned lclNum = curAssertion->op1.lcl.lclNum; assert(lclNum < lvaCount); @@ -3286,7 +3286,7 @@ inline void Compiler::optAssertionReset(AssertionIndex limit) #ifdef DEBUG optAssertionDscMap->Set(*curAssertion, optAssertionCount); #endif - printf("++ Added map[%d] = %u\n", optAssertionCount - 1, + JITDUMP("++ Added map[%d] = %u\n", optAssertionCount - 1, AssertionDscKeyFuncs /**/ ::GetHashCode(*curAssertion)); unsigned lclNum = curAssertion->op1.lcl.lclNum; @@ -3352,7 +3352,7 @@ inline void Compiler::optAssertionRemove(AssertionIndex index) optAssertionDscMap->Remove(*curAssertion); #endif optAssertionCount--; - printf("-- Removed map[%d] = %u\n", optAssertionCount, + JITDUMP("-- Removed map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs/**/::GetHashCode(*curAssertion)); } else From 47e8066f950646d4bfb93bf0b4c473a588c7c1b9 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Fri, 22 Jul 2022 17:35:49 -0700 Subject: [PATCH 12/29] Enable hashtable --- src/coreclr/jit/assertionprop.cpp | 26 +++++++------------------- src/coreclr/jit/compiler.hpp | 16 +++++++++------- 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 54e4728977f0ac..a51ec616b0bc6e 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -1977,12 +1977,10 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) return NO_ASSERTION_INDEX; } - bool found = false; - #ifdef DEBUG + bool found = false; AssertionIndex slowAnswer = NO_ASSERTION_INDEX; AssertionIndex fastAnswer = NO_ASSERTION_INDEX; -#endif // Check if exists already, so we can skip adding new one. Search backwards. for (AssertionIndex index = optAssertionCount; index >= 1; index--) @@ -1990,17 +1988,12 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) AssertionDsc* curAssertion = optGetAssertion(index); if (curAssertion->Equals(newAssertion)) { -#ifdef DEBUG found = true; slowAnswer = index; break; -#else - return index; -#endif } } - -#ifdef DEBUG +#endif // Check if we are within max count. if (optAssertionCount >= optMaxAssertionCount) @@ -2010,7 +2003,7 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) if (optAssertionDscMap->Lookup(*newAssertion, &fastAnswer)) { assert(slowAnswer == fastAnswer); - return slowAnswer; + return fastAnswer; } else { @@ -2029,24 +2022,19 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) &fastAnswer)) { assert(slowAnswer == fastAnswer); - return slowAnswer; + return fastAnswer; } +#ifdef DEBUG else { if (found) { - JITDUMP("HashCode=%u not found in map and we added it.\n", + JITDUMP("HashCode=%u was not found in map and we added it.\n", AssertionDscKeyFuncs /**/ ::GetHashCode(*newAssertion)); assert(false); } } -#else - // Check if we are within max count. - if (optAssertionCount >= optMaxAssertionCount) - { - return NO_ASSERTION_INDEX; - } -#endif // DEBUG +#endif JITDUMP("++ Added map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs /**/ ::GetHashCode(*newAssertion)); optAssertionTabPrivate[optAssertionCount] = *newAssertion; diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index 7a930cfc49ab49..8105c27ac454b7 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -3249,14 +3249,20 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX inline void Compiler::optAssertionReset(AssertionIndex limit) { PREFAST_ASSUME(optAssertionCount <= optMaxAssertionCount); + if (limit == 0) + { + optAssertionDscMap->RemoveAll(); + } while (optAssertionCount > limit) { AssertionIndex index = optAssertionCount; AssertionDsc* curAssertion = optGetAssertion(index); -#ifdef DEBUG - optAssertionDscMap->Remove(*curAssertion); -#endif + + if (limit > 0) + { + optAssertionDscMap->Remove(*curAssertion); + } optAssertionCount--; JITDUMP("-- Removed map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs::GetHashCode(*curAssertion)); @@ -3283,9 +3289,7 @@ inline void Compiler::optAssertionReset(AssertionIndex limit) AssertionIndex index = ++optAssertionCount; AssertionDsc* curAssertion = optGetAssertion(index); -#ifdef DEBUG optAssertionDscMap->Set(*curAssertion, optAssertionCount); -#endif JITDUMP("++ Added map[%d] = %u\n", optAssertionCount - 1, AssertionDscKeyFuncs /**/ ::GetHashCode(*curAssertion)); @@ -3348,9 +3352,7 @@ inline void Compiler::optAssertionRemove(AssertionIndex index) BitVecOps::RemoveElemD(apTraits, GetAssertionDep(lclNum), index - 1); } -#ifdef DEBUG optAssertionDscMap->Remove(*curAssertion); -#endif optAssertionCount--; JITDUMP("-- Removed map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs/**/::GetHashCode(*curAssertion)); From 1e57b63c5ce8a241b0cac8a81e7c319bb4ef9160 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Fri, 22 Jul 2022 18:17:12 -0700 Subject: [PATCH 13/29] jit format --- src/coreclr/jit/assertionprop.cpp | 14 +++++------ src/coreclr/jit/compiler.h | 40 +++++++++++++------------------ src/coreclr/jit/compiler.hpp | 8 +++---- src/coreclr/jit/jithashtable.h | 6 ++--- 4 files changed, 30 insertions(+), 38 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index a51ec616b0bc6e..a970c3d83e7292 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -944,7 +944,6 @@ void Compiler::optAssertionTraitsInit(AssertionIndex assertionCount) * Initialize the assertion prop tracking logic. */ - void Compiler::optAssertionInit(bool isLocalProp) { // Use a function countFunc to determine a proper maximum assertion count for the @@ -958,7 +957,7 @@ void Compiler::optAssertionInit(bool isLocalProp) const unsigned codeSize = info.compILCodeSize / 512; optMaxAssertionCount = countFunc[isLocalProp ? lowerBound : min(upperBound, codeSize)]; - optLocalAssertionProp = isLocalProp; + optLocalAssertionProp = isLocalProp; optAssertionTabPrivate = new (this, CMK_AssertionProp) AssertionDsc[optMaxAssertionCount]; for (int i = 0; i < optMaxAssertionCount; i++) @@ -2009,7 +2008,8 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) { if (found) { - JITDUMP("HashCode= %u not found in map.\n", AssertionDscKeyFuncs/**/::GetHashCode(*newAssertion)); + JITDUMP("HashCode= %u not found in map.\n", + AssertionDscKeyFuncs /**/ ::GetHashCode(*newAssertion)); assert(false); } return NO_ASSERTION_INDEX; @@ -2019,7 +2019,7 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) // Check if newAssertion already exists and return the corresponding assertionIndex // Otherwise, set it in the map. if (optAssertionDscMap->Set(*newAssertion, optAssertionCount + 1, AssertionDscMap::SetKind::SkipIfExist, - &fastAnswer)) + &fastAnswer)) { assert(slowAnswer == fastAnswer); return fastAnswer; @@ -2333,9 +2333,9 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) GenTree* op1 = relop->gtGetOp1(); GenTree* op2 = relop->gtGetOp2(); - ValueNum op1VN = vnStore->VNConservativeNormalValue(op1->gtVNPair); - ValueNum op2VN = vnStore->VNConservativeNormalValue(op2->gtVNPair); - ValueNum relopVN = vnStore->VNConservativeNormalValue(relop->gtVNPair); + ValueNum op1VN = vnStore->VNConservativeNormalValue(op1->gtVNPair); + ValueNum op2VN = vnStore->VNConservativeNormalValue(op2->gtVNPair); + ValueNum relopVN = vnStore->VNConservativeNormalValue(relop->gtVNPair); AssertionDsc dsc(optLocalAssertionProp); bool hasTestAgainstZero = diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 8b957990d5f79a..2604376d58d0ae 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7188,8 +7188,7 @@ class Compiler bool Complementary(AssertionDsc* that) { - return ComplementaryKind(assertionKind, that->assertionKind) && HasSameOp1(that) && - HasSameOp2(that); + return ComplementaryKind(assertionKind, that->assertionKind) && HasSameOp1(that) && HasSameOp2(that); } bool Equals(AssertionDsc* that) @@ -7224,26 +7223,22 @@ class Compiler /* op2.lcl's lclNum combined 9-bits will take care of 9-bits of other members of union like u1.iconVal, lconVal, dconVal. */ - hashCode |= - ((op2.lcl.lclNum & 0x1FF) << 23) | /* 31 ~ 23 : op2.lcl.lclNum (low 9-bits) */ - (op2.kind << 18); /* 22 ~ 18 : op2Kind (5-bits) */ + hashCode |= ((op2.lcl.lclNum & 0x1FF) << 23) | /* 31 ~ 23 : op2.lcl.lclNum (low 9-bits) */ + (op2.kind << 18); /* 22 ~ 18 : op2Kind (5-bits) */ } if (op1.kind == O1K_ARR_BND) { - hashCode |= - ((op1.lcl.lclNum & 0x7FF) << 7) | /* 17 ~ 07 : op1.lcl.lclNum (low 11-bits) */ - (op1.kind << 3); /* 06 ~ 03 : op1Kind (4-bits) */ + hashCode |= ((op1.lcl.lclNum & 0x7FF) << 7) | /* 17 ~ 07 : op1.lcl.lclNum (low 11-bits) */ + (op1.kind << 3); /* 06 ~ 03 : op1Kind (4-bits) */ } else if (op1Valid) { - hashCode |= - ((op1.vn & 0x7FF) << 7) | /* 17 ~ 07 : op1.vn (low 11-bits) */ - (op1.kind << 3); /* 06 ~ 03 : op1Kind (4-bits) */ + hashCode |= ((op1.vn & 0x7FF) << 7) | /* 17 ~ 07 : op1.vn (low 11-bits) */ + (op1.kind << 3); /* 06 ~ 03 : op1Kind (4-bits) */ } - return hashCode | - (assertionKind); /* 02 ~ 00 : assertionKind (3-bits)*/ + return hashCode | (assertionKind); /* 02 ~ 00 : assertionKind (3-bits)*/ } else { @@ -7252,29 +7247,26 @@ class Compiler /* op2.lcl's lclNum combined 15-bits will take care of 15-bits of other members of union like u1.iconVal, lconVal, dconVal. */ - hashCode |= - ((op2.lcl.lclNum & 0x7FFF) << 17) | /* 31 ~ 17 : op2.lcl.lclNum (low 15-bits) */ - (op2.kind << 12); /* 16 ~ 12 : op2Kind (5-bits) */ + hashCode |= ((op2.lcl.lclNum & 0x7FFF) << 17) | /* 31 ~ 17 : op2.lcl.lclNum (low 15-bits) */ + (op2.kind << 12); /* 16 ~ 12 : op2Kind (5-bits) */ } if (op1Valid) { - hashCode |= - ((op1.lcl.lclNum & 0x1F) << 7) | /* 11 ~ 07 : op1.lcl.lclNum (low 5-bits) */ - (op1.kind << 3); /* 06 ~ 03 : op1Kind (4-bits) */ + hashCode |= ((op1.lcl.lclNum & 0x1F) << 7) | /* 11 ~ 07 : op1.lcl.lclNum (low 5-bits) */ + (op1.kind << 3); /* 06 ~ 03 : op1Kind (4-bits) */ } - return hashCode | - (assertionKind); /* 02 ~ 00 : assertionKind (3-bits)*/ + return hashCode | (assertionKind); /* 02 ~ 00 : assertionKind (3-bits)*/ } } AssertionDsc(bool isLocalProp = false) { assertionKind = OAK_INVALID; - op1 = AssertionDscOp1(); - op2 = AssertionDscOp2(); - vnBased = !isLocalProp; + op1 = AssertionDscOp1(); + op2 = AssertionDscOp2(); + vnBased = !isLocalProp; } }; diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index 8105c27ac454b7..f51505b5e97d0f 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -3263,7 +3263,7 @@ inline void Compiler::optAssertionReset(AssertionIndex limit) { optAssertionDscMap->Remove(*curAssertion); } - + optAssertionCount--; JITDUMP("-- Removed map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs::GetHashCode(*curAssertion)); @@ -3291,9 +3291,9 @@ inline void Compiler::optAssertionReset(AssertionIndex limit) optAssertionDscMap->Set(*curAssertion, optAssertionCount); JITDUMP("++ Added map[%d] = %u\n", optAssertionCount - 1, - AssertionDscKeyFuncs /**/ ::GetHashCode(*curAssertion)); + AssertionDscKeyFuncs /**/ ::GetHashCode(*curAssertion)); - unsigned lclNum = curAssertion->op1.lcl.lclNum; + unsigned lclNum = curAssertion->op1.lcl.lclNum; BitVecOps::AddElemD(apTraits, GetAssertionDep(lclNum), index - 1); // @@ -3355,7 +3355,7 @@ inline void Compiler::optAssertionRemove(AssertionIndex index) optAssertionDscMap->Remove(*curAssertion); optAssertionCount--; JITDUMP("-- Removed map[%d] = %u\n", optAssertionCount, - AssertionDscKeyFuncs/**/::GetHashCode(*curAssertion)); + AssertionDscKeyFuncs /**/ ::GetHashCode(*curAssertion)); } else { diff --git a/src/coreclr/jit/jithashtable.h b/src/coreclr/jit/jithashtable.h index 1999595c12dc71..6fa43510d0526e 100644 --- a/src/coreclr/jit/jithashtable.h +++ b/src/coreclr/jit/jithashtable.h @@ -222,12 +222,12 @@ class JitHashTable None, Overwrite, - //Skip setting if it exists. Useful to find node just once instead of - //Lookup() and Set + // Skip setting if it exists. Useful to find node just once instead of + // Lookup() and Set SkipIfExist }; - bool Set(Key k, Value v, SetKind kind = None, Value *pVal = nullptr) + bool Set(Key k, Value v, SetKind kind = None, Value* pVal = nullptr) { CheckGrowth(); From 958056c3b00ee07186cfc4ab3391e7ae5acbda59 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Sun, 24 Jul 2022 22:22:19 -0700 Subject: [PATCH 14/29] fix release build --- src/coreclr/jit/assertionprop.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index a970c3d83e7292..c64fe654b52b48 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -1976,10 +1976,10 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) return NO_ASSERTION_INDEX; } + AssertionIndex fastAnswer = NO_ASSERTION_INDEX; + AssertionIndex slowAnswer = NO_ASSERTION_INDEX; #ifdef DEBUG bool found = false; - AssertionIndex slowAnswer = NO_ASSERTION_INDEX; - AssertionIndex fastAnswer = NO_ASSERTION_INDEX; // Check if exists already, so we can skip adding new one. Search backwards. for (AssertionIndex index = optAssertionCount; index >= 1; index--) @@ -2006,12 +2006,14 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) } else { +#ifdef DEBUG if (found) { JITDUMP("HashCode= %u not found in map.\n", AssertionDscKeyFuncs /**/ ::GetHashCode(*newAssertion)); assert(false); } +#endif return NO_ASSERTION_INDEX; } } From 06cf68398603b59a8dbaeb3e4ed1cd345a993064 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Thu, 28 Jul 2022 16:31:24 -0700 Subject: [PATCH 15/29] Review comments --- src/coreclr/jit/assertionprop.cpp | 1 - src/coreclr/jit/compiler.h | 44 +++++++++++++++---------------- src/coreclr/jit/compiler.hpp | 5 ---- 3 files changed, 22 insertions(+), 28 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index c64fe654b52b48..502d8b979f2bb4 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -2038,7 +2038,6 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) } #endif - JITDUMP("++ Added map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs /**/ ::GetHashCode(*newAssertion)); optAssertionTabPrivate[optAssertionCount] = *newAssertion; optAssertionCount++; diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 2604376d58d0ae..3993989efed700 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7126,27 +7126,27 @@ class Compiler return false; } - bool HasSameOp1(AssertionDsc* that) + bool HasSameOp1(const AssertionDsc& that) const { - if (op1.kind != that->op1.kind) + if (op1.kind != that.op1.kind) { return false; } else if (op1.kind == O1K_ARR_BND) { assert(vnBased); - return (op1.bnd.vnIdx == that->op1.bnd.vnIdx) && (op1.bnd.vnLen == that->op1.bnd.vnLen); + return (op1.bnd.vnIdx == that.op1.bnd.vnIdx) && (op1.bnd.vnLen == that.op1.bnd.vnLen); } else { - return ((vnBased && (op1.vn == that->op1.vn)) || - (!vnBased && (op1.lcl.lclNum == that->op1.lcl.lclNum))); + return ((vnBased && (op1.vn == that.op1.vn)) || + (!vnBased && (op1.lcl.lclNum == that.op1.lcl.lclNum))); } } - bool HasSameOp2(AssertionDsc* that) + bool HasSameOp2(const AssertionDsc& that) const { - if (op2.kind != that->op2.kind) + if (op2.kind != that.op2.kind) { return false; } @@ -7155,24 +7155,24 @@ class Compiler { case O2K_IND_CNS_INT: case O2K_CONST_INT: - return ((op2.u1.iconVal == that->op2.u1.iconVal) && (op2.u1.iconFlags == that->op2.u1.iconFlags)); + return ((op2.u1.iconVal == that.op2.u1.iconVal) && (op2.u1.iconFlags == that.op2.u1.iconFlags)); case O2K_CONST_LONG: - return (op2.lconVal == that->op2.lconVal); + return (op2.lconVal == that.op2.lconVal); case O2K_CONST_DOUBLE: // exact match because of positive and negative zero. - return (memcmp(&op2.dconVal, &that->op2.dconVal, sizeof(double)) == 0); + return (memcmp(&op2.dconVal, &that.op2.dconVal, sizeof(double)) == 0); case O2K_ZEROOBJ: return true; case O2K_LCLVAR_COPY: - return (op2.lcl.lclNum == that->op2.lcl.lclNum) && - (!vnBased || (op2.lcl.ssaNum == that->op2.lcl.ssaNum)); + return (op2.lcl.lclNum == that.op2.lcl.lclNum) && + (!vnBased || (op2.lcl.ssaNum == that.op2.lcl.ssaNum)); case O2K_SUBRANGE: - return op2.u2.Equals(that->op2.u2); + return op2.u2.Equals(that.op2.u2); case O2K_INVALID: // we will return false @@ -7186,14 +7186,14 @@ class Compiler return false; } - bool Complementary(AssertionDsc* that) + bool Complementary(const AssertionDsc& that) { - return ComplementaryKind(assertionKind, that->assertionKind) && HasSameOp1(that) && HasSameOp2(that); + return ComplementaryKind(assertionKind, that.assertionKind) && HasSameOp1(that) && HasSameOp2(that); } - bool Equals(AssertionDsc* that) + bool Equals(const AssertionDsc& that) const { - if (assertionKind != that->assertionKind) + if (assertionKind != that.assertionKind) { return false; } @@ -7209,7 +7209,7 @@ class Compiler } public: - unsigned GetHashCode() + unsigned GetHashCode() const { assert(assertionKind != OAK_INVALID); unsigned op2Valid = op2.kind ^ O2K_INVALID; @@ -7291,18 +7291,18 @@ class Compiler struct AssertionDscKeyFuncs { - static bool Equals(AssertionDsc x, AssertionDsc y) + static bool Equals(const AssertionDsc& x, const AssertionDsc& y) { - return (&x)->Equals(&y); + return x.Equals(y); } - static unsigned GetHashCode(AssertionDsc dsc) + static unsigned GetHashCode(const AssertionDsc& dsc) { return dsc.GetHashCode(); } }; - typedef JitHashTable AssertionDscMap; + typedef JitHashTable AssertionDscMap; AssertionDscMap* optAssertionDscMap; public: diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index f51505b5e97d0f..04323d1cb6c65e 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -3265,7 +3265,6 @@ inline void Compiler::optAssertionReset(AssertionIndex limit) } optAssertionCount--; - JITDUMP("-- Removed map[%d] = %u\n", optAssertionCount, AssertionDscKeyFuncs::GetHashCode(*curAssertion)); unsigned lclNum = curAssertion->op1.lcl.lclNum; assert(lclNum < lvaCount); @@ -3290,8 +3289,6 @@ inline void Compiler::optAssertionReset(AssertionIndex limit) AssertionDsc* curAssertion = optGetAssertion(index); optAssertionDscMap->Set(*curAssertion, optAssertionCount); - JITDUMP("++ Added map[%d] = %u\n", optAssertionCount - 1, - AssertionDscKeyFuncs /**/ ::GetHashCode(*curAssertion)); unsigned lclNum = curAssertion->op1.lcl.lclNum; BitVecOps::AddElemD(apTraits, GetAssertionDep(lclNum), index - 1); @@ -3354,8 +3351,6 @@ inline void Compiler::optAssertionRemove(AssertionIndex index) optAssertionDscMap->Remove(*curAssertion); optAssertionCount--; - JITDUMP("-- Removed map[%d] = %u\n", optAssertionCount, - AssertionDscKeyFuncs /**/ ::GetHashCode(*curAssertion)); } else { From e3ec9a9d61070318ba7b865201731322438c1176 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Thu, 28 Jul 2022 16:41:49 -0700 Subject: [PATCH 16/29] jit format --- src/coreclr/jit/assertionprop.cpp | 2 +- src/coreclr/jit/compiler.h | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 502d8b979f2bb4..77cfb5301e18ae 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -1979,7 +1979,7 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) AssertionIndex fastAnswer = NO_ASSERTION_INDEX; AssertionIndex slowAnswer = NO_ASSERTION_INDEX; #ifdef DEBUG - bool found = false; + bool found = false; // Check if exists already, so we can skip adding new one. Search backwards. for (AssertionIndex index = optAssertionCount; index >= 1; index--) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 3993989efed700..1822c479e9bc64 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7139,8 +7139,7 @@ class Compiler } else { - return ((vnBased && (op1.vn == that.op1.vn)) || - (!vnBased && (op1.lcl.lclNum == that.op1.lcl.lclNum))); + return ((vnBased && (op1.vn == that.op1.vn)) || (!vnBased && (op1.lcl.lclNum == that.op1.lcl.lclNum))); } } From 868993dfa8a19ff2e09761e3390779c3229fad3d Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Thu, 28 Jul 2022 16:46:14 -0700 Subject: [PATCH 17/29] Minor comment removal --- src/coreclr/jit/assertionprop.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 77cfb5301e18ae..a66bfe2e048ef2 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -2009,8 +2009,7 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) #ifdef DEBUG if (found) { - JITDUMP("HashCode= %u not found in map.\n", - AssertionDscKeyFuncs /**/ ::GetHashCode(*newAssertion)); + JITDUMP("HashCode= %u not found in map.\n", AssertionDscKeyFuncs::GetHashCode(*newAssertion)); assert(false); } #endif @@ -2032,7 +2031,7 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) if (found) { JITDUMP("HashCode=%u was not found in map and we added it.\n", - AssertionDscKeyFuncs /**/ ::GetHashCode(*newAssertion)); + AssertionDscKeyFuncs::GetHashCode(*newAssertion)); assert(false); } } From e8ce68e07afe9df71412136fd639e6efe964c858 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Fri, 29 Jul 2022 11:34:42 -0700 Subject: [PATCH 18/29] Fix failures --- src/coreclr/jit/assertionprop.cpp | 2 +- src/coreclr/jit/compiler.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index a66bfe2e048ef2..831ecfa7601b1c 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -1985,7 +1985,7 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) for (AssertionIndex index = optAssertionCount; index >= 1; index--) { AssertionDsc* curAssertion = optGetAssertion(index); - if (curAssertion->Equals(newAssertion)) + if (curAssertion->Equals(*newAssertion)) { found = true; slowAnswer = index; diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 1822c479e9bc64..34b2debf155f80 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7301,7 +7301,7 @@ class Compiler } }; - typedef JitHashTable AssertionDscMap; + typedef JitHashTable AssertionDscMap; AssertionDscMap* optAssertionDscMap; public: From 597e9c3d70444084629b7afa048f2c568b51f983 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Fri, 29 Jul 2022 14:01:10 -0700 Subject: [PATCH 19/29] Reduce size of AssertionDsc --- src/coreclr/jit/compiler.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 34b2debf155f80..8f93ca473c8bb6 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -6992,7 +6992,7 @@ class Compiler BitVecTraits* apTraits; ASSERT_TP apFull; - enum optAssertionKind + enum optAssertionKind : unsigned short { OAK_INVALID, OAK_EQUAL, @@ -7033,6 +7033,7 @@ class Compiler struct AssertionDsc { optAssertionKind assertionKind; + bool vnBased; struct SsaVar { unsigned lclNum; // assigned to or property of this local var number @@ -7072,7 +7073,6 @@ class Compiler IntegralRange u2; }; } op2; - bool vnBased : 1; bool IsCheckedBoundArithBound() { From bb165aaa8930b59d6be367c67c5cd18903095b1a Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Fri, 29 Jul 2022 15:35:41 -0700 Subject: [PATCH 20/29] fix asmdiff regression --- src/coreclr/jit/assertionprop.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 831ecfa7601b1c..03b89f64964f5a 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -2848,7 +2848,7 @@ AssertionIndex Compiler::optFindComplementary(AssertionIndex assertIndex) { // Make sure assertion kinds are complementary and op1, op2 kinds match. AssertionDsc* curAssertion = optGetAssertion(index); - if (curAssertion->Complementary(inputAssertion)) + if (curAssertion->Complementary(*inputAssertion)) { optMapComplementary(assertIndex, index); return index; From a1822efe17ee916b6bb1100916105ba6c14d77ed Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Wed, 27 Jul 2022 13:38:10 -0700 Subject: [PATCH 21/29] Add instrumentation for assertions --- src/coreclr/jit/assertionprop.cpp | 14 +++- src/coreclr/jit/compiler.cpp | 132 +++++++++++++++++------------- src/coreclr/jit/compiler.h | 13 +++ 3 files changed, 100 insertions(+), 59 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 03b89f64964f5a..775155879e595a 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -1989,6 +1989,8 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) { found = true; slowAnswer = index; + addAssertionCount++; + addAssertionIter += (optAssertionCount - index + 1); break; } } @@ -2898,6 +2900,8 @@ AssertionIndex Compiler::optAssertionIsSubrange(GenTree* tree, IntegralRange ran if (range.Contains(curAssertion->op2.u2)) { + subRangeCount++; + subRangeIter += index; return index; } } @@ -2964,6 +2968,8 @@ AssertionIndex Compiler::optAssertionIsSubtype(GenTree* tree, GenTree* methodTab if (curAssertion->op2.u1.iconVal == methodTableVal) { + subTypeCount++; + subTypeIter += index; return index; } } @@ -3815,6 +3821,8 @@ AssertionIndex Compiler::optLocalAssertionIsEqualOrNotEqual( if (constantIsEqual || assertionIsEqual) { + equalOrNotEquaCount++; + equalOrNotEquaIter += index; return index; } } @@ -4613,6 +4621,8 @@ AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op, (curAssertion->op2.kind == O2K_CONST_INT) && // op2 (curAssertion->op1.lcl.lclNum == lclNum) && (curAssertion->op2.u1.iconVal == 0)) { + noNullCount++; + noNullIter += index; return index; } } @@ -5105,14 +5115,14 @@ void Compiler::optImpliedByTypeOfAssertions(ASSERT_TP& activeAssertions) // Search the assertion table for a non-null assertion on op1 that matches chkAssertion for (AssertionIndex impIndex = 1; impIndex <= optAssertionCount; impIndex++) { - AssertionDsc* impAssertion = optGetAssertion(impIndex); - // The impAssertion must be different from the chkAssertion if (impIndex == chkAssertionIndex) { continue; } + AssertionDsc* impAssertion = optGetAssertion(impIndex); + // impAssertion must be a Non Null assertion on lclNum if ((impAssertion->assertionKind != OAK_NOT_EQUAL) || ((impAssertion->op1.kind != O1K_LCLVAR) && (impAssertion->op1.kind != O1K_VALUE_NUMBER)) || diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 5745dc191f8f60..9e36faa5706a55 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -6448,6 +6448,17 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, compHasBackwardJump = false; compHasBackwardJumpInHandler = false; + addAssertionCount = 0; + addAssertionIter = 0; + subRangeCount = 0; + subRangeIter = 0; + subTypeCount = 0; + subTypeIter = 0; + equalOrNotEquaCount = 0; + equalOrNotEquaIter = 0; + noNullCount = 0; + noNullIter = 0; + #ifdef DEBUG compCurBB = nullptr; lvaTable = nullptr; @@ -8583,35 +8594,51 @@ void JitTimer::PrintCsvHeader() // Write the header if the file is empty if (ftell(s_csvFile) == 0) { - fprintf(s_csvFile, "\"Method Name\","); + //fprintf(s_csvFile, "\"Method Name\","); fprintf(s_csvFile, "\"Assembly or SPMI Index\","); fprintf(s_csvFile, "\"IL Bytes\","); fprintf(s_csvFile, "\"Basic Blocks\","); - fprintf(s_csvFile, "\"Min Opts\","); - fprintf(s_csvFile, "\"Loops\","); - fprintf(s_csvFile, "\"Loops Cloned\","); -#if FEATURE_LOOP_ALIGN -#ifdef DEBUG - fprintf(s_csvFile, "\"Alignment Candidates\","); - fprintf(s_csvFile, "\"Loops Aligned\","); -#endif // DEBUG -#endif // FEATURE_LOOP_ALIGN - for (int i = 0; i < PHASE_NUMBER_OF; i++) - { - fprintf(s_csvFile, "\"%s\",", PhaseNames[i]); - if ((JitConfig.JitMeasureIR() != 0) && PhaseReportsIRSize[i]) - { - fprintf(s_csvFile, "\"Node Count After %s\",", PhaseNames[i]); - } - } - - InlineStrategy::DumpCsvHeader(s_csvFile); - fprintf(s_csvFile, "\"Executable Code Bytes\","); - fprintf(s_csvFile, "\"GC Info Bytes\","); - fprintf(s_csvFile, "\"Total Bytes Allocated\","); - fprintf(s_csvFile, "\"Total Cycles\","); - fprintf(s_csvFile, "\"CPS\"\n"); +#define ASSERTION_TITLE(name) \ + fprintf(s_csvFile, "\"" ## name ## "Count\","); \ + fprintf(s_csvFile, "\"" ## name ## "Iter\","); \ + fprintf(s_csvFile, "\"" ## name ## "Ratio\","); + +ASSERTION_TITLE("AddAssertion") +ASSERTION_TITLE("SubType") +ASSERTION_TITLE("SubRange") +ASSERTION_TITLE("EqualOrNotEqual") +ASSERTION_TITLE("NoNull") + + fprintf(s_csvFile, "\n,"); + + + + // fprintf(s_csvFile, "\"Min Opts\","); +// fprintf(s_csvFile, "\"Loops\","); +// fprintf(s_csvFile, "\"Loops Cloned\","); +//#if FEATURE_LOOP_ALIGN +//#ifdef DEBUG +// fprintf(s_csvFile, "\"Alignment Candidates\","); +// fprintf(s_csvFile, "\"Loops Aligned\","); +//#endif // DEBUG +//#endif // FEATURE_LOOP_ALIGN +// for (int i = 0; i < PHASE_NUMBER_OF; i++) +// { +// fprintf(s_csvFile, "\"%s\",", PhaseNames[i]); +// if ((JitConfig.JitMeasureIR() != 0) && PhaseReportsIRSize[i]) +// { +// fprintf(s_csvFile, "\"Node Count After %s\",", PhaseNames[i]); +// } +// } +// +// InlineStrategy::DumpCsvHeader(s_csvFile); +// +// fprintf(s_csvFile, "\"Executable Code Bytes\","); +// fprintf(s_csvFile, "\"GC Info Bytes\","); +// fprintf(s_csvFile, "\"Total Bytes Allocated\","); +// fprintf(s_csvFile, "\"Total Cycles\","); +// fprintf(s_csvFile, "\"CPS\"\n"); fflush(s_csvFile); } @@ -8651,7 +8678,7 @@ void JitTimer::PrintCsvMethodStats(Compiler* comp) return; } - fprintf(s_csvFile, "\"%s\",", methName); + //fprintf(s_csvFile, "\"%s\",", methName); if (index != 0) { fprintf(s_csvFile, "%d,", index); @@ -8662,40 +8689,31 @@ void JitTimer::PrintCsvMethodStats(Compiler* comp) comp->info.compCompHnd->getModuleAssembly(comp->info.compCompHnd->getClassModule(comp->info.compClassHnd))); fprintf(s_csvFile, "\"%s\",", methodAssemblyName); } - fprintf(s_csvFile, "%u,", comp->info.compILCodeSize); - fprintf(s_csvFile, "%u,", comp->fgBBcount); - fprintf(s_csvFile, "%u,", comp->opts.MinOpts()); - fprintf(s_csvFile, "%u,", comp->optLoopCount); - fprintf(s_csvFile, "%u,", comp->optLoopsCloned); -#if FEATURE_LOOP_ALIGN -#ifdef DEBUG - fprintf(s_csvFile, "%u,", comp->loopAlignCandidates); - fprintf(s_csvFile, "%u,", comp->loopsAligned); -#endif // DEBUG -#endif // FEATURE_LOOP_ALIGN - unsigned __int64 totCycles = 0; - for (int i = 0; i < PHASE_NUMBER_OF; i++) - { - if (!PhaseHasChildren[i]) - { - totCycles += m_info.m_cyclesByPhase[i]; - } - fprintf(s_csvFile, "%I64u,", m_info.m_cyclesByPhase[i]); - - if ((JitConfig.JitMeasureIR() != 0) && PhaseReportsIRSize[i]) - { - fprintf(s_csvFile, "%u,", m_info.m_nodeCountAfterPhase[i]); - } - } - comp->m_inlineStrategy->DumpCsvData(s_csvFile); - fprintf(s_csvFile, "%u,", comp->info.compNativeCodeSize); - fprintf(s_csvFile, "%Iu,", comp->compInfoBlkSize); - fprintf(s_csvFile, "%Iu,", comp->compGetArenaAllocator()->getTotalBytesAllocated()); - fprintf(s_csvFile, "%I64u,", m_info.m_totalCycles); - fprintf(s_csvFile, "%f\n", CachedCyclesPerSecond()); + fprintf(s_csvFile, "%u,", comp->info.compILCodeSize); + fprintf(s_csvFile, "%u,", comp->fgBBcount); +#define ASSERTION_STATS(name) \ + assert(comp->##name##Iter >= comp->##name##Count); \ + fprintf(s_csvFile, "%u,", comp->##name##Count); \ + fprintf(s_csvFile, "%u,", comp->##name##Iter); \ + if (comp->##name##Count == 0) \ + { \ + fprintf(s_csvFile, "0,"); \ + } \ + else \ + { \ + fprintf(s_csvFile, "%d,", (comp->##name##Iter / comp->##name##Count)); \ + } + +ASSERTION_STATS(addAssertion) +ASSERTION_STATS(subRange) +ASSERTION_STATS(subType) +ASSERTION_STATS(equalOrNotEqua) +ASSERTION_STATS(noNull) + + fprintf(s_csvFile, "\n,"); fflush(s_csvFile); } diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 8f93ca473c8bb6..a072ec4d90a042 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7288,6 +7288,19 @@ class Compiler AssertionIndex optAssertionCount; // total number of assertions in the assertion table AssertionIndex optMaxAssertionCount; +#ifdef DEBUG +#define ASSERTION_VAR(name) \ + unsigned name##Iter = 0; \ + unsigned name##Count = 0; + +ASSERTION_VAR(addAssertion); +ASSERTION_VAR(subRange); +ASSERTION_VAR(subType); +ASSERTION_VAR(equalOrNotEqua); +ASSERTION_VAR(noNull); + +#endif + struct AssertionDscKeyFuncs { static bool Equals(const AssertionDsc& x, const AssertionDsc& y) From a704843011fe113f4d7a163b54e1ba3dbe5fddbb Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Wed, 27 Jul 2022 14:40:15 -0700 Subject: [PATCH 22/29] Add #ifdef DEBUG --- src/coreclr/jit/assertionprop.cpp | 8 ++++++++ src/coreclr/jit/compiler.cpp | 7 ++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 775155879e595a..53de667e5309d2 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -2900,8 +2900,10 @@ AssertionIndex Compiler::optAssertionIsSubrange(GenTree* tree, IntegralRange ran if (range.Contains(curAssertion->op2.u2)) { +#ifdef DEBUG subRangeCount++; subRangeIter += index; +#endif return index; } } @@ -2968,8 +2970,10 @@ AssertionIndex Compiler::optAssertionIsSubtype(GenTree* tree, GenTree* methodTab if (curAssertion->op2.u1.iconVal == methodTableVal) { +#ifdef DEBUG subTypeCount++; subTypeIter += index; +#endif return index; } } @@ -3821,8 +3825,10 @@ AssertionIndex Compiler::optLocalAssertionIsEqualOrNotEqual( if (constantIsEqual || assertionIsEqual) { +#ifdef DEBUG equalOrNotEquaCount++; equalOrNotEquaIter += index; +#endif return index; } } @@ -4621,8 +4627,10 @@ AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op, (curAssertion->op2.kind == O2K_CONST_INT) && // op2 (curAssertion->op1.lcl.lclNum == lclNum) && (curAssertion->op2.u1.iconVal == 0)) { +#ifdef DEBUG noNullCount++; noNullIter += index; +#endif return index; } } diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 9e36faa5706a55..ee8f2ef98ceb93 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -6448,6 +6448,7 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, compHasBackwardJump = false; compHasBackwardJumpInHandler = false; +#ifdef DEBUG addAssertionCount = 0; addAssertionIter = 0; subRangeCount = 0; @@ -6459,7 +6460,6 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, noNullCount = 0; noNullIter = 0; -#ifdef DEBUG compCurBB = nullptr; lvaTable = nullptr; @@ -8599,6 +8599,7 @@ void JitTimer::PrintCsvHeader() fprintf(s_csvFile, "\"IL Bytes\","); fprintf(s_csvFile, "\"Basic Blocks\","); +#ifdef DEBUG #define ASSERTION_TITLE(name) \ fprintf(s_csvFile, "\"" ## name ## "Count\","); \ fprintf(s_csvFile, "\"" ## name ## "Iter\","); \ @@ -8609,6 +8610,7 @@ ASSERTION_TITLE("SubType") ASSERTION_TITLE("SubRange") ASSERTION_TITLE("EqualOrNotEqual") ASSERTION_TITLE("NoNull") +#endif fprintf(s_csvFile, "\n,"); @@ -8694,6 +8696,8 @@ void JitTimer::PrintCsvMethodStats(Compiler* comp) fprintf(s_csvFile, "%u,", comp->info.compILCodeSize); fprintf(s_csvFile, "%u,", comp->fgBBcount); +#ifdef DEBUG + #define ASSERTION_STATS(name) \ assert(comp->##name##Iter >= comp->##name##Count); \ fprintf(s_csvFile, "%u,", comp->##name##Count); \ @@ -8713,6 +8717,7 @@ ASSERTION_STATS(subType) ASSERTION_STATS(equalOrNotEqua) ASSERTION_STATS(noNull) +#endif fprintf(s_csvFile, "\n,"); fflush(s_csvFile); } From a8b36198089484a2913f38c0aeb496be96f5dae1 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Wed, 27 Jul 2022 16:00:15 -0700 Subject: [PATCH 23/29] Add BucketLimit --- src/coreclr/jit/jithashtable.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/coreclr/jit/jithashtable.h b/src/coreclr/jit/jithashtable.h index 6fa43510d0526e..2eaa4513c7d66f 100644 --- a/src/coreclr/jit/jithashtable.h +++ b/src/coreclr/jit/jithashtable.h @@ -99,7 +99,8 @@ template + typename Behavior = JitHashTableBehavior, + int BucketIndex = 500> class JitHashTable { public: @@ -236,10 +237,14 @@ class JitHashTable unsigned index = GetIndexForKey(k); Node* pN = m_table[index]; + int iterCount = 0; while ((pN != nullptr) && !KeyFuncs::Equals(k, pN->m_key)) { + iterCount++; pN = pN->m_next; } + + assert(iterCount < BucketIndex); if (pN != nullptr) { if (kind == SkipIfExist) From ac688ce1481b41eeb8b91837f0a281614a5c0e83 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Wed, 27 Jul 2022 18:02:20 -0700 Subject: [PATCH 24/29] More instrumentation around prop --- src/coreclr/jit/assertionprop.cpp | 28 +++++++++++++++++ src/coreclr/jit/compiler.cpp | 51 ++++++++++++++++++++----------- src/coreclr/jit/compiler.h | 6 ++++ src/coreclr/jit/jithashtable.h | 10 +++++- 4 files changed, 77 insertions(+), 18 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 53de667e5309d2..f19a59eaa42d4e 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -3657,8 +3657,10 @@ GenTree* Compiler::optAssertionProp_LclVar(ASSERT_VALARG_TP assertions, GenTreeL BitVecOps::Iter iter(apTraits, assertions); unsigned index = 0; + unsigned iterCount = 0; while (iter.NextElem(&index)) { + iterCount++; AssertionIndex assertionIndex = GetAssertionIndex(index); if (assertionIndex > optAssertionCount) { @@ -3680,6 +3682,8 @@ GenTree* Compiler::optAssertionProp_LclVar(ASSERT_VALARG_TP assertions, GenTreeL // matching SSA numbers (i.e., if a0 == b1 and b1 == c0 then a0 == c0) they don't need kill sets. if (optLocalAssertionProp) { + propLclVarCount++; + propLclVarIter += iterCount; // Perform copy assertion prop. GenTree* newTree = optCopyAssertionProp(curAssertion, tree, stmt DEBUGARG(assertionIndex)); if (newTree != nullptr) @@ -3714,12 +3718,16 @@ GenTree* Compiler::optAssertionProp_LclVar(ASSERT_VALARG_TP assertions, GenTreeL // If local assertion prop, just perform constant prop. if (optLocalAssertionProp) { + propLclVarCount++; + propLclVarIter += iterCount; return optConstantAssertionProp(curAssertion, tree, stmt DEBUGARG(assertionIndex)); } // If global assertion, perform constant propagation only if the VN's match. if (curAssertion->op1.vn == vnStore->VNConservativeNormalValue(tree->gtVNPair)) { + propLclVarCount++; + propLclVarIter += iterCount; return optConstantAssertionProp(curAssertion, tree, stmt DEBUGARG(assertionIndex)); } } @@ -3863,8 +3871,11 @@ AssertionIndex Compiler::optGlobalAssertionIsEqualOrNotEqual(ASSERT_VALARG_TP as } BitVecOps::Iter iter(apTraits, assertions); unsigned index = 0; + unsigned iterCount = 0; while (iter.NextElem(&index)) { + iterCount++; + AssertionIndex assertionIndex = GetAssertionIndex(index); if (assertionIndex > optAssertionCount) { @@ -3879,6 +3890,8 @@ AssertionIndex Compiler::optGlobalAssertionIsEqualOrNotEqual(ASSERT_VALARG_TP as if ((curAssertion->op1.vn == vnStore->VNConservativeNormalValue(op1->gtVNPair)) && (curAssertion->op2.vn == vnStore->VNConservativeNormalValue(op2->gtVNPair))) { + propEqualOrNotCount++; + propEqualOrNotIter += iterCount; return assertionIndex; } @@ -3894,6 +3907,8 @@ AssertionIndex Compiler::optGlobalAssertionIsEqualOrNotEqual(ASSERT_VALARG_TP as if ((curAssertion->op1.vn == vnStore->VNConservativeNormalValue(indirAddr->gtVNPair)) && (curAssertion->op2.vn == vnStore->VNConservativeNormalValue(op2->gtVNPair))) { + propEqualOrNotCount++; + propEqualOrNotIter += iterCount; return assertionIndex; } } @@ -3916,8 +3931,10 @@ AssertionIndex Compiler::optGlobalAssertionIsEqualOrNotEqualZero(ASSERT_VALARG_T } BitVecOps::Iter iter(apTraits, assertions); unsigned index = 0; + unsigned iterCount = 0; while (iter.NextElem(&index)) { + iterCount++; AssertionIndex assertionIndex = GetAssertionIndex(index); if (assertionIndex > optAssertionCount) { @@ -3932,6 +3949,9 @@ AssertionIndex Compiler::optGlobalAssertionIsEqualOrNotEqualZero(ASSERT_VALARG_T if ((curAssertion->op1.vn == vnStore->VNConservativeNormalValue(op1->gtVNPair)) && (curAssertion->op2.vn == vnStore->VNZeroForType(op1->TypeGet()))) { + propEqualZeroCount++; + propEqualZeroIter += iterCount; + return assertionIndex; } } @@ -4585,8 +4605,10 @@ AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op, // BitVecOps::Iter iter(apTraits, assertions); unsigned index = 0; + unsigned iterCount = 0; while (iter.NextElem(&index)) { + iterCount++; AssertionIndex assertionIndex = GetAssertionIndex(index); if (assertionIndex > optAssertionCount) { @@ -4612,6 +4634,8 @@ AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op, *pVnBased = true; #endif + propNonNullCount++; + propNonNullIter += iterCount; return assertionIndex; } } @@ -4771,8 +4795,10 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree BitVecOps::Iter iter(apTraits, assertions); unsigned index = 0; + unsigned iterCount = 0; while (iter.NextElem(&index)) { + iterCount++; AssertionIndex assertionIndex = GetAssertionIndex(index); if (assertionIndex > optAssertionCount) { @@ -4865,6 +4891,8 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree #endif if (arrBndsChk == stmt->GetRootNode()) { + propBndChkCount++; + propBndChkIter += iterCount; // We have a top-level bounds check node. // This can happen when trees are broken up due to inlining. // optRemoveStandaloneRangeCheck will return the modified tree (side effects or a no-op). diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index ee8f2ef98ceb93..a68d46c793f0cc 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -6449,16 +6449,22 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, compHasBackwardJumpInHandler = false; #ifdef DEBUG - addAssertionCount = 0; - addAssertionIter = 0; - subRangeCount = 0; - subRangeIter = 0; - subTypeCount = 0; - subTypeIter = 0; - equalOrNotEquaCount = 0; - equalOrNotEquaIter = 0; - noNullCount = 0; - noNullIter = 0; + +#define ASSERTION_ZERO(name) \ + name ## Count = 0; \ + name ## Iter = 0; \ + + + ASSERTION_ZERO(addAssertion) + ASSERTION_ZERO(subRange) + ASSERTION_ZERO(subType) + ASSERTION_ZERO(equalOrNotEqua) + ASSERTION_ZERO(noNull) + ASSERTION_ZERO(propLclVar) + ASSERTION_ZERO(propEqualOrNot) + ASSERTION_ZERO(propEqualZero) + ASSERTION_ZERO(propNonNull) + ASSERTION_ZERO(propBndChk) compCurBB = nullptr; lvaTable = nullptr; @@ -8610,6 +8616,12 @@ ASSERTION_TITLE("SubType") ASSERTION_TITLE("SubRange") ASSERTION_TITLE("EqualOrNotEqual") ASSERTION_TITLE("NoNull") +ASSERTION_TITLE("PropLclVar") +ASSERTION_TITLE("PropEqualOrNot") +ASSERTION_TITLE("PropEqualZero") +ASSERTION_TITLE("PropNonNull") +ASSERTION_TITLE("PropBndChk") + #endif fprintf(s_csvFile, "\n,"); @@ -8681,16 +8693,16 @@ void JitTimer::PrintCsvMethodStats(Compiler* comp) } //fprintf(s_csvFile, "\"%s\",", methName); - if (index != 0) + //if (index != 0) { fprintf(s_csvFile, "%d,", index); } - else - { - const char* methodAssemblyName = comp->info.compCompHnd->getAssemblyName( - comp->info.compCompHnd->getModuleAssembly(comp->info.compCompHnd->getClassModule(comp->info.compClassHnd))); - fprintf(s_csvFile, "\"%s\",", methodAssemblyName); - } + //else + //{ + // const char* methodAssemblyName = comp->info.compCompHnd->getAssemblyName( + // comp->info.compCompHnd->getModuleAssembly(comp->info.compCompHnd->getClassModule(comp->info.compClassHnd))); + // fprintf(s_csvFile, "\"%s\",", methodAssemblyName); + //} fprintf(s_csvFile, "%u,", comp->info.compILCodeSize); @@ -8716,6 +8728,11 @@ ASSERTION_STATS(subRange) ASSERTION_STATS(subType) ASSERTION_STATS(equalOrNotEqua) ASSERTION_STATS(noNull) +ASSERTION_STATS(propLclVar) +ASSERTION_STATS(propEqualOrNot) +ASSERTION_STATS(propEqualZero) +ASSERTION_STATS(propNonNull) +ASSERTION_STATS(propBndChk) #endif fprintf(s_csvFile, "\n,"); diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index a072ec4d90a042..700e3b65f794c8 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7299,6 +7299,12 @@ ASSERTION_VAR(subType); ASSERTION_VAR(equalOrNotEqua); ASSERTION_VAR(noNull); +ASSERTION_VAR(propLclVar); +ASSERTION_VAR(propEqualOrNot); +ASSERTION_VAR(propEqualZero); +ASSERTION_VAR(propNonNull); +ASSERTION_VAR(propBndChk); + #endif struct AssertionDscKeyFuncs diff --git a/src/coreclr/jit/jithashtable.h b/src/coreclr/jit/jithashtable.h index 2eaa4513c7d66f..be8285aa642801 100644 --- a/src/coreclr/jit/jithashtable.h +++ b/src/coreclr/jit/jithashtable.h @@ -236,6 +236,14 @@ class JitHashTable unsigned index = GetIndexForKey(k); + //if (BucketIndex == 13) + //{ + // unsigned hash = KeyFuncs::GetHashCode(k); + + // unsigned index = m_tableSizeInfo.magicNumberRem(hash); + // printf("hash= %d, index= %d\n", hash, index); + //} + Node* pN = m_table[index]; int iterCount = 0; while ((pN != nullptr) && !KeyFuncs::Equals(k, pN->m_key)) @@ -244,7 +252,7 @@ class JitHashTable pN = pN->m_next; } - assert(iterCount < BucketIndex); + //assert(iterCount < BucketIndex); if (pN != nullptr) { if (kind == SkipIfExist) From 6594abd76419fb7751c12b677f8c5578e4e32d37 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Thu, 28 Jul 2022 15:27:37 -0700 Subject: [PATCH 25/29] Added count for missed count, iterations --- src/coreclr/jit/assertionprop.cpp | 63 ++++++++++++++++++++++++++++++- src/coreclr/jit/compiler.cpp | 45 +++++++++++----------- src/coreclr/jit/compiler.h | 34 +++++++++-------- 3 files changed, 104 insertions(+), 38 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index f19a59eaa42d4e..1771a805e0af68 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -1966,6 +1966,7 @@ bool Compiler::optAssertionVnInvolvesNan(AssertionDsc* assertion) */ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) { + addAssertionCallCount++; noway_assert(newAssertion->assertionKind != OAK_INVALID); // Even though the propagation step takes care of NaN, just a check @@ -1994,6 +1995,12 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) break; } } + + if (!found) + { + missedaddAssertionCount++; + missedaddAssertionIter += optAssertionCount; + } #endif // Check if we are within max count. @@ -2881,6 +2888,8 @@ AssertionIndex Compiler::optAssertionIsSubrange(GenTree* tree, IntegralRange ran return NO_ASSERTION_INDEX; } + subRangeCallCount++; + for (AssertionIndex index = 1; index <= optAssertionCount; index++) { AssertionDsc* curAssertion = optGetAssertion(index); @@ -2909,6 +2918,9 @@ AssertionIndex Compiler::optAssertionIsSubrange(GenTree* tree, IntegralRange ran } } + missedsubRangeCount++; + missedsubRangeIter += (optLocalAssertionProp ? optAssertionCount : (BitVecOps::Count(apTraits, assertions))); + return NO_ASSERTION_INDEX; } @@ -2927,6 +2939,9 @@ AssertionIndex Compiler::optAssertionIsSubtype(GenTree* tree, GenTree* methodTab { return NO_ASSERTION_INDEX; } + + subTypeCallCount++; + for (AssertionIndex index = 1; index <= optAssertionCount; index++) { if (!optLocalAssertionProp && !BitVecOps::IsMember(apTraits, assertions, index - 1)) @@ -2977,6 +2992,9 @@ AssertionIndex Compiler::optAssertionIsSubtype(GenTree* tree, GenTree* methodTab return index; } } + + missedsubTypeCount++; + missedsubTypeIter += (optLocalAssertionProp ? optAssertionCount : (BitVecOps::Count(apTraits, assertions))); return NO_ASSERTION_INDEX; } @@ -3655,6 +3673,8 @@ GenTree* Compiler::optAssertionProp_LclVar(ASSERT_VALARG_TP assertions, GenTreeL return nullptr; } + propLclVarCallCount++; + BitVecOps::Iter iter(apTraits, assertions); unsigned index = 0; unsigned iterCount = 0; @@ -3734,6 +3754,9 @@ GenTree* Compiler::optAssertionProp_LclVar(ASSERT_VALARG_TP assertions, GenTreeL } } + missedpropLclVarCount++; + missedpropLclVarIter += (optLocalAssertionProp ? optAssertionCount : (BitVecOps::Count(apTraits, assertions))); + return nullptr; } @@ -3815,6 +3838,8 @@ AssertionIndex Compiler::optLocalAssertionIsEqualOrNotEqual( return NO_ASSERTION_INDEX; } + equalOrNotEquaCallCount++; + for (AssertionIndex index = 1; index <= optAssertionCount; ++index) { AssertionDsc* curAssertion = optGetAssertion(index); @@ -3842,6 +3867,10 @@ AssertionIndex Compiler::optLocalAssertionIsEqualOrNotEqual( } } } + + missedequalOrNotEquaCount++; + missedequalOrNotEquaIter += (optLocalAssertionProp ? optAssertionCount : (BitVecOps::Count(apTraits, assertions))); + return NO_ASSERTION_INDEX; } @@ -3869,6 +3898,9 @@ AssertionIndex Compiler::optGlobalAssertionIsEqualOrNotEqual(ASSERT_VALARG_TP as { return NO_ASSERTION_INDEX; } + + propEqualOrNotCallCount++; + BitVecOps::Iter iter(apTraits, assertions); unsigned index = 0; unsigned iterCount = 0; @@ -3914,6 +3946,10 @@ AssertionIndex Compiler::optGlobalAssertionIsEqualOrNotEqual(ASSERT_VALARG_TP as } } } + + missedpropEqualOrNotCount++; + missedpropEqualOrNotIter += BitVecOps::Count(apTraits, assertions); + return NO_ASSERTION_INDEX; } @@ -3929,6 +3965,9 @@ AssertionIndex Compiler::optGlobalAssertionIsEqualOrNotEqualZero(ASSERT_VALARG_T { return NO_ASSERTION_INDEX; } + + propEqualZeroCallCount++; + BitVecOps::Iter iter(apTraits, assertions); unsigned index = 0; unsigned iterCount = 0; @@ -3955,6 +3994,10 @@ AssertionIndex Compiler::optGlobalAssertionIsEqualOrNotEqualZero(ASSERT_VALARG_T return assertionIndex; } } + + missedpropEqualZeroCount++; + missedpropEqualZeroIter += BitVecOps::Count(apTraits, assertions); + return NO_ASSERTION_INDEX; } @@ -4577,6 +4620,7 @@ AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op, return NO_ASSERTION_INDEX; } + noNullCallCount++; // Look at both the top-level vn, and // the vn we get by stripping off any constant adds. // @@ -4634,13 +4678,19 @@ AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op, *pVnBased = true; #endif - propNonNullCount++; - propNonNullIter += iterCount; + noNullCount++; + noNullIter += iterCount; return assertionIndex; } + + + missednoNullCount++; + missednoNullIter += BitVecOps::Count(apTraits, assertions); } else { + noNullCallCount++; + unsigned lclNum = op->AsLclVarCommon()->GetLclNum(); // Check each assertion to find if we have a variable == or != null assertion. for (AssertionIndex index = 1; index <= optAssertionCount; index++) @@ -4658,7 +4708,11 @@ AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op, return index; } } + + missednoNullCount++; + missednoNullIter += optAssertionCount; } + return NO_ASSERTION_INDEX; } /***************************************************************************** @@ -4793,6 +4847,8 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree } #endif // FEATURE_ENABLE_NO_RANGE_CHECKS + propBndChkCallCount++; + BitVecOps::Iter iter(apTraits, assertions); unsigned index = 0; unsigned iterCount = 0; @@ -4908,6 +4964,9 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree return nullptr; } + missedpropBndChkCount++; + missedpropBndChkIter += BitVecOps::Count(apTraits, assertions); + return nullptr; } diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index a68d46c793f0cc..c89d0dfd8cd78d 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -6450,11 +6450,13 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, #ifdef DEBUG -#define ASSERTION_ZERO(name) \ - name ## Count = 0; \ - name ## Iter = 0; \ +#define ASSERTION_ZERO(name) \ + name##Count = 0; \ + name##Iter = 0; \ + missed##name##Iter = 0; \ + missed##name##Count = 0; \ + name##CallCount = 0; - ASSERTION_ZERO(addAssertion) ASSERTION_ZERO(subRange) ASSERTION_ZERO(subType) @@ -6463,8 +6465,10 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, ASSERTION_ZERO(propLclVar) ASSERTION_ZERO(propEqualOrNot) ASSERTION_ZERO(propEqualZero) - ASSERTION_ZERO(propNonNull) ASSERTION_ZERO(propBndChk) + ASSERTION_ZERO(impliedByCopy) + ASSERTION_ZERO(impliedByConst) + ASSERTION_ZERO(impliedByType) compCurBB = nullptr; lvaTable = nullptr; @@ -8607,9 +8611,14 @@ void JitTimer::PrintCsvHeader() #ifdef DEBUG #define ASSERTION_TITLE(name) \ - fprintf(s_csvFile, "\"" ## name ## "Count\","); \ - fprintf(s_csvFile, "\"" ## name ## "Iter\","); \ - fprintf(s_csvFile, "\"" ## name ## "Ratio\","); + fprintf(s_csvFile, "\"" ## name ## "Match\","); \ + fprintf(s_csvFile, "\"" ## name ## "Iter\","); \ + fprintf(s_csvFile, "\"" ## name ## "Ratio\","); \ + fprintf(s_csvFile, "\"" ## name ## "MissedCount\","); \ + fprintf(s_csvFile, "\"" ## name ## "MissedIter\","); \ + fprintf(s_csvFile, "\"" ## name ## "MissedRatio\","); \ + fprintf(s_csvFile, "\"" ## name ## "CallCount\","); + ASSERTION_TITLE("AddAssertion") ASSERTION_TITLE("SubType") @@ -8619,12 +8628,11 @@ ASSERTION_TITLE("NoNull") ASSERTION_TITLE("PropLclVar") ASSERTION_TITLE("PropEqualOrNot") ASSERTION_TITLE("PropEqualZero") -ASSERTION_TITLE("PropNonNull") ASSERTION_TITLE("PropBndChk") #endif - fprintf(s_csvFile, "\n,"); + fprintf(s_csvFile, "\n"); @@ -8714,14 +8722,11 @@ void JitTimer::PrintCsvMethodStats(Compiler* comp) assert(comp->##name##Iter >= comp->##name##Count); \ fprintf(s_csvFile, "%u,", comp->##name##Count); \ fprintf(s_csvFile, "%u,", comp->##name##Iter); \ - if (comp->##name##Count == 0) \ - { \ - fprintf(s_csvFile, "0,"); \ - } \ - else \ - { \ - fprintf(s_csvFile, "%d,", (comp->##name##Iter / comp->##name##Count)); \ - } + fprintf(s_csvFile, "%d,", (comp->##name##Count == 0) ? 0 : (comp->##name##Iter / comp->##name##Count)); \ + fprintf(s_csvFile, "%u,", comp->missed##name##Count); \ + fprintf(s_csvFile, "%u,", comp->missed##name##Iter); \ + fprintf(s_csvFile, "%d,", (comp->missed##name##Count == 0) ? 0 : (comp->missed##name##Iter / comp->missed##name##Count)); \ + fprintf(s_csvFile, "%u,", comp->##name##CallCount); ASSERTION_STATS(addAssertion) ASSERTION_STATS(subRange) @@ -8731,11 +8736,9 @@ ASSERTION_STATS(noNull) ASSERTION_STATS(propLclVar) ASSERTION_STATS(propEqualOrNot) ASSERTION_STATS(propEqualZero) -ASSERTION_STATS(propNonNull) ASSERTION_STATS(propBndChk) - #endif - fprintf(s_csvFile, "\n,"); + fprintf(s_csvFile, "\n"); fflush(s_csvFile); } diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 700e3b65f794c8..07dfb17551851d 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7289,21 +7289,25 @@ class Compiler AssertionIndex optMaxAssertionCount; #ifdef DEBUG -#define ASSERTION_VAR(name) \ - unsigned name##Iter = 0; \ - unsigned name##Count = 0; - -ASSERTION_VAR(addAssertion); -ASSERTION_VAR(subRange); -ASSERTION_VAR(subType); -ASSERTION_VAR(equalOrNotEqua); -ASSERTION_VAR(noNull); - -ASSERTION_VAR(propLclVar); -ASSERTION_VAR(propEqualOrNot); -ASSERTION_VAR(propEqualZero); -ASSERTION_VAR(propNonNull); -ASSERTION_VAR(propBndChk); +#define ASSERTION_VAR(name) \ + unsigned name##Iter = 0; \ + unsigned name##Count = 0; \ + unsigned missed##name##Iter = 0; \ + unsigned missed##name##Count = 0; \ + unsigned name##CallCount = 0; + +ASSERTION_VAR(addAssertion) +ASSERTION_VAR(subRange) +ASSERTION_VAR(subType) +ASSERTION_VAR(equalOrNotEqua) +ASSERTION_VAR(noNull) +ASSERTION_VAR(propLclVar) +ASSERTION_VAR(propEqualOrNot) +ASSERTION_VAR(propEqualZero) +ASSERTION_VAR(propBndChk) +ASSERTION_VAR(impliedByCopy) +ASSERTION_VAR(impliedByConst) +ASSERTION_VAR(impliedByType) #endif From 45057e4661a024cb7beac3cc1c6d1691654bcbe5 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Thu, 28 Jul 2022 16:00:07 -0700 Subject: [PATCH 26/29] fix the propLclVarCount --- src/coreclr/jit/assertionprop.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 1771a805e0af68..6a343297725fe3 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -3702,12 +3702,12 @@ GenTree* Compiler::optAssertionProp_LclVar(ASSERT_VALARG_TP assertions, GenTreeL // matching SSA numbers (i.e., if a0 == b1 and b1 == c0 then a0 == c0) they don't need kill sets. if (optLocalAssertionProp) { - propLclVarCount++; - propLclVarIter += iterCount; // Perform copy assertion prop. GenTree* newTree = optCopyAssertionProp(curAssertion, tree, stmt DEBUGARG(assertionIndex)); if (newTree != nullptr) { + propLclVarCount++; + propLclVarIter += iterCount; return newTree; } } @@ -3716,7 +3716,7 @@ GenTree* Compiler::optAssertionProp_LclVar(ASSERT_VALARG_TP assertions, GenTreeL } // There are no constant assertions for structs. - // + // OK - Then why is the check inside the for-loop for global prop? if (varTypeIsStruct(tree)) { continue; From 88c2459c6d4d1eaa45cb7691902e319a4eb32c55 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Thu, 28 Jul 2022 18:24:00 -0700 Subject: [PATCH 27/29] PR ready --- src/coreclr/jit/assertionprop.cpp | 122 ++++++++-------- src/coreclr/jit/compiler.cpp | 225 ++++++++++++++++-------------- src/coreclr/jit/compiler.h | 40 +++--- src/coreclr/jit/jit.h | 2 + src/coreclr/jit/jithashtable.h | 15 +- 5 files changed, 208 insertions(+), 196 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 6a343297725fe3..da446600c208e4 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -1966,7 +1966,7 @@ bool Compiler::optAssertionVnInvolvesNan(AssertionDsc* assertion) */ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) { - addAssertionCallCount++; + RECORD_ASSERTION_STATS(addAssertionCallCount++); noway_assert(newAssertion->assertionKind != OAK_INVALID); // Even though the propagation step takes care of NaN, just a check @@ -1990,16 +1990,16 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) { found = true; slowAnswer = index; - addAssertionCount++; - addAssertionIter += (optAssertionCount - index + 1); + RECORD_ASSERTION_STATS(addAssertionMatchCount++); + RECORD_ASSERTION_STATS(addAssertionIter += (optAssertionCount - index + 1)); break; } } if (!found) { - missedaddAssertionCount++; - missedaddAssertionIter += optAssertionCount; + RECORD_ASSERTION_STATS(addAssertionMissedCount++); + RECORD_ASSERTION_STATS(addAssertionMissedIter += optAssertionCount); } #endif @@ -2888,7 +2888,7 @@ AssertionIndex Compiler::optAssertionIsSubrange(GenTree* tree, IntegralRange ran return NO_ASSERTION_INDEX; } - subRangeCallCount++; + RECORD_ASSERTION_STATS(subRangeCallCount++); for (AssertionIndex index = 1; index <= optAssertionCount; index++) { @@ -2909,17 +2909,15 @@ AssertionIndex Compiler::optAssertionIsSubrange(GenTree* tree, IntegralRange ran if (range.Contains(curAssertion->op2.u2)) { -#ifdef DEBUG - subRangeCount++; - subRangeIter += index; -#endif + RECORD_ASSERTION_STATS(subRangeMatchCount++); + RECORD_ASSERTION_STATS(subRangeIter += index); return index; } } } - missedsubRangeCount++; - missedsubRangeIter += (optLocalAssertionProp ? optAssertionCount : (BitVecOps::Count(apTraits, assertions))); + RECORD_ASSERTION_STATS(subRangeMissedCount++); + RECORD_ASSERTION_STATS(subRangeMissedIter += (optLocalAssertionProp ? optAssertionCount : (BitVecOps::Count(apTraits, assertions)))); return NO_ASSERTION_INDEX; } @@ -2940,7 +2938,7 @@ AssertionIndex Compiler::optAssertionIsSubtype(GenTree* tree, GenTree* methodTab return NO_ASSERTION_INDEX; } - subTypeCallCount++; + RECORD_ASSERTION_STATS(subTypeCallCount++); for (AssertionIndex index = 1; index <= optAssertionCount; index++) { @@ -2985,16 +2983,14 @@ AssertionIndex Compiler::optAssertionIsSubtype(GenTree* tree, GenTree* methodTab if (curAssertion->op2.u1.iconVal == methodTableVal) { -#ifdef DEBUG - subTypeCount++; - subTypeIter += index; -#endif + RECORD_ASSERTION_STATS(subTypeMatchCount++); + RECORD_ASSERTION_STATS(subTypeIter += index); return index; } } - missedsubTypeCount++; - missedsubTypeIter += (optLocalAssertionProp ? optAssertionCount : (BitVecOps::Count(apTraits, assertions))); + RECORD_ASSERTION_STATS(subTypeMissedCount++); + RECORD_ASSERTION_STATS(subTypeMissedIter += (optLocalAssertionProp ? optAssertionCount : (BitVecOps::Count(apTraits, assertions)))); return NO_ASSERTION_INDEX; } @@ -3673,14 +3669,18 @@ GenTree* Compiler::optAssertionProp_LclVar(ASSERT_VALARG_TP assertions, GenTreeL return nullptr; } - propLclVarCallCount++; + RECORD_ASSERTION_STATS(propLclVarCallCount++); BitVecOps::Iter iter(apTraits, assertions); unsigned index = 0; +#if TRACK_ASSERTION_STATS unsigned iterCount = 0; +#endif while (iter.NextElem(&index)) { +#if TRACK_ASSERTION_STATS iterCount++; +#endi AssertionIndex assertionIndex = GetAssertionIndex(index); if (assertionIndex > optAssertionCount) { @@ -3706,8 +3706,8 @@ GenTree* Compiler::optAssertionProp_LclVar(ASSERT_VALARG_TP assertions, GenTreeL GenTree* newTree = optCopyAssertionProp(curAssertion, tree, stmt DEBUGARG(assertionIndex)); if (newTree != nullptr) { - propLclVarCount++; - propLclVarIter += iterCount; + RECORD_ASSERTION_STATS(propLclVarMatchCount++); + RECORD_ASSERTION_STATS(propLclVarIter += iterCount); return newTree; } } @@ -3738,24 +3738,24 @@ GenTree* Compiler::optAssertionProp_LclVar(ASSERT_VALARG_TP assertions, GenTreeL // If local assertion prop, just perform constant prop. if (optLocalAssertionProp) { - propLclVarCount++; - propLclVarIter += iterCount; + RECORD_ASSERTION_STATS(propLclVarMatchCount++); + RECORD_ASSERTION_STATS(propLclVarIter += iterCount); return optConstantAssertionProp(curAssertion, tree, stmt DEBUGARG(assertionIndex)); } // If global assertion, perform constant propagation only if the VN's match. if (curAssertion->op1.vn == vnStore->VNConservativeNormalValue(tree->gtVNPair)) { - propLclVarCount++; - propLclVarIter += iterCount; + RECORD_ASSERTION_STATS(propLclVarMatchCount++); + RECORD_ASSERTION_STATS(propLclVarIter += iterCount); return optConstantAssertionProp(curAssertion, tree, stmt DEBUGARG(assertionIndex)); } } } } - missedpropLclVarCount++; - missedpropLclVarIter += (optLocalAssertionProp ? optAssertionCount : (BitVecOps::Count(apTraits, assertions))); + RECORD_ASSERTION_STATS(propLclVarMissedCount++); + RECORD_ASSERTION_STATS(propLclVarMissedIter += (optLocalAssertionProp ? optAssertionCount : (BitVecOps::Count(apTraits, assertions)))); return nullptr; } @@ -3838,7 +3838,7 @@ AssertionIndex Compiler::optLocalAssertionIsEqualOrNotEqual( return NO_ASSERTION_INDEX; } - equalOrNotEquaCallCount++; + RECORD_ASSERTION_STATS(equalOrNotEquaCallCount++); for (AssertionIndex index = 1; index <= optAssertionCount; ++index) { @@ -3858,18 +3858,16 @@ AssertionIndex Compiler::optLocalAssertionIsEqualOrNotEqual( if (constantIsEqual || assertionIsEqual) { -#ifdef DEBUG - equalOrNotEquaCount++; - equalOrNotEquaIter += index; -#endif + RECORD_ASSERTION_STATS(equalOrNotEquaMatchCount++); + RECORD_ASSERTION_STATS(equalOrNotEquaIter += index); return index; } } } } - missedequalOrNotEquaCount++; - missedequalOrNotEquaIter += (optLocalAssertionProp ? optAssertionCount : (BitVecOps::Count(apTraits, assertions))); + RECORD_ASSERTION_STATS(equalOrNotEquaMissedCount++); + RECORD_ASSERTION_STATS(equalOrNotEquaMissedIter += (optLocalAssertionProp ? optAssertionCount : (BitVecOps::Count(apTraits, assertions)))); return NO_ASSERTION_INDEX; } @@ -3899,7 +3897,7 @@ AssertionIndex Compiler::optGlobalAssertionIsEqualOrNotEqual(ASSERT_VALARG_TP as return NO_ASSERTION_INDEX; } - propEqualOrNotCallCount++; + RECORD_ASSERTION_STATS(propEqualOrNotCallCount++); BitVecOps::Iter iter(apTraits, assertions); unsigned index = 0; @@ -3922,8 +3920,8 @@ AssertionIndex Compiler::optGlobalAssertionIsEqualOrNotEqual(ASSERT_VALARG_TP as if ((curAssertion->op1.vn == vnStore->VNConservativeNormalValue(op1->gtVNPair)) && (curAssertion->op2.vn == vnStore->VNConservativeNormalValue(op2->gtVNPair))) { - propEqualOrNotCount++; - propEqualOrNotIter += iterCount; + RECORD_ASSERTION_STATS(propEqualOrNotMatchCount++); + RECORD_ASSERTION_STATS(propEqualOrNotIter += iterCount); return assertionIndex; } @@ -3939,16 +3937,16 @@ AssertionIndex Compiler::optGlobalAssertionIsEqualOrNotEqual(ASSERT_VALARG_TP as if ((curAssertion->op1.vn == vnStore->VNConservativeNormalValue(indirAddr->gtVNPair)) && (curAssertion->op2.vn == vnStore->VNConservativeNormalValue(op2->gtVNPair))) { - propEqualOrNotCount++; - propEqualOrNotIter += iterCount; + RECORD_ASSERTION_STATS(propEqualOrNotMatchCount++); + RECORD_ASSERTION_STATS(propEqualOrNotIter += iterCount); return assertionIndex; } } } } - missedpropEqualOrNotCount++; - missedpropEqualOrNotIter += BitVecOps::Count(apTraits, assertions); + RECORD_ASSERTION_STATS(propEqualOrNotMissedCount++); + RECORD_ASSERTION_STATS(propEqualOrNotMissedIter += BitVecOps::Count(apTraits, assertions)); return NO_ASSERTION_INDEX; } @@ -3966,7 +3964,7 @@ AssertionIndex Compiler::optGlobalAssertionIsEqualOrNotEqualZero(ASSERT_VALARG_T return NO_ASSERTION_INDEX; } - propEqualZeroCallCount++; + RECORD_ASSERTION_STATS(propEqualZeroCallCount++); BitVecOps::Iter iter(apTraits, assertions); unsigned index = 0; @@ -3988,15 +3986,15 @@ AssertionIndex Compiler::optGlobalAssertionIsEqualOrNotEqualZero(ASSERT_VALARG_T if ((curAssertion->op1.vn == vnStore->VNConservativeNormalValue(op1->gtVNPair)) && (curAssertion->op2.vn == vnStore->VNZeroForType(op1->TypeGet()))) { - propEqualZeroCount++; - propEqualZeroIter += iterCount; + RECORD_ASSERTION_STATS(propEqualZeroMatchCount++); + RECORD_ASSERTION_STATS(propEqualZeroIter += iterCount); return assertionIndex; } } - missedpropEqualZeroCount++; - missedpropEqualZeroIter += BitVecOps::Count(apTraits, assertions); + RECORD_ASSERTION_STATS(propEqualZeroMissedCount++); + RECORD_ASSERTION_STATS(propEqualZeroMissedIter += BitVecOps::Count(apTraits, assertions)); return NO_ASSERTION_INDEX; } @@ -4620,7 +4618,7 @@ AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op, return NO_ASSERTION_INDEX; } - noNullCallCount++; + RECORD_ASSERTION_STATS(noNullCallCount++); // Look at both the top-level vn, and // the vn we get by stripping off any constant adds. // @@ -4678,18 +4676,18 @@ AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op, *pVnBased = true; #endif - noNullCount++; - noNullIter += iterCount; + RECORD_ASSERTION_STATS(noNullMatchCount++); + RECORD_ASSERTION_STATS(noNullIter += iterCount); return assertionIndex; } - missednoNullCount++; - missednoNullIter += BitVecOps::Count(apTraits, assertions); + RECORD_ASSERTION_STATS(noNullMissedCount++); + RECORD_ASSERTION_STATS(noNullMissedIter += BitVecOps::Count(apTraits, assertions)); } else { - noNullCallCount++; + RECORD_ASSERTION_STATS(noNullCallCount++); unsigned lclNum = op->AsLclVarCommon()->GetLclNum(); // Check each assertion to find if we have a variable == or != null assertion. @@ -4702,15 +4700,15 @@ AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op, (curAssertion->op1.lcl.lclNum == lclNum) && (curAssertion->op2.u1.iconVal == 0)) { #ifdef DEBUG - noNullCount++; - noNullIter += index; + RECORD_ASSERTION_STATS(noNullMatchCount++); + RECORD_ASSERTION_STATS(noNullIter += index); #endif return index; } } - missednoNullCount++; - missednoNullIter += optAssertionCount; + RECORD_ASSERTION_STATS(noNullMissedCount++); + RECORD_ASSERTION_STATS(noNullMissedIter += optAssertionCount); } return NO_ASSERTION_INDEX; @@ -4847,7 +4845,7 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree } #endif // FEATURE_ENABLE_NO_RANGE_CHECKS - propBndChkCallCount++; + RECORD_ASSERTION_STATS(propBndChkCallCount++); BitVecOps::Iter iter(apTraits, assertions); unsigned index = 0; @@ -4947,8 +4945,8 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree #endif if (arrBndsChk == stmt->GetRootNode()) { - propBndChkCount++; - propBndChkIter += iterCount; + RECORD_ASSERTION_STATS(propBndChkMatchCount++); + RECORD_ASSERTION_STATS(propBndChkIter += iterCount); // We have a top-level bounds check node. // This can happen when trees are broken up due to inlining. // optRemoveStandaloneRangeCheck will return the modified tree (side effects or a no-op). @@ -4964,8 +4962,8 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree return nullptr; } - missedpropBndChkCount++; - missedpropBndChkIter += BitVecOps::Count(apTraits, assertions); + RECORD_ASSERTION_STATS(propBndChkMissedCount++); + RECORD_ASSERTION_STATS(propBndChkMissedIter += BitVecOps::Count(apTraits, assertions)); return nullptr; } diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index c89d0dfd8cd78d..adb2e4686c503c 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -6448,28 +6448,28 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, compHasBackwardJump = false; compHasBackwardJumpInHandler = false; -#ifdef DEBUG - -#define ASSERTION_ZERO(name) \ - name##Count = 0; \ - name##Iter = 0; \ - missed##name##Iter = 0; \ - missed##name##Count = 0; \ - name##CallCount = 0; - - ASSERTION_ZERO(addAssertion) - ASSERTION_ZERO(subRange) - ASSERTION_ZERO(subType) - ASSERTION_ZERO(equalOrNotEqua) - ASSERTION_ZERO(noNull) - ASSERTION_ZERO(propLclVar) - ASSERTION_ZERO(propEqualOrNot) - ASSERTION_ZERO(propEqualZero) - ASSERTION_ZERO(propBndChk) - ASSERTION_ZERO(impliedByCopy) - ASSERTION_ZERO(impliedByConst) - ASSERTION_ZERO(impliedByType) +#if TRACK_ASSERTION_STATS + +#define ASSERTION_STATS_ZERO(name) \ + name##Iter = 0; \ + name##MatchCount = 0; \ + name##MissedIter = 0; \ + name##MissedCount = 0; \ + name##CallCount = 0; + + ASSERTION_STATS_ZERO(addAssertion) + ASSERTION_STATS_ZERO(subRange) + ASSERTION_STATS_ZERO(subType) + ASSERTION_STATS_ZERO(equalOrNotEqua) + ASSERTION_STATS_ZERO(noNull) + ASSERTION_STATS_ZERO(propLclVar) + ASSERTION_STATS_ZERO(propEqualOrNot) + ASSERTION_STATS_ZERO(propEqualZero) + ASSERTION_STATS_ZERO(propBndChk) + +#endif // TRACK_ASSERTION_STATS +#ifdef DEBUG compCurBB = nullptr; lvaTable = nullptr; @@ -8604,64 +8604,57 @@ void JitTimer::PrintCsvHeader() // Write the header if the file is empty if (ftell(s_csvFile) == 0) { - //fprintf(s_csvFile, "\"Method Name\","); + fprintf(s_csvFile, "\"Method Name\","); fprintf(s_csvFile, "\"Assembly or SPMI Index\","); fprintf(s_csvFile, "\"IL Bytes\","); fprintf(s_csvFile, "\"Basic Blocks\","); - + fprintf(s_csvFile, "\"Min Opts\","); + fprintf(s_csvFile, "\"Loops\","); + fprintf(s_csvFile, "\"Loops Cloned\","); +#if FEATURE_LOOP_ALIGN #ifdef DEBUG -#define ASSERTION_TITLE(name) \ - fprintf(s_csvFile, "\"" ## name ## "Match\","); \ - fprintf(s_csvFile, "\"" ## name ## "Iter\","); \ - fprintf(s_csvFile, "\"" ## name ## "Ratio\","); \ - fprintf(s_csvFile, "\"" ## name ## "MissedCount\","); \ - fprintf(s_csvFile, "\"" ## name ## "MissedIter\","); \ - fprintf(s_csvFile, "\"" ## name ## "MissedRatio\","); \ - fprintf(s_csvFile, "\"" ## name ## "CallCount\","); - - -ASSERTION_TITLE("AddAssertion") -ASSERTION_TITLE("SubType") -ASSERTION_TITLE("SubRange") -ASSERTION_TITLE("EqualOrNotEqual") -ASSERTION_TITLE("NoNull") -ASSERTION_TITLE("PropLclVar") -ASSERTION_TITLE("PropEqualOrNot") -ASSERTION_TITLE("PropEqualZero") -ASSERTION_TITLE("PropBndChk") - -#endif + fprintf(s_csvFile, "\"Alignment Candidates\","); + fprintf(s_csvFile, "\"Loops Aligned\","); +#endif // DEBUG +#endif // FEATURE_LOOP_ALIGN + for (int i = 0; i < PHASE_NUMBER_OF; i++) + { + fprintf(s_csvFile, "\"%s\",", PhaseNames[i]); + if ((JitConfig.JitMeasureIR() != 0) && PhaseReportsIRSize[i]) + { + fprintf(s_csvFile, "\"Node Count After %s\",", PhaseNames[i]); + } + } + InlineStrategy::DumpCsvHeader(s_csvFile); + +#if TRACK_ASSERTION_STATS + +#define ASSERTION_TITLE(name) \ + fprintf(s_csvFile, "\""##name##"Match\","); \ + fprintf(s_csvFile, "\""##name##"Iter\","); \ + fprintf(s_csvFile, "\""##name##"MissedCount\","); \ + fprintf(s_csvFile, "\""##name##"MissedIter\","); \ + fprintf(s_csvFile, "\""##name##"CallCount\","); + + ASSERTION_TITLE("AddAssertion") + ASSERTION_TITLE("SubType") + ASSERTION_TITLE("SubRange") + ASSERTION_TITLE("EqualOrNotEqual") + ASSERTION_TITLE("NoNull") + ASSERTION_TITLE("PropLclVar") + ASSERTION_TITLE("PropEqualOrNot") + ASSERTION_TITLE("PropEqualZero") + ASSERTION_TITLE("PropBndChk") + +#endif // TRACK_ASSERTION_STATS + + fprintf(s_csvFile, "\"Executable Code Bytes\","); + fprintf(s_csvFile, "\"GC Info Bytes\","); + fprintf(s_csvFile, "\"Total Bytes Allocated\","); + fprintf(s_csvFile, "\"Total Cycles\","); + fprintf(s_csvFile, "\"CPS\""); fprintf(s_csvFile, "\n"); - - - - // fprintf(s_csvFile, "\"Min Opts\","); -// fprintf(s_csvFile, "\"Loops\","); -// fprintf(s_csvFile, "\"Loops Cloned\","); -//#if FEATURE_LOOP_ALIGN -//#ifdef DEBUG -// fprintf(s_csvFile, "\"Alignment Candidates\","); -// fprintf(s_csvFile, "\"Loops Aligned\","); -//#endif // DEBUG -//#endif // FEATURE_LOOP_ALIGN -// for (int i = 0; i < PHASE_NUMBER_OF; i++) -// { -// fprintf(s_csvFile, "\"%s\",", PhaseNames[i]); -// if ((JitConfig.JitMeasureIR() != 0) && PhaseReportsIRSize[i]) -// { -// fprintf(s_csvFile, "\"Node Count After %s\",", PhaseNames[i]); -// } -// } -// -// InlineStrategy::DumpCsvHeader(s_csvFile); -// -// fprintf(s_csvFile, "\"Executable Code Bytes\","); -// fprintf(s_csvFile, "\"GC Info Bytes\","); -// fprintf(s_csvFile, "\"Total Bytes Allocated\","); -// fprintf(s_csvFile, "\"Total Cycles\","); -// fprintf(s_csvFile, "\"CPS\"\n"); - fflush(s_csvFile); } } @@ -8700,44 +8693,72 @@ void JitTimer::PrintCsvMethodStats(Compiler* comp) return; } - //fprintf(s_csvFile, "\"%s\",", methName); - //if (index != 0) + fprintf(s_csvFile, "\"%s\",", methName); + if (index != 0) { fprintf(s_csvFile, "%d,", index); } - //else - //{ - // const char* methodAssemblyName = comp->info.compCompHnd->getAssemblyName( - // comp->info.compCompHnd->getModuleAssembly(comp->info.compCompHnd->getClassModule(comp->info.compClassHnd))); - // fprintf(s_csvFile, "\"%s\",", methodAssemblyName); - //} - - + else + { + const char* methodAssemblyName = comp->info.compCompHnd->getAssemblyName( + comp->info.compCompHnd->getModuleAssembly(comp->info.compCompHnd->getClassModule(comp->info.compClassHnd))); + fprintf(s_csvFile, "\"%s\",", methodAssemblyName); + } fprintf(s_csvFile, "%u,", comp->info.compILCodeSize); fprintf(s_csvFile, "%u,", comp->fgBBcount); - + fprintf(s_csvFile, "%u,", comp->opts.MinOpts()); + fprintf(s_csvFile, "%u,", comp->optLoopCount); + fprintf(s_csvFile, "%u,", comp->optLoopsCloned); +#if FEATURE_LOOP_ALIGN #ifdef DEBUG + fprintf(s_csvFile, "%u,", comp->loopAlignCandidates); + fprintf(s_csvFile, "%u,", comp->loopsAligned); +#endif // DEBUG +#endif // FEATURE_LOOP_ALIGN + unsigned __int64 totCycles = 0; + for (int i = 0; i < PHASE_NUMBER_OF; i++) + { + if (!PhaseHasChildren[i]) + { + totCycles += m_info.m_cyclesByPhase[i]; + } + fprintf(s_csvFile, "%I64u,", m_info.m_cyclesByPhase[i]); -#define ASSERTION_STATS(name) \ - assert(comp->##name##Iter >= comp->##name##Count); \ - fprintf(s_csvFile, "%u,", comp->##name##Count); \ - fprintf(s_csvFile, "%u,", comp->##name##Iter); \ - fprintf(s_csvFile, "%d,", (comp->##name##Count == 0) ? 0 : (comp->##name##Iter / comp->##name##Count)); \ - fprintf(s_csvFile, "%u,", comp->missed##name##Count); \ - fprintf(s_csvFile, "%u,", comp->missed##name##Iter); \ - fprintf(s_csvFile, "%d,", (comp->missed##name##Count == 0) ? 0 : (comp->missed##name##Iter / comp->missed##name##Count)); \ + if ((JitConfig.JitMeasureIR() != 0) && PhaseReportsIRSize[i]) + { + fprintf(s_csvFile, "%u,", m_info.m_nodeCountAfterPhase[i]); + } + } + + comp->m_inlineStrategy->DumpCsvData(s_csvFile); + +#if TRACK_ASSERTION_STATS + +#define ASSERTION_STATS(name) \ + assert(comp->##name##Iter >= comp->##name##MatchCount); \ + fprintf(s_csvFile, "%u,", comp->##name##MatchCount); \ + fprintf(s_csvFile, "%u,", comp->##name##Iter); \ + fprintf(s_csvFile, "%u,", comp->name##MissedCount); \ + fprintf(s_csvFile, "%u,", comp->name##MissedIter); \ fprintf(s_csvFile, "%u,", comp->##name##CallCount); -ASSERTION_STATS(addAssertion) -ASSERTION_STATS(subRange) -ASSERTION_STATS(subType) -ASSERTION_STATS(equalOrNotEqua) -ASSERTION_STATS(noNull) -ASSERTION_STATS(propLclVar) -ASSERTION_STATS(propEqualOrNot) -ASSERTION_STATS(propEqualZero) -ASSERTION_STATS(propBndChk) -#endif + ASSERTION_STATS(addAssertion) + ASSERTION_STATS(subRange) + ASSERTION_STATS(subType) + ASSERTION_STATS(equalOrNotEqua) + ASSERTION_STATS(noNull) + ASSERTION_STATS(propLclVar) + ASSERTION_STATS(propEqualOrNot) + ASSERTION_STATS(propEqualZero) + ASSERTION_STATS(propBndChk) + +#endif // TRACK_ASSERTION_STATS + + fprintf(s_csvFile, "%u,", comp->info.compNativeCodeSize); + fprintf(s_csvFile, "%Iu,", comp->compInfoBlkSize); + fprintf(s_csvFile, "%Iu,", comp->compGetArenaAllocator()->getTotalBytesAllocated()); + fprintf(s_csvFile, "%I64u,", m_info.m_totalCycles); + fprintf(s_csvFile, "%f", CachedCyclesPerSecond()); fprintf(s_csvFile, "\n"); fflush(s_csvFile); } diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 07dfb17551851d..d5aa66f75b39a7 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7288,28 +7288,32 @@ class Compiler AssertionIndex optAssertionCount; // total number of assertions in the assertion table AssertionIndex optMaxAssertionCount; -#ifdef DEBUG -#define ASSERTION_VAR(name) \ +#if TRACK_ASSERTION_STATS + +#define ASSERTION_STATS_DECL_VAR(name) \ unsigned name##Iter = 0; \ - unsigned name##Count = 0; \ - unsigned missed##name##Iter = 0; \ - unsigned missed##name##Count = 0; \ + unsigned name##MatchCount = 0; \ + unsigned name##MissedIter = 0; \ + unsigned name##MissedCount = 0; \ unsigned name##CallCount = 0; -ASSERTION_VAR(addAssertion) -ASSERTION_VAR(subRange) -ASSERTION_VAR(subType) -ASSERTION_VAR(equalOrNotEqua) -ASSERTION_VAR(noNull) -ASSERTION_VAR(propLclVar) -ASSERTION_VAR(propEqualOrNot) -ASSERTION_VAR(propEqualZero) -ASSERTION_VAR(propBndChk) -ASSERTION_VAR(impliedByCopy) -ASSERTION_VAR(impliedByConst) -ASSERTION_VAR(impliedByType) +ASSERTION_STATS_DECL_VAR(addAssertion) +ASSERTION_STATS_DECL_VAR(subRange) +ASSERTION_STATS_DECL_VAR(subType) +ASSERTION_STATS_DECL_VAR(equalOrNotEqua) +ASSERTION_STATS_DECL_VAR(noNull) +ASSERTION_STATS_DECL_VAR(propLclVar) +ASSERTION_STATS_DECL_VAR(propEqualOrNot) +ASSERTION_STATS_DECL_VAR(propEqualZero) +ASSERTION_STATS_DECL_VAR(propBndChk) -#endif +#define RECORD_ASSERTION_STATS(x) x + +#else + +#define RECORD_ASSERTION_STATS(x) + +#endif // TRACK_ASSERTION_STATS struct AssertionDscKeyFuncs { diff --git a/src/coreclr/jit/jit.h b/src/coreclr/jit/jit.h index f229cae217031c..0738fe70194dea 100644 --- a/src/coreclr/jit/jit.h +++ b/src/coreclr/jit/jit.h @@ -442,10 +442,12 @@ class GlobalJitOptions #define LOOP_HOIST_STATS 1 // Collect loop hoisting stats. #define TRACK_LSRA_STATS 1 // Collect LSRA stats #define TRACK_ENREG_STATS 1 // Collect enregistration stats +#define TRACK_ASSERTION_STATS 1 // Collect assertion prop stats #else #define MEASURE_MEM_ALLOC 0 // You can set this to 1 to get memory stats in retail, as well #define LOOP_HOIST_STATS 0 // You can set this to 1 to get loop hoist stats in retail, as well #define TRACK_LSRA_STATS 0 // You can set this to 1 to get LSRA stats in retail, as well +#define TRACK_ASSERTION_STATS 0 // You can set this to 1 to get assertion prop stats in retail, as well #endif // Timing calls to clr.dll is only available under certain conditions. diff --git a/src/coreclr/jit/jithashtable.h b/src/coreclr/jit/jithashtable.h index be8285aa642801..6fa43510d0526e 100644 --- a/src/coreclr/jit/jithashtable.h +++ b/src/coreclr/jit/jithashtable.h @@ -99,8 +99,7 @@ template + typename Behavior = JitHashTableBehavior> class JitHashTable { public: @@ -236,23 +235,11 @@ class JitHashTable unsigned index = GetIndexForKey(k); - //if (BucketIndex == 13) - //{ - // unsigned hash = KeyFuncs::GetHashCode(k); - - // unsigned index = m_tableSizeInfo.magicNumberRem(hash); - // printf("hash= %d, index= %d\n", hash, index); - //} - Node* pN = m_table[index]; - int iterCount = 0; while ((pN != nullptr) && !KeyFuncs::Equals(k, pN->m_key)) { - iterCount++; pN = pN->m_next; } - - //assert(iterCount < BucketIndex); if (pN != nullptr) { if (kind == SkipIfExist) From 7aaeea0e2f03dc950034115232d7145095e22ec6 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Thu, 28 Jul 2022 18:45:19 -0700 Subject: [PATCH 28/29] Minor change --- src/coreclr/jit/assertionprop.cpp | 32 +++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index da446600c208e4..47a46471c7eed4 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -3673,14 +3673,11 @@ GenTree* Compiler::optAssertionProp_LclVar(ASSERT_VALARG_TP assertions, GenTreeL BitVecOps::Iter iter(apTraits, assertions); unsigned index = 0; -#if TRACK_ASSERTION_STATS - unsigned iterCount = 0; -#endif + RECORD_ASSERTION_STATS(unsigned iterCount = 0); while (iter.NextElem(&index)) { -#if TRACK_ASSERTION_STATS - iterCount++; -#endi + RECORD_ASSERTION_STATS(iterCount++); + AssertionIndex assertionIndex = GetAssertionIndex(index); if (assertionIndex > optAssertionCount) { @@ -3716,7 +3713,6 @@ GenTree* Compiler::optAssertionProp_LclVar(ASSERT_VALARG_TP assertions, GenTreeL } // There are no constant assertions for structs. - // OK - Then why is the check inside the for-loop for global prop? if (varTypeIsStruct(tree)) { continue; @@ -3901,10 +3897,11 @@ AssertionIndex Compiler::optGlobalAssertionIsEqualOrNotEqual(ASSERT_VALARG_TP as BitVecOps::Iter iter(apTraits, assertions); unsigned index = 0; - unsigned iterCount = 0; + RECORD_ASSERTION_STATS(unsigned iterCount = 0); + while (iter.NextElem(&index)) { - iterCount++; + RECORD_ASSERTION_STATS(iterCount++); AssertionIndex assertionIndex = GetAssertionIndex(index); if (assertionIndex > optAssertionCount) @@ -3968,10 +3965,11 @@ AssertionIndex Compiler::optGlobalAssertionIsEqualOrNotEqualZero(ASSERT_VALARG_T BitVecOps::Iter iter(apTraits, assertions); unsigned index = 0; - unsigned iterCount = 0; + RECORD_ASSERTION_STATS(unsigned iterCount = 0); + while (iter.NextElem(&index)) { - iterCount++; + RECORD_ASSERTION_STATS(iterCount++); AssertionIndex assertionIndex = GetAssertionIndex(index); if (assertionIndex > optAssertionCount) { @@ -4647,10 +4645,11 @@ AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op, // BitVecOps::Iter iter(apTraits, assertions); unsigned index = 0; - unsigned iterCount = 0; + RECORD_ASSERTION_STATS(unsigned iterCount = 0); + while (iter.NextElem(&index)) { - iterCount++; + RECORD_ASSERTION_STATS(iterCount++); AssertionIndex assertionIndex = GetAssertionIndex(index); if (assertionIndex > optAssertionCount) { @@ -4681,7 +4680,6 @@ AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op, return assertionIndex; } - RECORD_ASSERTION_STATS(noNullMissedCount++); RECORD_ASSERTION_STATS(noNullMissedIter += BitVecOps::Count(apTraits, assertions)); } @@ -4849,10 +4847,12 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree BitVecOps::Iter iter(apTraits, assertions); unsigned index = 0; - unsigned iterCount = 0; + RECORD_ASSERTION_STATS(unsigned iterCount = 0); + while (iter.NextElem(&index)) { - iterCount++; + RECORD_ASSERTION_STATS(iterCount++); + AssertionIndex assertionIndex = GetAssertionIndex(index); if (assertionIndex > optAssertionCount) { From da7fef41f48771bbbe89c9e4f12638bea0b324d2 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Fri, 29 Jul 2022 17:14:48 -0700 Subject: [PATCH 29/29] Convert from csv to summary stats --- src/coreclr/jit/assertionprop.cpp | 14 +-- src/coreclr/jit/compiler.cpp | 145 ++++++++++++++++++++---------- src/coreclr/jit/compiler.h | 66 ++++++++------ src/coreclr/jit/jit.h | 14 +-- src/coreclr/jit/jitconfigvalues.h | 3 +- 5 files changed, 153 insertions(+), 89 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 47a46471c7eed4..40379581737f1e 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -1991,7 +1991,7 @@ AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion) found = true; slowAnswer = index; RECORD_ASSERTION_STATS(addAssertionMatchCount++); - RECORD_ASSERTION_STATS(addAssertionIter += (optAssertionCount - index + 1)); + RECORD_ASSERTION_STATS(addAssertionIter += (optAssertionCount - index + 1)); break; } } @@ -2917,7 +2917,8 @@ AssertionIndex Compiler::optAssertionIsSubrange(GenTree* tree, IntegralRange ran } RECORD_ASSERTION_STATS(subRangeMissedCount++); - RECORD_ASSERTION_STATS(subRangeMissedIter += (optLocalAssertionProp ? optAssertionCount : (BitVecOps::Count(apTraits, assertions)))); + RECORD_ASSERTION_STATS(subRangeMissedIter += + (optLocalAssertionProp ? optAssertionCount : (BitVecOps::Count(apTraits, assertions)))); return NO_ASSERTION_INDEX; } @@ -2990,7 +2991,8 @@ AssertionIndex Compiler::optAssertionIsSubtype(GenTree* tree, GenTree* methodTab } RECORD_ASSERTION_STATS(subTypeMissedCount++); - RECORD_ASSERTION_STATS(subTypeMissedIter += (optLocalAssertionProp ? optAssertionCount : (BitVecOps::Count(apTraits, assertions)))); + RECORD_ASSERTION_STATS(subTypeMissedIter += + (optLocalAssertionProp ? optAssertionCount : (BitVecOps::Count(apTraits, assertions)))); return NO_ASSERTION_INDEX; } @@ -3751,7 +3753,8 @@ GenTree* Compiler::optAssertionProp_LclVar(ASSERT_VALARG_TP assertions, GenTreeL } RECORD_ASSERTION_STATS(propLclVarMissedCount++); - RECORD_ASSERTION_STATS(propLclVarMissedIter += (optLocalAssertionProp ? optAssertionCount : (BitVecOps::Count(apTraits, assertions)))); + RECORD_ASSERTION_STATS(propLclVarMissedIter += + (optLocalAssertionProp ? optAssertionCount : (BitVecOps::Count(apTraits, assertions)))); return nullptr; } @@ -3863,7 +3866,8 @@ AssertionIndex Compiler::optLocalAssertionIsEqualOrNotEqual( } RECORD_ASSERTION_STATS(equalOrNotEquaMissedCount++); - RECORD_ASSERTION_STATS(equalOrNotEquaMissedIter += (optLocalAssertionProp ? optAssertionCount : (BitVecOps::Count(apTraits, assertions)))); + RECORD_ASSERTION_STATS(equalOrNotEquaMissedIter += + (optLocalAssertionProp ? optAssertionCount : (BitVecOps::Count(apTraits, assertions)))); return NO_ASSERTION_INDEX; } diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index adb2e4686c503c..6a6737943686f4 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -1674,6 +1674,15 @@ void Compiler::compShutdown() } #endif // LOOP_HOIST_STATS +#if TRACK_ASSERTION_STATS +#ifdef DEBUG // Always display assertion stats in retail + if (JitConfig.DisplayAssertionPropStats() != 0) +#endif // DEBUG + { + PrintAggregateAssertionStats(jitstdout); + } +#endif + #if TRACK_ENREG_STATS if (JitConfig.JitEnregStats() != 0) { @@ -6036,6 +6045,10 @@ void Compiler::compCompileFinish() AddLoopHoistStats(); #endif // LOOP_HOIST_STATS +#if TRACK_ASSERTION_STATS + AddAssertionStats(); +#endif // TRACK_ASSERTION_STATS + #if MEASURE_NODE_SIZE genTreeNcntHist.record(static_cast(genNodeSizeStatsPerFunc.genTreeNodeCnt)); genTreeNsizHist.record(static_cast(genNodeSizeStatsPerFunc.genTreeNodeSize)); @@ -6450,12 +6463,12 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, #if TRACK_ASSERTION_STATS -#define ASSERTION_STATS_ZERO(name) \ - name##Iter = 0; \ - name##MatchCount = 0; \ - name##MissedIter = 0; \ - name##MissedCount = 0; \ - name##CallCount = 0; +#define ASSERTION_STATS_ZERO(name) \ + name##Iter = 0; \ + name##MatchCount = 0; \ + name##MissedIter = 0; \ + name##MissedCount = 0; \ + name##CallCount = 0; ASSERTION_STATS_ZERO(addAssertion) ASSERTION_STATS_ZERO(subRange) @@ -8628,27 +8641,6 @@ void JitTimer::PrintCsvHeader() InlineStrategy::DumpCsvHeader(s_csvFile); -#if TRACK_ASSERTION_STATS - -#define ASSERTION_TITLE(name) \ - fprintf(s_csvFile, "\""##name##"Match\","); \ - fprintf(s_csvFile, "\""##name##"Iter\","); \ - fprintf(s_csvFile, "\""##name##"MissedCount\","); \ - fprintf(s_csvFile, "\""##name##"MissedIter\","); \ - fprintf(s_csvFile, "\""##name##"CallCount\","); - - ASSERTION_TITLE("AddAssertion") - ASSERTION_TITLE("SubType") - ASSERTION_TITLE("SubRange") - ASSERTION_TITLE("EqualOrNotEqual") - ASSERTION_TITLE("NoNull") - ASSERTION_TITLE("PropLclVar") - ASSERTION_TITLE("PropEqualOrNot") - ASSERTION_TITLE("PropEqualZero") - ASSERTION_TITLE("PropBndChk") - -#endif // TRACK_ASSERTION_STATS - fprintf(s_csvFile, "\"Executable Code Bytes\","); fprintf(s_csvFile, "\"GC Info Bytes\","); fprintf(s_csvFile, "\"Total Bytes Allocated\","); @@ -8732,28 +8724,6 @@ void JitTimer::PrintCsvMethodStats(Compiler* comp) comp->m_inlineStrategy->DumpCsvData(s_csvFile); -#if TRACK_ASSERTION_STATS - -#define ASSERTION_STATS(name) \ - assert(comp->##name##Iter >= comp->##name##MatchCount); \ - fprintf(s_csvFile, "%u,", comp->##name##MatchCount); \ - fprintf(s_csvFile, "%u,", comp->##name##Iter); \ - fprintf(s_csvFile, "%u,", comp->name##MissedCount); \ - fprintf(s_csvFile, "%u,", comp->name##MissedIter); \ - fprintf(s_csvFile, "%u,", comp->##name##CallCount); - - ASSERTION_STATS(addAssertion) - ASSERTION_STATS(subRange) - ASSERTION_STATS(subType) - ASSERTION_STATS(equalOrNotEqua) - ASSERTION_STATS(noNull) - ASSERTION_STATS(propLclVar) - ASSERTION_STATS(propEqualOrNot) - ASSERTION_STATS(propEqualZero) - ASSERTION_STATS(propBndChk) - -#endif // TRACK_ASSERTION_STATS - fprintf(s_csvFile, "%u,", comp->info.compNativeCodeSize); fprintf(s_csvFile, "%Iu,", comp->compInfoBlkSize); fprintf(s_csvFile, "%Iu,", comp->compGetArenaAllocator()->getTotalBytesAllocated()); @@ -8846,6 +8816,83 @@ void Compiler::PrintPerMethodLoopHoistStats() } #endif // LOOP_HOIST_STATS +#if TRACK_ASSERTION_STATS +// Static fields. +CritSecObject Compiler::s_assertionStatsLock; // Default constructor. + +#define ASSERTION_STATS_DEF_VAR(name) \ + unsigned Compiler::s_##name##Iter = 0; \ + unsigned Compiler::s_##name##MatchCount = 0; \ + unsigned Compiler::s_##name##MissedIter = 0; \ + unsigned Compiler::s_##name##MissedCount = 0; \ + unsigned Compiler::s_##name##CallCount = 0; + +ASSERTION_STATS_DEF_VAR(addAssertion) +ASSERTION_STATS_DEF_VAR(subRange) +ASSERTION_STATS_DEF_VAR(subType) +ASSERTION_STATS_DEF_VAR(equalOrNotEqua) +ASSERTION_STATS_DEF_VAR(noNull) +ASSERTION_STATS_DEF_VAR(propLclVar) +ASSERTION_STATS_DEF_VAR(propEqualOrNot) +ASSERTION_STATS_DEF_VAR(propEqualZero) +ASSERTION_STATS_DEF_VAR(propBndChk) + +#undef ASSERTION_STATS_DEF_VAR + +// static +void Compiler::PrintAggregateAssertionStats(FILE* f) +{ + fprintf(f, "\n"); + fprintf(f, "---------------------------------------------------\n"); + fprintf(f, "Assertion stats\n"); + fprintf(f, "---------------------------------------------------\n"); + +#define ASSERTION_TITLE(name, value) \ + fprintf(f, "---" name "---\n"); \ + fprintf(f, name "Match: %u\n", s_##value##MatchCount); \ + fprintf(f, name "Iter: %u\n", s_##value##Iter); \ + fprintf(f, name "MissedIter: %u\n", s_##value##MissedIter); \ + fprintf(f, name "MissedCount: %u\n", s_##value##MissedCount); \ + fprintf(f, name "CallCount: %u\n", s_##value##CallCount); \ + fprintf(f, "\n"); + + ASSERTION_TITLE("AddAssertion", addAssertion) + ASSERTION_TITLE("SubType", subType) + ASSERTION_TITLE("SubRange", subRange) + ASSERTION_TITLE("EqualOrNotEqual", equalOrNotEqua) + ASSERTION_TITLE("NoNull", noNull) + ASSERTION_TITLE("PropLclVar", propLclVar) + ASSERTION_TITLE("PropEqualOrNot", propEqualOrNot) + ASSERTION_TITLE("PropEqualZero", propEqualZero) + ASSERTION_TITLE("PropBndChk", propBndChk) +} + +void Compiler::AddAssertionStats() +{ + CritSecHolder statsLock(s_assertionStatsLock); + +#define INCREMENT_STATS(name) \ + s_##name##Iter += name##Iter; \ + s_##name##MatchCount += name##MatchCount; \ + s_##name##MissedIter += name##MissedIter; \ + s_##name##MissedCount += name##MissedCount; \ + s_##name##CallCount += name##CallCount; + + INCREMENT_STATS(addAssertion) + INCREMENT_STATS(subRange) + INCREMENT_STATS(subType) + INCREMENT_STATS(equalOrNotEqua) + INCREMENT_STATS(noNull) + INCREMENT_STATS(propLclVar) + INCREMENT_STATS(propEqualOrNot) + INCREMENT_STATS(propEqualZero) + INCREMENT_STATS(propBndChk) + +#undef INCREMENT_STATS +} + +#endif + //------------------------------------------------------------------------ // RecordStateAtEndOfInlining: capture timing data (if enabled) after // inlining as completed. diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index d5aa66f75b39a7..c4bddc3eae5781 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7288,33 +7288,6 @@ class Compiler AssertionIndex optAssertionCount; // total number of assertions in the assertion table AssertionIndex optMaxAssertionCount; -#if TRACK_ASSERTION_STATS - -#define ASSERTION_STATS_DECL_VAR(name) \ - unsigned name##Iter = 0; \ - unsigned name##MatchCount = 0; \ - unsigned name##MissedIter = 0; \ - unsigned name##MissedCount = 0; \ - unsigned name##CallCount = 0; - -ASSERTION_STATS_DECL_VAR(addAssertion) -ASSERTION_STATS_DECL_VAR(subRange) -ASSERTION_STATS_DECL_VAR(subType) -ASSERTION_STATS_DECL_VAR(equalOrNotEqua) -ASSERTION_STATS_DECL_VAR(noNull) -ASSERTION_STATS_DECL_VAR(propLclVar) -ASSERTION_STATS_DECL_VAR(propEqualOrNot) -ASSERTION_STATS_DECL_VAR(propEqualZero) -ASSERTION_STATS_DECL_VAR(propBndChk) - -#define RECORD_ASSERTION_STATS(x) x - -#else - -#define RECORD_ASSERTION_STATS(x) - -#endif // TRACK_ASSERTION_STATS - struct AssertionDscKeyFuncs { static bool Equals(const AssertionDsc& x, const AssertionDsc& y) @@ -10046,6 +10019,45 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX static void PrintAggregateLoopHoistStats(FILE* f); #endif // LOOP_HOIST_STATS +#if TRACK_ASSERTION_STATS + + static CritSecObject s_assertionStatsLock; // This lock protects the data structures below. + +#define ASSERTION_STATS_DECL_VAR(name) \ + unsigned name##Iter = 0; \ + unsigned name##MatchCount = 0; \ + unsigned name##MissedIter = 0; \ + unsigned name##MissedCount = 0; \ + unsigned name##CallCount = 0; \ + static unsigned s_##name##Iter; \ + static unsigned s_##name##MatchCount; \ + static unsigned s_##name##MissedIter; \ + static unsigned s_##name##MissedCount; \ + static unsigned s_##name##CallCount; + + ASSERTION_STATS_DECL_VAR(addAssertion) + ASSERTION_STATS_DECL_VAR(subRange) + ASSERTION_STATS_DECL_VAR(subType) + ASSERTION_STATS_DECL_VAR(equalOrNotEqua) + ASSERTION_STATS_DECL_VAR(noNull) + ASSERTION_STATS_DECL_VAR(propLclVar) + ASSERTION_STATS_DECL_VAR(propEqualOrNot) + ASSERTION_STATS_DECL_VAR(propEqualZero) + ASSERTION_STATS_DECL_VAR(propBndChk) + +#undef ASSERTION_STATS_DECL_VAR + +#define RECORD_ASSERTION_STATS(x) x + + void AddAssertionStats(); + static void PrintAggregateAssertionStats(FILE* f); + +#else + +#define RECORD_ASSERTION_STATS(x) + +#endif // TRACK_ASSERTION_STATS + #if TRACK_ENREG_STATS class EnregisterStats { diff --git a/src/coreclr/jit/jit.h b/src/coreclr/jit/jit.h index 0738fe70194dea..efd7df2a3ee3dc 100644 --- a/src/coreclr/jit/jit.h +++ b/src/coreclr/jit/jit.h @@ -438,15 +438,15 @@ class GlobalJitOptions #define VERBOSE_VERIFY 0 // Dump additional information when verifying code. Useful to debug verification bugs. #ifdef DEBUG -#define MEASURE_MEM_ALLOC 1 // Collect memory allocation stats. -#define LOOP_HOIST_STATS 1 // Collect loop hoisting stats. -#define TRACK_LSRA_STATS 1 // Collect LSRA stats -#define TRACK_ENREG_STATS 1 // Collect enregistration stats +#define MEASURE_MEM_ALLOC 1 // Collect memory allocation stats. +#define LOOP_HOIST_STATS 1 // Collect loop hoisting stats. +#define TRACK_LSRA_STATS 1 // Collect LSRA stats +#define TRACK_ENREG_STATS 1 // Collect enregistration stats #define TRACK_ASSERTION_STATS 1 // Collect assertion prop stats #else -#define MEASURE_MEM_ALLOC 0 // You can set this to 1 to get memory stats in retail, as well -#define LOOP_HOIST_STATS 0 // You can set this to 1 to get loop hoist stats in retail, as well -#define TRACK_LSRA_STATS 0 // You can set this to 1 to get LSRA stats in retail, as well +#define MEASURE_MEM_ALLOC 0 // You can set this to 1 to get memory stats in retail, as well +#define LOOP_HOIST_STATS 0 // You can set this to 1 to get loop hoist stats in retail, as well +#define TRACK_LSRA_STATS 0 // You can set this to 1 to get LSRA stats in retail, as well #define TRACK_ASSERTION_STATS 0 // You can set this to 1 to get assertion prop stats in retail, as well #endif diff --git a/src/coreclr/jit/jitconfigvalues.h b/src/coreclr/jit/jitconfigvalues.h index 893cdbb51831fb..243bb3b92f4fbf 100644 --- a/src/coreclr/jit/jitconfigvalues.h +++ b/src/coreclr/jit/jitconfigvalues.h @@ -25,7 +25,8 @@ CONFIG_INTEGER(DebugBreakOnVerificationFailure, W("DebugBreakOnVerificationFailu CONFIG_INTEGER(DiffableDasm, W("JitDiffableDasm"), 0) // Make the disassembly diff-able CONFIG_INTEGER(JitDasmWithAddress, W("JitDasmWithAddress"), 0) // Print the process address next to each instruction of // the disassembly -CONFIG_INTEGER(DisplayLoopHoistStats, W("JitLoopHoistStats"), 0) // Display JIT loop hoisting statistics +CONFIG_INTEGER(DisplayLoopHoistStats, W("JitLoopHoistStats"), 0) // Display JIT loop hoisting statistics +CONFIG_INTEGER(DisplayAssertionPropStats, W("JitAssertionPropStats"), 0) // Display JIT assertion statistics CONFIG_INTEGER(DisplayLsraStats, W("JitLsraStats"), 0) // Display JIT Linear Scan Register Allocator statistics // If set to "1", display the stats in textual format. // If set to "2", display the stats in csv format.