Refactor JTRUE handling during assertion gen/prop
authorMike Danes <onemihaid@hotmail.com>
Thu, 2 Mar 2017 21:45:45 +0000 (23:45 +0200)
committerMike Danes <onemihaid@hotmail.com>
Fri, 3 Mar 2017 17:16:03 +0000 (19:16 +0200)
- Pull JTRUE related code out of the inner loop of assertion gen to keep the loop small and simple
- Ignore JTRUE in the inner loop of assertion prop, there's nothing to propagate to or from it
- Avoid some unnecessary bitset clears and copies

Commit migrated from https://github.com/dotnet/coreclr/commit/9fd9a1d5d10728a35d51361242ad9d9790ab6af6

src/coreclr/src/jit/assertionprop.cpp

index cb0832f..d2ae516 100644 (file)
@@ -4429,15 +4429,10 @@ ASSERT_TP* Compiler::optComputeAssertionGen()
 {
     ASSERT_TP* jumpDestGen = fgAllocateTypeForEachBlk<ASSERT_TP>();
 
-    ASSERT_TP valueGen         = BitVecOps::MakeEmpty(apTraits);
-    ASSERT_TP jumpDestValueGen = BitVecOps::MakeEmpty(apTraits);
-
     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
     {
-        jumpDestGen[block->bbNum] = BitVecOps::MakeEmpty(apTraits);
-
-        BitVecOps::ClearD(apTraits, valueGen);
-        BitVecOps::ClearD(apTraits, jumpDestValueGen);
+        ASSERT_TP valueGen = BitVecOps::MakeEmpty(apTraits);
+        GenTree*  jtrue    = nullptr;
 
         // Walk the statement trees in this basic block.
         for (GenTreePtr stmt = block->bbTreeList; stmt; stmt = stmt->gtNext)
@@ -4446,47 +4441,58 @@ ASSERT_TP* Compiler::optComputeAssertionGen()
 
             for (GenTreePtr tree = stmt->gtStmt.gtStmtList; tree; tree = tree->gtNext)
             {
-                // Store whatever we have accumulated into jumpDest edge's valueGen.
                 if (tree->gtOper == GT_JTRUE)
                 {
-                    BitVecOps::Assign(apTraits, jumpDestValueGen, valueGen);
+                    assert((tree->gtNext == nullptr) && (stmt->gtNext == nullptr));
+                    jtrue = tree;
+                    break;
                 }
-                if (!tree->HasAssertion())
+
+                AssertionIndex index = tree->GetAssertion();
+                if (index != NO_ASSERTION_INDEX)
                 {
-                    continue;
+                    optImpliedAssertions(index, valueGen);
+                    BitVecOps::AddElemD(apTraits, valueGen, index - 1);
                 }
+            }
+        }
+
+        if (jtrue != nullptr)
+        {
+            // Copy whatever we have accumulated into jumpDest edge's valueGen.
+            ASSERT_TP jumpDestValueGen = BitVecOps::MakeCopy(apTraits, valueGen);
 
-                // For regular trees, just update valueGen. For GT_JTRUE, for false part,
-                // update valueGen and true part update jumpDestValueGen.
-                AssertionIndex assertionIndex[2] = {(AssertionIndex)tree->GetAssertion(),
-                                                    (tree->OperGet() == GT_JTRUE)
-                                                        ? optFindComplementary((AssertionIndex)tree->GetAssertion())
-                                                        : 0};
+            AssertionIndex index = jtrue->GetAssertion();
+            if (index != NO_ASSERTION_INDEX)
+            {
+                optImpliedAssertions(index, jumpDestValueGen);
+                BitVecOps::AddElemD(apTraits, jumpDestValueGen, index - 1);
 
-                for (unsigned i = 0; i < 2; ++i)
+                index = optFindComplementary(index);
+                if (index != NO_ASSERTION_INDEX)
                 {
-                    if (assertionIndex[i] > 0)
-                    {
-                        // If GT_JTRUE, and true part use jumpDestValueGen.
-                        ASSERT_TP& gen = (i == 0 && tree->OperGet() == GT_JTRUE) ? jumpDestValueGen : valueGen;
-                        optImpliedAssertions(assertionIndex[i], gen);
-                        BitVecOps::AddElemD(apTraits, gen, assertionIndex[i] - 1);
-                    }
+                    optImpliedAssertions(index, valueGen);
+                    BitVecOps::AddElemD(apTraits, valueGen, index - 1);
                 }
             }
+
+            jumpDestGen[block->bbNum] = jumpDestValueGen;
+        }
+        else
+        {
+            jumpDestGen[block->bbNum] = BitVecOps::MakeEmpty(apTraits);
         }
 
-        BitVecOps::Assign(apTraits, block->bbAssertionGen, valueGen);
-        BitVecOps::Assign(apTraits, jumpDestGen[block->bbNum], jumpDestValueGen);
+        block->bbAssertionGen = valueGen;
 
 #ifdef DEBUG
         if (verbose)
         {
-            printf("\nBB%02u valueGen = %s", block->bbNum, BitVecOps::ToString(apTraits, valueGen));
+            printf("\nBB%02u valueGen = %s", block->bbNum, BitVecOps::ToString(apTraits, block->bbAssertionGen));
             if (block->bbJumpKind == BBJ_COND)
             {
                 printf(" => BB%02u valueGen = %s,", block->bbJumpDest->bbNum,
-                       BitVecOps::ToString(apTraits, jumpDestValueGen));
+                       BitVecOps::ToString(apTraits, jumpDestGen[block->bbNum]));
             }
         }
 #endif
@@ -5070,6 +5076,12 @@ void Compiler::optAssertionPropMain()
                                                        // and thus we must morph, set order, re-link
             for (GenTreePtr tree = stmt->gtStmt.gtStmtList; tree; tree = tree->gtNext)
             {
+                if (tree->OperIs(GT_JTRUE))
+                {
+                    assert((tree->gtNext == nullptr) && (stmt->gtNext == nullptr));
+                    break;
+                }
+
                 JITDUMP("Propagating %s assertions for BB%02d, stmt [%06d], tree [%06d], tree -> %d\n",
                         BitVecOps::ToString(apTraits, assertions), block->bbNum, dspTreeID(stmt), dspTreeID(tree),
                         tree->GetAssertion());
@@ -5081,16 +5093,12 @@ void Compiler::optAssertionPropMain()
                     tree = newTree;
                 }
 
-                // Is this an assignment to a local variable
-                GenTreeLclVarCommon* lclVarTree = nullptr;
-
                 // If this tree makes an assertion - make it available.
-                if (tree->HasAssertion())
+                AssertionIndex index = tree->GetAssertion();
+                if (index != NO_ASSERTION_INDEX)
                 {
-                    BitVecOps::AddElemD(apTraits, assertions, tree->GetAssertion() - 1);
-
-                    // Also include any implied assertions for the tree node.
-                    optImpliedAssertions((AssertionIndex)tree->GetAssertion(), assertions);
+                    optImpliedAssertions(index, assertions);
+                    BitVecOps::AddElemD(apTraits, assertions, index - 1);
                 }
             }