From b64214fb02a5214e92cc2154117f3feaafea11b4 Mon Sep 17 00:00:00 2001 From: Sergey Andreenko Date: Wed, 20 Nov 2019 14:56:41 -0800 Subject: [PATCH 1/2] propogate assertions through Exception handlers. --- src/coreclr/src/jit/assertionprop.cpp | 19 +++++++------------ src/coreclr/src/jit/dataflow.h | 6 ++++++ src/coreclr/src/jit/optcse.cpp | 5 +++++ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/coreclr/src/jit/assertionprop.cpp b/src/coreclr/src/jit/assertionprop.cpp index 6641056bbded7b..4983c54346b1b1 100644 --- a/src/coreclr/src/jit/assertionprop.cpp +++ b/src/coreclr/src/jit/assertionprop.cpp @@ -4526,6 +4526,12 @@ class AssertionPropFlowCallback BitVecOps::IntersectionD(apTraits, block->bbAssertionIn, pAssertionOut); } + 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 +4683,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..bdd0f550f436c7 100644 --- a/src/coreclr/src/jit/optcse.cpp +++ b/src/coreclr/src/jit/optcse.cpp @@ -1034,6 +1034,11 @@ class CSE_DataFlow #endif // DEBUG } + 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. // From 622811b2688884712bb949682698c1a7056e9bff Mon Sep 17 00:00:00 2001 From: Sergey Andreenko Date: Wed, 20 Nov 2019 16:19:15 -0800 Subject: [PATCH 2/2] Add comments. --- src/coreclr/src/jit/assertionprop.cpp | 11 +++++++++++ src/coreclr/src/jit/optcse.cpp | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/coreclr/src/jit/assertionprop.cpp b/src/coreclr/src/jit/assertionprop.cpp index 4983c54346b1b1..96fe16f4035a68 100644 --- a/src/coreclr/src/jit/assertionprop.cpp +++ b/src/coreclr/src/jit/assertionprop.cpp @@ -4526,6 +4526,17 @@ 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); diff --git a/src/coreclr/src/jit/optcse.cpp b/src/coreclr/src/jit/optcse.cpp index bdd0f550f436c7..575bcc6b013b78 100644 --- a/src/coreclr/src/jit/optcse.cpp +++ b/src/coreclr/src/jit/optcse.cpp @@ -1034,6 +1034,17 @@ 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.