diff options
author | Kunal Pathak <Kunal.Pathak@microsoft.com> | 2021-02-25 21:52:45 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-25 21:52:45 +0300 |
commit | 3a24b921431832293d780ccd81c51edd4899241b (patch) | |
tree | d6289e729c7b221504383b8f5a692ac5d6002fbe /src | |
parent | 9211db0a98286d12241ab7201c48884e3d6899a7 (diff) |
fix assertion merge for degenerate flow (#48607)
* fix assertion merge for degenerate flow
* fix the dupCount condition
* Add comment and jitdump
Diffstat (limited to 'src')
-rw-r--r-- | src/coreclr/jit/assertionprop.cpp | 32 | ||||
-rw-r--r-- | src/coreclr/jit/dataflow.h | 4 | ||||
-rw-r--r-- | src/coreclr/jit/morph.cpp | 6 | ||||
-rw-r--r-- | src/coreclr/jit/optcse.cpp | 2 |
4 files changed, 33 insertions, 11 deletions
diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 53fd692601d..5d105881933 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -4648,14 +4648,36 @@ public: } // 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) + void Merge(BasicBlock* block, BasicBlock* predBlock, unsigned dupCount) { - ASSERT_TP pAssertionOut = ((predBlock->bbJumpKind == BBJ_COND) && (predBlock->bbJumpDest == block)) - ? mJumpDestOut[predBlock->bbNum] - : predBlock->bbAssertionOut; + ASSERT_TP pAssertionOut; + + if (predBlock->bbJumpKind == BBJ_COND && (predBlock->bbJumpDest == block)) + { + pAssertionOut = mJumpDestOut[predBlock->bbNum]; + + if (dupCount > 1) + { + // Scenario where next block and conditional block, both point to the same block. + // In such case, intersect the assertions present on both the out edges of predBlock. + assert(predBlock->bbNext == block); + BitVecOps::IntersectionD(apTraits, pAssertionOut, predBlock->bbAssertionOut); + + JITDUMP("AssertionPropCallback::Merge : Duplicate flow, " FMT_BB " in -> %s, predBlock " FMT_BB + " out1 -> %s, out2 -> %s\n", + block->bbNum, BitVecOps::ToString(apTraits, block->bbAssertionIn), predBlock->bbNum, + BitVecOps::ToString(apTraits, mJumpDestOut[predBlock->bbNum]), + BitVecOps::ToString(apTraits, predBlock->bbAssertionOut)); + } + } + else + { + pAssertionOut = predBlock->bbAssertionOut; + } + JITDUMP("AssertionPropCallback::Merge : " FMT_BB " in -> %s, predBlock " FMT_BB " out -> %s\n", block->bbNum, BitVecOps::ToString(apTraits, block->bbAssertionIn), predBlock->bbNum, - BitVecOps::ToString(apTraits, predBlock->bbAssertionOut)); + BitVecOps::ToString(apTraits, pAssertionOut)); BitVecOps::IntersectionD(apTraits, block->bbAssertionIn, pAssertionOut); } diff --git a/src/coreclr/jit/dataflow.h b/src/coreclr/jit/dataflow.h index 3f2ff1cc72a..7e84642dce6 100644 --- a/src/coreclr/jit/dataflow.h +++ b/src/coreclr/jit/dataflow.h @@ -16,7 +16,7 @@ // { // public: // void StartMerge(BasicBlock* block); -// void Merge(BasicBlock* block, BasicBlock* pred, flowList* preds); +// void Merge(BasicBlock* block, BasicBlock* pred, unsigned dupCount); // bool EndMerge(BasicBlock* block); // }; #pragma once @@ -61,7 +61,7 @@ void DataFlow::ForwardAnalysis(TCallback& callback) flowList* preds = m_pCompiler->BlockPredsWithEH(block); for (flowList* pred = preds; pred; pred = pred->flNext) { - callback.Merge(block, pred->getBlock(), preds); + callback.Merge(block, pred->getBlock(), pred->flDupCount); } } diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 0c07628678c..16a84a23149 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -16224,9 +16224,9 @@ bool Compiler::fgFoldConditional(BasicBlock* block) // no side effects, remove the jump entirely fgRemoveStmt(block, lastStmt); } - // block is a BBJ_COND that we are folding the conditional for - // bTaken is the path that will always be taken from block - // bNotTaken is the path that will never be taken from block + // block is a BBJ_COND that we are folding the conditional for. + // bTaken is the path that will always be taken from block. + // bNotTaken is the path that will never be taken from block. // BasicBlock* bTaken; BasicBlock* bNotTaken; diff --git a/src/coreclr/jit/optcse.cpp b/src/coreclr/jit/optcse.cpp index 83a86207c06..181b62b150c 100644 --- a/src/coreclr/jit/optcse.cpp +++ b/src/coreclr/jit/optcse.cpp @@ -1188,7 +1188,7 @@ public: } // Merge: perform the merging of each of the predecessor's liveness values (since this is a forward analysis) - void Merge(BasicBlock* block, BasicBlock* predBlock, flowList* preds) + void Merge(BasicBlock* block, BasicBlock* predBlock, unsigned dupCount) { #ifdef DEBUG if (m_comp->verbose) |