From 3d571832886f270ee102bf15ba5c9e590dbc57a2 Mon Sep 17 00:00:00 2001 From: Mike Danes Date: Thu, 2 Mar 2017 23:45:45 +0200 Subject: [PATCH] Refactor JTRUE handling during assertion gen/prop - 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 | 82 +++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/src/coreclr/src/jit/assertionprop.cpp b/src/coreclr/src/jit/assertionprop.cpp index cb0832f..d2ae516 100644 --- a/src/coreclr/src/jit/assertionprop.cpp +++ b/src/coreclr/src/jit/assertionprop.cpp @@ -4429,15 +4429,10 @@ ASSERT_TP* Compiler::optComputeAssertionGen() { ASSERT_TP* jumpDestGen = fgAllocateTypeForEachBlk(); - 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); } } -- 2.7.4