Some BitVecOps improvements (dotnet/coreclr#10437)
authormikedn <onemihaid@hotmail.com>
Sat, 25 Mar 2017 14:45:10 +0000 (16:45 +0200)
committerBruce Forstall <brucefo@microsoft.com>
Sat, 25 Mar 2017 14:45:10 +0000 (07:45 -0700)
* 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

src/coreclr/src/jit/assertionprop.cpp
src/coreclr/src/jit/bitset.cpp
src/coreclr/src/jit/bitsetasshortlong.h
src/coreclr/src/jit/codegencommon.cpp
src/coreclr/src/jit/compiler.h
src/coreclr/src/jit/compilerbitsettraits.h
src/coreclr/src/jit/compilerbitsettraits.hpp
src/coreclr/src/jit/liveness.cpp
src/coreclr/src/jit/optcse.cpp

index 0c5b8f3..b804b96 100644 (file)
@@ -511,7 +511,7 @@ ASSERT_TP& Compiler::GetAssertionDep(unsigned lclNum)
     ExpandArray<ASSERT_TP>& 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
index 90ef253..785061f 100644 (file)
@@ -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)
     {
index ec437e1..163cb36 100644 (file)
@@ -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</*BitSetType*/ BitSetShortLongRep,
     assert(!IsShort(env));
     unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
     assert(len > 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 <typename Env, typename BitSetTraits>
@@ -641,7 +690,7 @@ BitSetShortLongRep BitSetOps</*BitSetType*/ BitSetShortLongRep,
     assert(!IsShort(env));
     unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
     assert(len > 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</*BitSetType*/ BitSetShortLongRep,
     assert(!IsShort(env));
     unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
     assert(len > 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 <typename Env, typename BitSetTraits>
 bool BitSetOps</*BitSetType*/ BitSetShortLongRep,
                /*Brand*/ BSShortLong,
                /*Env*/ Env,
+               /*BitSetTraits*/ BitSetTraits>::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 <typename Env, typename BitSetTraits>
+void BitSetOps</*BitSetType*/ BitSetShortLongRep,
+               /*Brand*/ BSShortLong,
+               /*Env*/ Env,
+               /*BitSetTraits*/ BitSetTraits>::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 <typename Env, typename BitSetTraits>
+void BitSetOps</*BitSetType*/ BitSetShortLongRep,
+               /*Brand*/ BSShortLong,
+               /*Env*/ Env,
+               /*BitSetTraits*/ BitSetTraits>::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 <typename Env, typename BitSetTraits>
+bool BitSetOps</*BitSetType*/ BitSetShortLongRep,
+               /*Brand*/ BSShortLong,
+               /*Env*/ Env,
                /*BitSetTraits*/ BitSetTraits>::EqualLong(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2)
 {
     assert(!IsShort(env));
@@ -762,13 +864,12 @@ const char* BitSetOps</*BitSetType*/ BitSetShortLongRep,
                       /*BitSetTraits*/ BitSetTraits>::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];
index 71d27be..a28ce2c 100644 (file)
@@ -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
index 3099c44..98e9fb8 100644 (file)
@@ -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);
index 4365c51..d0436f4 100644 (file)
 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);
index e2ba2f8..be30564 100644 (file)
 ///////////////////////////////////////////////////////////////////////////////
 
 // 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
 
index c666318..47950ae 100644 (file)
@@ -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 */
 
index 519e31f..41aad40 100644 (file)
@@ -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);