From: mikedn Date: Sat, 25 Mar 2017 14:45:10 +0000 (+0200) Subject: Some BitVecOps improvements (dotnet/coreclr#10437) X-Git-Tag: submit/tizen/20210909.063632~11030^2~7551 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=71b844115d596231b5ea8c0c2112dee04fb16e0d;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Some BitVecOps improvements (dotnet/coreclr#10437) * Avoid virtual calls when allocating bitvectors * Use specialized BitVecOps when possible * Avoid unnecessary bitvector copying * Cleanup CSE_DataFlow Commit migrated from https://github.com/dotnet/coreclr/commit/6d5ce09e13a3ff43d592cc67c04e026a12cce008 --- diff --git a/src/coreclr/src/jit/assertionprop.cpp b/src/coreclr/src/jit/assertionprop.cpp index 0c5b8f3..b804b96 100644 --- a/src/coreclr/src/jit/assertionprop.cpp +++ b/src/coreclr/src/jit/assertionprop.cpp @@ -511,7 +511,7 @@ ASSERT_TP& Compiler::GetAssertionDep(unsigned lclNum) ExpandArray& dep = *optAssertionDep; if (dep[lclNum] == nullptr) { - dep[lclNum] = optNewEmptyAssertSet(); + dep[lclNum] = BitVecOps::MakeEmpty(apTraits); } return dep[lclNum]; } @@ -524,10 +524,7 @@ ASSERT_TP& Compiler::GetAssertionDep(unsigned lclNum) void Compiler::optAssertionTraitsInit(AssertionIndex assertionCount) { apTraits = new (getAllocator()) BitVecTraits(assertionCount, this); - apFull = BitVecOps::UninitVal(); - apEmpty = BitVecOps::UninitVal(); - BitVecOps::AssignNoCopy(apTraits, apFull, BitVecOps::MakeFull(apTraits)); - BitVecOps::AssignNoCopy(apTraits, apEmpty, BitVecOps::MakeEmpty(apTraits)); + apFull = BitVecOps::MakeFull(apTraits); } /***************************************************************************** @@ -792,12 +789,7 @@ void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex asse if (assertionIndex > 0) { printf(" index=#%02u, mask=", assertionIndex); - - // This is an hack to reuse a known empty set in order to display - // a single bit mask. - BitVecOps::AddElemD(apTraits, apEmpty, assertionIndex - 1); - printf("%s", BitVecOps::ToString(apTraits, apEmpty)); - BitVecOps::RemoveElemD(apTraits, apEmpty, assertionIndex - 1); + printf("%s", BitVecOps::ToString(apTraits, BitVecOps::MakeSingleton(apTraits, assertionIndex - 1))); } printf("\n"); } @@ -1494,7 +1486,7 @@ void Compiler::optAddVnAssertionMapping(ValueNum vn, AssertionIndex index) ASSERT_TP cur; if (!optValueNumToAsserts->Lookup(vn, &cur)) { - cur = optNewEmptyAssertSet(); + cur = BitVecOps::MakeEmpty(apTraits); optValueNumToAsserts->Set(vn, cur); } BitVecOps::AddElemD(apTraits, cur, index - 1); @@ -4397,15 +4389,8 @@ public: JITDUMP("AssertionPropCallback::EndMerge : BB%02d in -> %s\n\n", block->bbNum, BitVecOps::ToString(apTraits, block->bbAssertionIn)); - // PERF: eliminate this tmp by passing in a OperationTree (AST) to the bitset, - // so the expr tree is operated on a single bit level. See "expression templates." - ASSERT_TP tmp = BitVecOps::MakeCopy(apTraits, block->bbAssertionIn); - BitVecOps::UnionD(apTraits, tmp, block->bbAssertionGen); - BitVecOps::IntersectionD(apTraits, block->bbAssertionOut, tmp); - - BitVecOps::Assign(apTraits, tmp, block->bbAssertionIn); - BitVecOps::UnionD(apTraits, tmp, mJumpDestGen[block->bbNum]); - BitVecOps::IntersectionD(apTraits, mJumpDestOut[block->bbNum], tmp); + BitVecOps::DataFlowD(apTraits, block->bbAssertionOut, block->bbAssertionGen, block->bbAssertionIn); + BitVecOps::DataFlowD(apTraits, mJumpDestOut[block->bbNum], mJumpDestGen[block->bbNum], block->bbAssertionIn); bool changed = (!BitVecOps::Equal(apTraits, preMergeOut, block->bbAssertionOut) || !BitVecOps::Equal(apTraits, preMergeJumpDestOut, mJumpDestOut[block->bbNum])); @@ -4430,16 +4415,6 @@ public: } }; -ASSERT_VALRET_TP Compiler::optNewFullAssertSet() -{ - return BitVecOps::MakeCopy(apTraits, apFull); -} - -ASSERT_VALRET_TP Compiler::optNewEmptyAssertSet() -{ - return BitVecOps::MakeCopy(apTraits, apEmpty); -} - /***************************************************************************** * * Compute the assertions generated by each block. @@ -4553,7 +4528,7 @@ ASSERT_TP* Compiler::optInitAssertionDataflowFlags() // apFull (i.e. all possible bits set), we need to set the bits only for valid // assertions (note that at this point we are not creating any new assertions). // Also note that assertion indices start from 1. - ASSERT_TP apValidFull = optNewEmptyAssertSet(); + ASSERT_TP apValidFull = BitVecOps::MakeEmpty(apTraits); for (int i = 1; i <= optAssertionCount; i++) { BitVecOps::AddElemD(apTraits, apValidFull, i - 1); @@ -4567,20 +4542,21 @@ ASSERT_TP* Compiler::optInitAssertionDataflowFlags() // edges. for (BasicBlock* block = fgFirstBB; block; block = block->bbNext) { - block->bbAssertionIn = optNewEmptyAssertSet(); - if (!bbIsHandlerBeg(block)) + if (bbIsHandlerBeg(block)) + { + block->bbAssertionIn = BitVecOps::MakeEmpty(apTraits); + } + else { - BitVecOps::Assign(apTraits, block->bbAssertionIn, apValidFull); + block->bbAssertionIn = BitVecOps::MakeCopy(apTraits, apValidFull); } - block->bbAssertionGen = optNewEmptyAssertSet(); - block->bbAssertionOut = optNewEmptyAssertSet(); - BitVecOps::Assign(apTraits, block->bbAssertionOut, apValidFull); - jumpDestOut[block->bbNum] = optNewEmptyAssertSet(); - BitVecOps::Assign(apTraits, jumpDestOut[block->bbNum], apValidFull); + block->bbAssertionGen = BitVecOps::MakeEmpty(apTraits); + block->bbAssertionOut = BitVecOps::MakeCopy(apTraits, apValidFull); + jumpDestOut[block->bbNum] = BitVecOps::MakeCopy(apTraits, apValidFull); } // Compute the data flow values for all tracked expressions // IN and OUT never change for the initial basic block B1 - BitVecOps::Assign(apTraits, fgFirstBB->bbAssertionIn, apEmpty); + BitVecOps::ClearD(apTraits, fgFirstBB->bbAssertionIn); return jumpDestOut; } @@ -5076,10 +5052,12 @@ void Compiler::optAssertionPropMain() } #endif // DEBUG + ASSERT_TP assertions = BitVecOps::MakeEmpty(apTraits); + // Perform assertion propagation (and constant folding) for (BasicBlock* block = fgFirstBB; block; block = block->bbNext) { - ASSERT_TP assertions = BitVecOps::MakeCopy(apTraits, block->bbAssertionIn); + BitVecOps::Assign(apTraits, assertions, block->bbAssertionIn); // TODO-Review: EH successor/predecessor iteration seems broken. // SELF_HOST_TESTS_ARM\jit\Directed\ExcepFilters\fault\fault.exe diff --git a/src/coreclr/src/jit/bitset.cpp b/src/coreclr/src/jit/bitset.cpp index 90ef253..785061f 100644 --- a/src/coreclr/src/jit/bitset.cpp +++ b/src/coreclr/src/jit/bitset.cpp @@ -98,9 +98,9 @@ void BitSetSupport::RunTests(Env env) class TestBitSetTraits { public: - static IAllocator* GetAllocator(IAllocator* alloc) + static void* Alloc(IAllocator* alloc, size_t byteSize) { - return alloc; + return alloc->Alloc(byteSize); } static unsigned GetSize(IAllocator* alloc) { diff --git a/src/coreclr/src/jit/bitsetasshortlong.h b/src/coreclr/src/jit/bitsetasshortlong.h index ec437e1..163cb36 100644 --- a/src/coreclr/src/jit/bitsetasshortlong.h +++ b/src/coreclr/src/jit/bitsetasshortlong.h @@ -38,6 +38,7 @@ private: static BitSetShortLongRep MakeCopyLong(Env env, BitSetShortLongRep bs); static bool IsEmptyLong(Env env, BitSetShortLongRep bs); static unsigned CountLong(Env env, BitSetShortLongRep bs); + static bool IsEmptyUnionLong(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2); static void UnionDLong(Env env, BitSetShortLongRep& bs1, BitSetShortLongRep bs2); static void DiffDLong(Env env, BitSetShortLongRep& bs1, BitSetShortLongRep bs2); static void AddElemDLong(Env env, BitSetShortLongRep& bs, unsigned i); @@ -51,6 +52,15 @@ private: static bool IsSubsetLong(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2); static bool IsEmptyIntersectionLong(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2); static void IntersectionDLong(Env env, BitSetShortLongRep& bs1, BitSetShortLongRep bs2); + static void DataFlowDLong(Env env, + BitSetShortLongRep& out, + const BitSetShortLongRep gen, + const BitSetShortLongRep in); + static void LivenessDLong(Env env, + BitSetShortLongRep& in, + const BitSetShortLongRep def, + const BitSetShortLongRep use, + const BitSetShortLongRep out); #ifdef DEBUG static const char* ToStringLong(Env env, BitSetShortLongRep bs); #endif @@ -176,6 +186,18 @@ public: } } + static bool IsEmptyUnion(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2) + { + if (IsShort(env)) + { + return (((size_t)bs1) | ((size_t)bs2)) == 0; + } + else + { + return IsEmptyUnionLong(env, bs1, bs2); + } + } + static void UnionD(Env env, BitSetShortLongRep& bs1, BitSetShortLongRep bs2) { if (IsShort(env)) @@ -299,6 +321,34 @@ public: } } + static void DataFlowD(Env env, BitSetShortLongRep& out, const BitSetShortLongRep gen, const BitSetShortLongRep in) + { + if (IsShort(env)) + { + (size_t&)out = (size_t)out & ((size_t)gen | (size_t)in); + } + else + { + DataFlowDLong(env, out, gen, in); + } + } + + static void LivenessD(Env env, + BitSetShortLongRep& in, + const BitSetShortLongRep def, + const BitSetShortLongRep use, + const BitSetShortLongRep out) + { + if (IsShort(env)) + { + (size_t&)in = (size_t)use | ((size_t)out & ~(size_t)def); + } + else + { + LivenessDLong(env, in, def, use, out); + } + } + static bool IsSubset(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2) { if (IsShort(env)) @@ -332,14 +382,13 @@ public: if (IsShort(env)) { assert(sizeof(BitSetShortLongRep) == sizeof(size_t)); - IAllocator* alloc = BitSetTraits::GetDebugOnlyAllocator(env); - const int CharsForSizeT = sizeof(size_t) * 2; - char* res = nullptr; - const int ShortAllocSize = CharsForSizeT + 4; - res = (char*)alloc->Alloc(ShortAllocSize); - size_t bits = (size_t)bs; - unsigned remaining = ShortAllocSize; - char* ptr = res; + const int CharsForSizeT = sizeof(size_t) * 2; + char* res = nullptr; + const int ShortAllocSize = CharsForSizeT + 4; + res = (char*)BitSetTraits::DebugAlloc(env, ShortAllocSize); + size_t bits = (size_t)bs; + unsigned remaining = ShortAllocSize; + char* ptr = res; if (sizeof(size_t) == sizeof(int64_t)) { sprintf_s(ptr, remaining, "%016llX", bits); @@ -629,7 +678,7 @@ BitSetShortLongRep BitSetOps 1); // Or else would not require an array. - return (BitSetShortLongRep)(BitSetTraits::GetAllocator(env)->Alloc(len * sizeof(size_t))); + return (BitSetShortLongRep)(BitSetTraits::Alloc(env, len * sizeof(size_t))); } template @@ -641,7 +690,7 @@ BitSetShortLongRep BitSetOps 1); // Or else would not require an array. - BitSetShortLongRep res = (BitSetShortLongRep)(BitSetTraits::GetAllocator(env)->Alloc(len * sizeof(size_t))); + BitSetShortLongRep res = (BitSetShortLongRep)(BitSetTraits::Alloc(env, len * sizeof(size_t))); for (unsigned i = 0; i < len; i++) { res[i] = 0; @@ -658,7 +707,7 @@ BitSetShortLongRep BitSetOps 1); // Or else would not require an array. - BitSetShortLongRep res = (BitSetShortLongRep)(BitSetTraits::GetAllocator(env)->Alloc(len * sizeof(size_t))); + BitSetShortLongRep res = (BitSetShortLongRep)(BitSetTraits::Alloc(env, len * sizeof(size_t))); for (unsigned i = 0; i < len - 1; i++) { res[i] = size_t(-1); @@ -722,6 +771,59 @@ template bool BitSetOps::IsEmptyUnionLong(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2) +{ + assert(!IsShort(env)); + unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t)); + for (unsigned i = 0; i < len; i++) + { + if ((bs1[i] | bs2[i]) != 0) + { + return false; + } + } + return true; +} + +template +void BitSetOps::DataFlowDLong(Env env, + BitSetShortLongRep& out, + const BitSetShortLongRep gen, + const BitSetShortLongRep in) +{ + assert(!IsShort(env)); + unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t)); + for (unsigned i = 0; i < len; i++) + { + out[i] = out[i] & (gen[i] | in[i]); + } +} + +template +void BitSetOps::LivenessDLong(Env env, + BitSetShortLongRep& in, + const BitSetShortLongRep def, + const BitSetShortLongRep use, + const BitSetShortLongRep out) +{ + assert(!IsShort(env)); + unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t)); + for (unsigned i = 0; i < len; i++) + { + in[i] = use[i] | (out[i] & ~def[i]); + } +} + +template +bool BitSetOps::EqualLong(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2) { assert(!IsShort(env)); @@ -762,13 +864,12 @@ const char* BitSetOps::ToStringLong(Env env, BitSetShortLongRep bs) { assert(!IsShort(env)); - unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t)); - const int CharsForSizeT = sizeof(size_t) * 2; - unsigned allocSz = len * CharsForSizeT + 4; - unsigned remaining = allocSz; - IAllocator* alloc = BitSetTraits::GetDebugOnlyAllocator(env); - char* res = (char*)alloc->Alloc(allocSz); - char* temp = res; + unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t)); + const int CharsForSizeT = sizeof(size_t) * 2; + unsigned allocSz = len * CharsForSizeT + 4; + unsigned remaining = allocSz; + char* res = (char*)BitSetTraits::DebugAlloc(env, allocSz); + char* temp = res; for (unsigned i = len; 0 < i; i--) { size_t bits = bs[i - 1]; diff --git a/src/coreclr/src/jit/codegencommon.cpp b/src/coreclr/src/jit/codegencommon.cpp index 71d27be..a28ce2c 100644 --- a/src/coreclr/src/jit/codegencommon.cpp +++ b/src/coreclr/src/jit/codegencommon.cpp @@ -1100,9 +1100,9 @@ void Compiler::compChangeLife(VARSET_VALARG_TP newLife DEBUGARG(GenTreePtr tree) /* Can't simultaneously become live and dead at the same time */ // (deadSet UNION bornSet) != EMPTY - noway_assert(!VarSetOps::IsEmpty(this, VarSetOps::Union(this, deadSet, bornSet))); + noway_assert(!VarSetOps::IsEmptyUnion(this, deadSet, bornSet)); // (deadSet INTERSECTION bornSet) == EMPTY - noway_assert(VarSetOps::IsEmpty(this, VarSetOps::Intersection(this, deadSet, bornSet))); + noway_assert(VarSetOps::IsEmptyIntersection(this, deadSet, bornSet)); #ifdef LEGACY_BACKEND // In the LEGACY_BACKEND case, we only consider variables that are fully enregisterd diff --git a/src/coreclr/src/jit/compiler.h b/src/coreclr/src/jit/compiler.h index 3099c44..98e9fb8 100644 --- a/src/coreclr/src/jit/compiler.h +++ b/src/coreclr/src/jit/compiler.h @@ -5418,7 +5418,6 @@ protected: // Keeps tracked cse indices BitVecTraits* cseTraits; EXPSET_TP cseFull; - EXPSET_TP cseEmpty; /* Generic list of nodes - used by the CSE logic */ @@ -5691,7 +5690,6 @@ public: // Data structures for assertion prop BitVecTraits* apTraits; ASSERT_TP apFull; - ASSERT_TP apEmpty; enum optAssertionKind { @@ -6060,9 +6058,6 @@ public: void optImpliedByCopyAssertion(AssertionDsc* copyAssertion, AssertionDsc* depAssertion, ASSERT_TP& result); void optImpliedByConstAssertion(AssertionDsc* curAssertion, ASSERT_TP& result); - ASSERT_VALRET_TP optNewFullAssertSet(); - ASSERT_VALRET_TP optNewEmptyAssertSet(); - #ifdef DEBUG void optPrintAssertion(AssertionDsc* newAssertion, AssertionIndex assertionIndex = 0); void optDebugCheckAssertion(AssertionDsc* assertion); diff --git a/src/coreclr/src/jit/compilerbitsettraits.h b/src/coreclr/src/jit/compilerbitsettraits.h index 4365c51..d0436f4 100644 --- a/src/coreclr/src/jit/compilerbitsettraits.h +++ b/src/coreclr/src/jit/compilerbitsettraits.h @@ -22,10 +22,10 @@ class CompAllocBitSetTraits { public: - static inline IAllocator* GetAllocator(class Compiler* comp); + static inline void* Alloc(Compiler* comp, size_t byteSize); #ifdef DEBUG - static inline IAllocator* GetDebugOnlyAllocator(class Compiler* comp); + static inline void* DebugAlloc(Compiler* comp, size_t byteSize); #endif // DEBUG }; @@ -112,10 +112,10 @@ public: { } - static inline IAllocator* GetAllocator(BitVecTraits* b); + static inline void* Alloc(BitVecTraits* b, size_t byteSize); #ifdef DEBUG - static inline IAllocator* GetDebugOnlyAllocator(BitVecTraits* b); + static inline void* DebugAlloc(BitVecTraits* b, size_t byteSize); #endif // DEBUG static inline unsigned GetSize(BitVecTraits* b); diff --git a/src/coreclr/src/jit/compilerbitsettraits.hpp b/src/coreclr/src/jit/compilerbitsettraits.hpp index e2ba2f8..be30564 100644 --- a/src/coreclr/src/jit/compilerbitsettraits.hpp +++ b/src/coreclr/src/jit/compilerbitsettraits.hpp @@ -15,16 +15,16 @@ /////////////////////////////////////////////////////////////////////////////// // static -IAllocator* CompAllocBitSetTraits::GetAllocator(Compiler* comp) +void* CompAllocBitSetTraits::Alloc(Compiler* comp, size_t byteSize) { - return comp->getAllocatorBitset(); + return comp->compGetMem(byteSize, CMK_bitset); } #ifdef DEBUG // static -IAllocator* CompAllocBitSetTraits::GetDebugOnlyAllocator(Compiler* comp) +void* CompAllocBitSetTraits::DebugAlloc(Compiler* comp, size_t byteSize) { - return comp->getAllocatorDebugOnly(); + return comp->compGetMem(byteSize, CMK_DebugOnly); } #endif // DEBUG @@ -139,16 +139,16 @@ BitSetSupport::BitSetOpCounter* BasicBlockBitSetTraits::GetOpCounter(Compiler* c /////////////////////////////////////////////////////////////////////////////// // static -IAllocator* BitVecTraits::GetAllocator(BitVecTraits* b) +void* BitVecTraits::Alloc(BitVecTraits* b, size_t byteSize) { - return b->comp->getAllocatorBitset(); + return b->comp->compGetMem(byteSize, CMK_bitset); } #ifdef DEBUG // static -IAllocator* BitVecTraits::GetDebugOnlyAllocator(BitVecTraits* b) +void* BitVecTraits::DebugAlloc(BitVecTraits* b, size_t byteSize) { - return b->comp->getAllocatorDebugOnly(); + return b->comp->compGetMem(byteSize, CMK_DebugOnly); } #endif // DEBUG diff --git a/src/coreclr/src/jit/liveness.cpp b/src/coreclr/src/jit/liveness.cpp index c666318..47950ae 100644 --- a/src/coreclr/src/jit/liveness.cpp +++ b/src/coreclr/src/jit/liveness.cpp @@ -1189,9 +1189,7 @@ class LiveVarAnalysis } /* Compute the 'm_liveIn' set */ - VarSetOps::Assign(m_compiler, m_liveIn, m_liveOut); - VarSetOps::DiffD(m_compiler, m_liveIn, block->bbVarDef); - VarSetOps::UnionD(m_compiler, m_liveIn, block->bbVarUse); + VarSetOps::LivenessD(m_compiler, m_liveIn, block->bbVarDef, block->bbVarUse, m_liveOut); // Even if block->bbMemoryDef is set, we must assume that it doesn't kill memory liveness from m_memoryLiveOut, // since (without proof otherwise) the use and def may touch different memory at run-time. @@ -1218,12 +1216,8 @@ class LiveVarAnalysis noway_assert(block->bbFlags & BBF_INTERNAL); - liveInChanged = - !VarSetOps::Equal(m_compiler, VarSetOps::Intersection(m_compiler, block->bbLiveIn, m_liveIn), - m_liveIn); - if (liveInChanged || - !VarSetOps::Equal(m_compiler, VarSetOps::Intersection(m_compiler, block->bbLiveOut, m_liveOut), - m_liveOut)) + liveInChanged = !VarSetOps::IsSubset(m_compiler, m_liveIn, block->bbLiveIn); + if (liveInChanged || !VarSetOps::IsSubset(m_compiler, m_liveOut, block->bbLiveOut)) { #ifdef DEBUG if (m_compiler->verbose) @@ -1834,7 +1828,7 @@ VARSET_VALRET_TP Compiler::fgComputeLife(VARSET_VALARG_TP lifeArg, VARSET_TP VARSET_INIT(this, keepAliveVars, volatileVars); VarSetOps::UnionD(this, keepAliveVars, compCurBB->bbScope); // Don't kill vars in scope - noway_assert(VarSetOps::Equal(this, VarSetOps::Intersection(this, keepAliveVars, life), keepAliveVars)); + noway_assert(VarSetOps::IsSubset(this, keepAliveVars, life)); noway_assert(compCurStmt->gtOper == GT_STMT); noway_assert(endNode || (startNode == compCurStmt->gtStmt.gtStmtExpr)); @@ -1882,7 +1876,7 @@ VARSET_VALRET_TP Compiler::fgComputeLifeLIR(VARSET_VALARG_TP lifeArg, BasicBlock VARSET_TP VARSET_INIT(this, keepAliveVars, volatileVars); VarSetOps::UnionD(this, keepAliveVars, block->bbScope); // Don't kill vars in scope - noway_assert(VarSetOps::Equal(this, VarSetOps::Intersection(this, keepAliveVars, life), keepAliveVars)); + noway_assert(VarSetOps::IsSubset(this, keepAliveVars, life)); LIR::Range& blockRange = LIR::AsRange(block); GenTree* firstNonPhiNode = blockRange.FirstNonPhiNode(); @@ -2997,7 +2991,7 @@ void Compiler::fgInterBlockLocalVarLiveness() // which may expose more dead stores. fgLocalVarLivenessChanged = true; - noway_assert(VarSetOps::Equal(this, VarSetOps::Intersection(this, life, block->bbLiveIn), life)); + noway_assert(VarSetOps::IsSubset(this, life, block->bbLiveIn)); /* set the new bbLiveIn */ diff --git a/src/coreclr/src/jit/optcse.cpp b/src/coreclr/src/jit/optcse.cpp index 519e31f..41aad40 100644 --- a/src/coreclr/src/jit/optcse.cpp +++ b/src/coreclr/src/jit/optcse.cpp @@ -321,8 +321,8 @@ Compiler::fgWalkResult Compiler::optCSE_MaskHelper(GenTreePtr* pTree, fgWalkData // void Compiler::optCSE_GetMaskData(GenTreePtr tree, optCSE_MaskData* pMaskData) { - pMaskData->CSE_defMask = BitVecOps::MakeCopy(cseTraits, cseEmpty); - pMaskData->CSE_useMask = BitVecOps::MakeCopy(cseTraits, cseEmpty); + pMaskData->CSE_defMask = BitVecOps::MakeEmpty(cseTraits); + pMaskData->CSE_useMask = BitVecOps::MakeEmpty(cseTraits); fgWalkTreePre(&tree, optCSE_MaskHelper, (void*)pMaskData); } @@ -498,10 +498,7 @@ void Compiler::optValnumCSE_Init() // Init traits and full/empty bitvectors. This will be used to track the // individual cse indexes. cseTraits = new (getAllocator()) BitVecTraits(EXPSET_SZ, this); - cseFull = BitVecOps::UninitVal(); - cseEmpty = BitVecOps::UninitVal(); - BitVecOps::AssignNoCopy(cseTraits, cseFull, BitVecOps::MakeFull(cseTraits)); - BitVecOps::AssignNoCopy(cseTraits, cseEmpty, BitVecOps::MakeEmpty(cseTraits)); + cseFull = BitVecOps::MakeFull(cseTraits); /* Allocate and clear the hash bucket table */ @@ -895,7 +892,7 @@ void Compiler::optValnumCSE_InitDataFlow() if (init_to_zero) { /* Initialize to {ZERO} prior to dataflow */ - block->bbCseIn = BitVecOps::MakeCopy(cseTraits, cseEmpty); + block->bbCseIn = BitVecOps::MakeEmpty(cseTraits); } else { @@ -906,7 +903,7 @@ void Compiler::optValnumCSE_InitDataFlow() block->bbCseOut = BitVecOps::MakeCopy(cseTraits, cseFull); /* Initialize to {ZERO} prior to locating the CSE candidates */ - block->bbCseGen = BitVecOps::MakeCopy(cseTraits, cseEmpty); + block->bbCseGen = BitVecOps::MakeEmpty(cseTraits); } // We walk the set of CSE candidates and set the bit corresponsing to the CSEindex @@ -960,42 +957,31 @@ void Compiler::optValnumCSE_InitDataFlow() */ class CSE_DataFlow { -private: - EXPSET_TP m_preMergeOut; - - Compiler* m_pCompiler; + BitVecTraits* m_pBitVecTraits; + EXPSET_TP m_preMergeOut; public: - CSE_DataFlow(Compiler* pCompiler) : m_pCompiler(pCompiler) - { - } - - Compiler* getCompiler() + CSE_DataFlow(Compiler* pCompiler) : m_pBitVecTraits(pCompiler->cseTraits), m_preMergeOut(BitVecOps::UninitVal()) { - return m_pCompiler; } // At the start of the merge function of the dataflow equations, initialize premerge state (to detect changes.) void StartMerge(BasicBlock* block) { - m_preMergeOut = BitVecOps::MakeCopy(m_pCompiler->cseTraits, block->bbCseOut); + BitVecOps::Assign(m_pBitVecTraits, m_preMergeOut, block->bbCseOut); } // During merge, perform the actual merging of the predecessor's (since this is a forward analysis) dataflow flags. void Merge(BasicBlock* block, BasicBlock* predBlock, flowList* preds) { - BitVecOps::IntersectionD(m_pCompiler->cseTraits, block->bbCseIn, predBlock->bbCseOut); + BitVecOps::IntersectionD(m_pBitVecTraits, block->bbCseIn, predBlock->bbCseOut); } // At the end of the merge store results of the dataflow equations, in a postmerge state. bool EndMerge(BasicBlock* block) { - BitVecTraits* traits = m_pCompiler->cseTraits; - EXPSET_TP mergeOut = BitVecOps::MakeCopy(traits, block->bbCseIn); - BitVecOps::UnionD(traits, mergeOut, block->bbCseGen); - BitVecOps::IntersectionD(traits, mergeOut, block->bbCseOut); - BitVecOps::Assign(traits, block->bbCseOut, mergeOut); - return (!BitVecOps::Equal(traits, mergeOut, m_preMergeOut)); + BitVecOps::DataFlowD(m_pBitVecTraits, block->bbCseOut, block->bbCseGen, block->bbCseIn); + return !BitVecOps::Equal(m_pBitVecTraits, block->bbCseOut, m_preMergeOut); } }; @@ -1061,6 +1047,8 @@ void Compiler::optValnumCSE_Availablity() printf("Labeling the CSEs with Use/Def information\n"); } #endif + EXPSET_TP available_cses = BitVecOps::MakeEmpty(cseTraits); + for (BasicBlock* block = fgFirstBB; block; block = block->bbNext) { GenTreePtr stmt; @@ -1070,7 +1058,7 @@ void Compiler::optValnumCSE_Availablity() compCurBB = block; - EXPSET_TP available_cses = BitVecOps::MakeCopy(cseTraits, block->bbCseIn); + BitVecOps::Assign(cseTraits, available_cses, block->bbCseIn); optCSEweight = block->getBBWeight(this);