diff --git a/src/coreclr/src/jit/assertionprop.cpp b/src/coreclr/src/jit/assertionprop.cpp index 6641056bbded7b..96fe16f4035a68 100644 --- a/src/coreclr/src/jit/assertionprop.cpp +++ b/src/coreclr/src/jit/assertionprop.cpp @@ -4526,6 +4526,23 @@ class AssertionPropFlowCallback BitVecOps::IntersectionD(apTraits, block->bbAssertionIn, pAssertionOut); } + //------------------------------------------------------------------------ + // MergeHandler: Merge assertions into the first exception handler/filter block. + // + // Arguments: + // block - the block that is the start of a handler or filter; + // firstTryBlock - the first block of the try for "block" handler; + // lastTryBlock - the last block of the try for "block" handler;. + // + // Notes: + // We can jump to the handler from any instruction in the try region. + // It means we can propagate only assertions that are valid for the whole try region. + void MergeHandler(BasicBlock* block, BasicBlock* firstTryBlock, BasicBlock* lastTryBlock) + { + BitVecOps::IntersectionD(apTraits, block->bbAssertionIn, firstTryBlock->bbAssertionIn); + BitVecOps::IntersectionD(apTraits, block->bbAssertionIn, lastTryBlock->bbAssertionOut); + } + // At the end of the merge store results of the dataflow equations, in a postmerge state. bool EndMerge(BasicBlock* block) { @@ -4677,20 +4694,9 @@ ASSERT_TP* Compiler::optInitAssertionDataflowFlags() // Initially estimate the OUT sets to everything except killed expressions // Also set the IN sets to 1, so that we can perform the intersection. - // Also, zero-out the flags for handler blocks, as we could be in the - // handler due to an exception bypassing the regular program flow which - // actually generates assertions along the bbAssertionOut/jumpDestOut - // edges. for (BasicBlock* block = fgFirstBB; block; block = block->bbNext) { - if (bbIsHandlerBeg(block)) - { - block->bbAssertionIn = BitVecOps::MakeEmpty(apTraits); - } - else - { - block->bbAssertionIn = BitVecOps::MakeCopy(apTraits, apValidFull); - } + block->bbAssertionIn = BitVecOps::MakeCopy(apTraits, apValidFull); block->bbAssertionGen = BitVecOps::MakeEmpty(apTraits); block->bbAssertionOut = BitVecOps::MakeCopy(apTraits, apValidFull); jumpDestOut[block->bbNum] = BitVecOps::MakeCopy(apTraits, apValidFull); diff --git a/src/coreclr/src/jit/dataflow.h b/src/coreclr/src/jit/dataflow.h index c7a08db7bb2792..ff691e443bdd8a 100644 --- a/src/coreclr/src/jit/dataflow.h +++ b/src/coreclr/src/jit/dataflow.h @@ -52,6 +52,12 @@ void DataFlow::ForwardAnalysis(TCallback& callback) worklist.erase(worklist.begin()); callback.StartMerge(block); + if (m_pCompiler->bbIsHandlerBeg(block)) + { + EHblkDsc* ehDsc = m_pCompiler->ehGetBlockHndDsc(block); + callback.MergeHandler(block, ehDsc->ebdTryBeg, ehDsc->ebdTryLast); + } + else { flowList* preds = m_pCompiler->BlockPredsWithEH(block); for (flowList* pred = preds; pred; pred = pred->flNext) diff --git a/src/coreclr/src/jit/optcse.cpp b/src/coreclr/src/jit/optcse.cpp index 4398e6fd3fa01c..575bcc6b013b78 100644 --- a/src/coreclr/src/jit/optcse.cpp +++ b/src/coreclr/src/jit/optcse.cpp @@ -1034,6 +1034,22 @@ class CSE_DataFlow #endif // DEBUG } + //------------------------------------------------------------------------ + // MergeHandler: Merge CSE values into the first exception handler/filter block. + // + // Arguments: + // block - the block that is the start of a handler or filter; + // firstTryBlock - the first block of the try for "block" handler; + // lastTryBlock - the last block of the try for "block" handler;. + // + // Notes: + // We can jump to the handler from any instruction in the try region. + // It means we can propagate only CSE that are valid for the whole try region. + void MergeHandler(BasicBlock* block, BasicBlock* firstTryBlock, BasicBlock* lastTryBlock) + { + // TODO CQ: add CSE for handler blocks, CSE_INTO_HANDLERS should be defined. + } + // At the end of the merge store results of the dataflow equations, in a postmerge state. // We also handle the case where calls conditionally kill CSE availabilty. //