JIT: remove cheap preds (#81562)
authorAndy Ayers <andya@microsoft.com>
Fri, 3 Feb 2023 02:28:20 +0000 (18:28 -0800)
committerGitHub <noreply@github.com>
Fri, 3 Feb 2023 02:28:20 +0000 (18:28 -0800)
We no longer need cheap preds. We always have full preds available.

Also, remove the ability to drop and recompute full preds, as we now compute
full preds incrementally while building the flow graph, and never drop or need
to rebuild them.

Contributes to #80193.

src/coreclr/jit/block.cpp
src/coreclr/jit/block.h
src/coreclr/jit/compiler.cpp
src/coreclr/jit/compiler.h
src/coreclr/jit/fgbasic.cpp
src/coreclr/jit/fgdiagnostic.cpp
src/coreclr/jit/fgflow.cpp
src/coreclr/jit/fgopt.cpp
src/coreclr/jit/optimizer.cpp

index 720f449..c383097 100644 (file)
@@ -554,35 +554,6 @@ unsigned BasicBlock::dspPreds()
     return count;
 }
 
-/*****************************************************************************
- *
- *  Display the bbCheapPreds basic block list (the block predecessors).
- *  Returns the number of characters printed.
- */
-
-unsigned BasicBlock::dspCheapPreds()
-{
-    unsigned count = 0;
-    for (BasicBlockList* pred = bbCheapPreds; pred != nullptr; pred = pred->next)
-    {
-        if (count != 0)
-        {
-            printf(",");
-            count += 1;
-        }
-        printf(FMT_BB, pred->block->bbNum);
-        count += 4;
-
-        // Account for %02u only handling 2 digits, but we can display more than that.
-        unsigned digits = CountDigits(pred->block->bbNum);
-        if (digits > 2)
-        {
-            count += digits - 2;
-        }
-    }
-    return count;
-}
-
 //------------------------------------------------------------------------
 // dspSuccs: Display the basic block successors.
 //
@@ -731,14 +702,7 @@ void BasicBlock::dspBlockHeader(Compiler* compiler,
     if (showPreds)
     {
         printf(", preds={");
-        if (compiler->fgCheapPredsValid)
-        {
-            dspCheapPreds();
-        }
-        else
-        {
-            dspPreds();
-        }
+        dspPreds();
         printf("} succs={");
         dspSuccs(compiler);
         printf("}");
index b27e122..1bc175b 100644 (file)
@@ -665,7 +665,6 @@ struct BasicBlock : private LIR::Range
 
 #ifdef DEBUG
     void     dspFlags();               // Print the flags
-    unsigned dspCheapPreds();          // Print the predecessors (bbCheapPreds)
     unsigned dspPreds();               // Print the predecessors (bbPreds)
     void dspSuccs(Compiler* compiler); // Print the successors. The 'compiler' argument determines whether EH
                                        // regions are printed: see NumSucc() for details.
@@ -1052,16 +1051,11 @@ struct BasicBlock : private LIR::Range
         unsigned short bbFPinVars; // number of inner enregistered FP vars
     };
 
-    // Basic block predecessor lists. Early in compilation, some phases might need to compute "cheap" predecessor
-    // lists. These are stored in bbCheapPreds, computed by fgComputeCheapPreds(). If bbCheapPreds is valid,
-    // 'fgCheapPredsValid' will be 'true'. Later, the "full" predecessor lists are created by fgComputePreds(), stored
+    // Basic block predecessor lists. Predecessor lists are created by fgLinkBasicBlocks(), stored
     // in 'bbPreds', and then maintained throughout compilation. 'fgComputePredsDone' will be 'true' after the
-    // full predecessor lists are created. See the comment at fgComputeCheapPreds() to see how those differ from
-    // the "full" variant.
-    union {
-        BasicBlockList* bbCheapPreds; // ptr to list of cheap predecessors (used before normal preds are computed)
-        flowList*       bbPreds;      // ptr to list of predecessors
-    };
+    // predecessor lists are created.
+    //
+    flowList* bbPreds; // ptr to list of predecessors
 
     // PredEdges: convenience method for enabling range-based `for` iteration over predecessor edges, e.g.:
     //    for (flowList* const edge : block->PredEdges()) ...
@@ -1774,9 +1768,7 @@ inline BBArrayIterator BasicBlock::BBSuccList::end() const
 // by Compiler::fgReorderBlocks()
 //
 // We have a simpler struct, BasicBlockList, which is simply a singly-linked
-// list of blocks. This is used for various purposes, but one is as a "cheap"
-// predecessor list, computed by fgComputeCheapPreds(), and stored as a list
-// on BasicBlock pointed to by bbCheapPreds.
+// list of blocks.
 
 struct BasicBlockList
 {
index 8e36f38..b60013a 100644 (file)
@@ -8860,7 +8860,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  *      cVarDsc,     dVarDsc        : Display a local variable given a LclVarDsc* (call lvaDumpEntry()).
  *      cVars,       dVars          : Display the local variable table (call lvaTableDump()).
  *      cVarsFinal,  dVarsFinal     : Display the local variable table (call lvaTableDump(FINAL_FRAME_LAYOUT)).
- *      cBlockCheapPreds, dBlockCheapPreds : Display a block's cheap predecessors (call block->dspCheapPreds()).
  *      cBlockPreds, dBlockPreds    : Display a block's predecessors (call block->dspPreds()).
  *      cBlockSuccs, dBlockSuccs    : Display a block's successors (call block->dspSuccs(compiler)).
  *      cReach,      dReach         : Display all block reachability (call fgDispReach()).
@@ -8962,14 +8961,6 @@ void cVarsFinal(Compiler* comp)
     comp->lvaTableDump(Compiler::FINAL_FRAME_LAYOUT);
 }
 
-void cBlockCheapPreds(Compiler* comp, BasicBlock* block)
-{
-    static unsigned sequenceNumber = 0; // separate calls with a number to indicate this function has been called
-    printf("===================================================================== *BlockCheapPreds %u\n",
-           sequenceNumber++);
-    block->dspCheapPreds();
-}
-
 void cBlockPreds(Compiler* comp, BasicBlock* block)
 {
     static unsigned sequenceNumber = 0; // separate calls with a number to indicate this function has been called
@@ -9115,11 +9106,6 @@ void dBlockPreds(BasicBlock* block)
     cBlockPreds(JitTls::GetCompiler(), block);
 }
 
-void dBlockCheapPreds(BasicBlock* block)
-{
-    cBlockCheapPreds(JitTls::GetCompiler(), block);
-}
-
 void dBlockSuccs(BasicBlock* block)
 {
     cBlockSuccs(JitTls::GetCompiler(), block);
index 74cf4e3..9c42682 100644 (file)
@@ -4513,7 +4513,6 @@ public:
 
     bool fgModified;             // True if the flow graph has been modified recently
     bool fgComputePredsDone;     // Have we computed the bbPreds list
-    bool fgCheapPredsValid;      // Is the bbCheapPreds list valid?
     bool fgDomsComputed;         // Have we computed the dominator sets?
     bool fgReturnBlocksComputed; // Have we computed the return blocks list?
     bool fgOptimizedFinally;     // Did we optimize any try-finallys?
@@ -5224,22 +5223,6 @@ protected:
     void fgUpdateChangedFlowGraph(FlowGraphUpdates updates);
 
 public:
-    // Compute the predecessors of the blocks in the control flow graph.
-    void fgComputePreds();
-
-    // Remove all predecessor information.
-    void fgRemovePreds();
-
-    // Compute the cheap flow graph predecessors lists. This is used in some early phases
-    // before the full predecessors lists are computed.
-    void fgComputeCheapPreds();
-
-private:
-    void fgAddCheapPred(BasicBlock* block, BasicBlock* blockPred);
-
-    void fgRemoveCheapPred(BasicBlock* block, BasicBlock* blockPred);
-
-public:
     enum GCPollType
     {
         GCPOLL_NONE,
index 03a8f85..54a9510 100644 (file)
@@ -23,9 +23,6 @@ void Compiler::fgInit()
     /* We haven't yet computed the bbPreds lists */
     fgComputePredsDone = false;
 
-    /* We haven't yet computed the bbCheapPreds lists */
-    fgCheapPredsValid = false;
-
     /* We haven't yet computed the edge weight */
     fgEdgeWeightsComputed    = false;
     fgHaveValidEdgeWeights   = false;
@@ -641,7 +638,6 @@ void Compiler::fgReplacePred(BasicBlock* block, BasicBlock* oldPred, BasicBlock*
     noway_assert(block != nullptr);
     noway_assert(oldPred != nullptr);
     noway_assert(newPred != nullptr);
-    assert(!fgCheapPredsValid);
 
     bool modified = false;
 
index 3773fe5..1bce589 100644 (file)
@@ -1871,15 +1871,7 @@ void Compiler::fgTableDispBasicBlock(BasicBlock* block, int ibcColWidth /* = 0 *
     // Display block predecessor list
     //
 
-    unsigned charCnt;
-    if (fgCheapPredsValid)
-    {
-        charCnt = block->dspCheapPreds();
-    }
-    else
-    {
-        charCnt = block->dspPreds();
-    }
+    unsigned charCnt = block->dspPreds();
 
     if (charCnt < 19)
     {
@@ -2283,7 +2275,6 @@ void Compiler::fgDispBasicBlocks(BasicBlock* firstBlock, BasicBlock* lastBlock,
         maxBlockNumWidth, "----");
     printf("BBnum %*sBBid ref try hnd %s     weight  %*s%s  lp [IL range]     [jump]%*s    [EH region]         [flags]\n",
         padWidth, "",
-        fgCheapPredsValid       ? "cheap preds" :
         (fgComputePredsDone     ? "preds      "
                                 : "           "),
         ((ibcColWidth > 0) ? ibcColWidth - 3 : 0), "",  // Subtract 3 for the width of "IBC", printed next.
@@ -2504,11 +2495,6 @@ private:
 //   the number of incoming edges for the block.
 unsigned BBPredsChecker::CheckBBPreds(BasicBlock* block, unsigned curTraversalStamp)
 {
-    if (comp->fgCheapPredsValid)
-    {
-        return 0;
-    }
-
     if (!comp->fgComputePredsDone)
     {
         assert(block->bbPreds == nullptr);
@@ -2857,11 +2843,8 @@ void Compiler::fgDebugCheckBBlist(bool checkBBNum /* = false */, bool checkBBRef
 
         if (block->bbCatchTyp == BBCT_FILTER)
         {
-            if (!fgCheapPredsValid) // Don't check cheap preds
-            {
-                // A filter has no predecessors
-                assert(block->bbPreds == nullptr);
-            }
+            // A filter has no predecessors
+            assert(block->bbPreds == nullptr);
         }
 
 #if defined(FEATURE_EH_FUNCLETS)
index 6b67696..d745386 100644 (file)
 //    The flowList edge corresponding to "blockPred". If "blockPred" is not in the predecessor list of "block",
 //    then returns nullptr.
 //
-// Assumptions:
-//    -- This only works on the full predecessor lists, not the cheap preds lists.
-//
 flowList* Compiler::fgGetPredForBlock(BasicBlock* block, BasicBlock* blockPred)
 {
     assert(block);
     assert(blockPred);
-    assert(!fgCheapPredsValid);
 
     for (flowList* const pred : block->PredEdges())
     {
@@ -54,15 +50,11 @@ flowList* Compiler::fgGetPredForBlock(BasicBlock* block, BasicBlock* blockPred)
 //    The flowList edge corresponding to "blockPred". If "blockPred" is not in the predecessor list of "block",
 //    then returns nullptr.
 //
-// Assumptions:
-//    -- This only works on the full predecessor lists, not the cheap preds lists.
-//
 flowList* Compiler::fgGetPredForBlock(BasicBlock* block, BasicBlock* blockPred, flowList*** ptrToPred)
 {
     assert(block);
     assert(blockPred);
     assert(ptrToPred);
-    assert(!fgCheapPredsValid);
 
     flowList** predPrevAddr;
     flowList*  pred;
@@ -95,9 +87,6 @@ flowList* Compiler::fgGetPredForBlock(BasicBlock* block, BasicBlock* blockPred,
 // Return Value:
 //    The flow edge representing the predecessor.
 //
-// Assumptions:
-//    -- This only works on the full predecessor lists, not the cheap preds lists.
-//
 // Notes:
 //    -- block->bbRefs is incremented by one to account for the increase in incoming edges.
 //    -- block->bbRefs is adjusted even if preds haven't been computed. If preds haven't been computed,
@@ -122,8 +111,6 @@ flowList* Compiler::fgAddRefPred(BasicBlock* block,
         return nullptr;
     }
 
-    assert(!fgCheapPredsValid);
-
     // Keep the predecessor list in lowest to highest bbNum order. This allows us to discover the loops in
     // optFindNaturalLoops from innermost to outermost.
     //
@@ -263,7 +250,6 @@ flowList* Compiler::fgAddRefPred(BasicBlock* block,
 //
 // Assumptions:
 //    -- "blockPred" must be a predecessor block of "block".
-//    -- This only works on the full predecessor lists, not the cheap preds lists.
 //
 // Notes:
 //    -- block->bbRefs is decremented by one to account for the reduction in incoming edges.
@@ -289,8 +275,6 @@ flowList* Compiler::fgRemoveRefPred(BasicBlock* block, BasicBlock* blockPred)
         return nullptr;
     }
 
-    assert(!fgCheapPredsValid);
-
     flowList** ptrToPred;
     flowList*  pred = fgGetPredForBlock(block, blockPred, &ptrToPred);
     noway_assert(pred != nullptr);
@@ -326,7 +310,6 @@ flowList* Compiler::fgRemoveRefPred(BasicBlock* block, BasicBlock* blockPred)
 //
 // Assumptions:
 //    -- "blockPred" must be a predecessor block of "block".
-//    -- This only works on the full predecessor lists, not the cheap preds lists.
 //
 // Notes:
 //    block->bbRefs is decremented to account for the reduction in incoming edges.
@@ -336,7 +319,6 @@ flowList* Compiler::fgRemoveAllRefPreds(BasicBlock* block, BasicBlock* blockPred
     assert(block != nullptr);
     assert(blockPred != nullptr);
     assert(fgComputePredsDone);
-    assert(!fgCheapPredsValid);
     assert(block->countOfInEdges() > 0);
 
     flowList** ptrToPred;
@@ -363,13 +345,8 @@ flowList* Compiler::fgRemoveAllRefPreds(BasicBlock* block, BasicBlock* blockPred
 // Arguments:
 //    block -- A block to operate on.
 //
-// Assumptions:
-//    -- This only works on the full predecessor lists, not the cheap preds lists.
-//
 void Compiler::fgRemoveBlockAsPred(BasicBlock* block)
 {
-    assert(!fgCheapPredsValid);
-
     PREFIX_ASSUME(block != nullptr);
 
     BasicBlock* bNext;
@@ -471,359 +448,6 @@ void Compiler::fgRemoveBlockAsPred(BasicBlock* block)
     }
 }
 
-//------------------------------------------------------------------------
-// fgComputeCheapPreds: Compute the BasicBlock::bbCheapPreds lists.
-//
-// No other block data is changed (e.g., bbRefs, bbFlags).
-//
-// The cheap preds lists are similar to the normal (bbPreds) predecessor lists, but are cheaper to
-// compute and store, as follows:
-// 1. A flow edge is typed BasicBlockList, which only has a block pointer and 'next' pointer. It doesn't
-//    have weights or a dup count.
-// 2. The preds list for a block is not sorted by block number.
-// 3. The predecessors of the block following a BBJ_CALLFINALLY (the corresponding BBJ_ALWAYS,
-//    for normal, non-retless calls to the finally) are not computed.
-// 4. The cheap preds lists will contain duplicates if a single switch table has multiple branches
-//    to the same block. Thus, we don't spend the time looking for duplicates for every edge we insert.
-//
-void Compiler::fgComputeCheapPreds()
-{
-    noway_assert(!fgComputePredsDone); // We can't do this if we've got the full preds.
-    noway_assert(fgFirstBB != nullptr);
-
-#ifdef DEBUG
-    if (verbose)
-    {
-        printf("\n*************** In fgComputeCheapPreds()\n");
-        fgDispBasicBlocks();
-        printf("\n");
-    }
-#endif // DEBUG
-
-    // Clear out the cheap preds lists.
-    fgRemovePreds();
-
-    for (BasicBlock* const block : Blocks())
-    {
-        switch (block->bbJumpKind)
-        {
-            case BBJ_COND:
-                fgAddCheapPred(block->bbJumpDest, block);
-                fgAddCheapPred(block->bbNext, block);
-                break;
-
-            case BBJ_CALLFINALLY:
-            case BBJ_LEAVE: // If fgComputeCheapPreds is called before all blocks are imported, BBJ_LEAVE blocks are
-                            // still in the BB list.
-            case BBJ_ALWAYS:
-            case BBJ_EHCATCHRET:
-                fgAddCheapPred(block->bbJumpDest, block);
-                break;
-
-            case BBJ_NONE:
-                fgAddCheapPred(block->bbNext, block);
-                break;
-
-            case BBJ_EHFILTERRET:
-                // Connect end of filter to catch handler.
-                // In a well-formed program, this cannot be null.  Tolerate here, so that we can call
-                // fgComputeCheapPreds before fgImport on an ill-formed program; the problem will be detected in
-                // fgImport.
-                if (block->bbJumpDest != nullptr)
-                {
-                    fgAddCheapPred(block->bbJumpDest, block);
-                }
-                break;
-
-            case BBJ_SWITCH:
-                for (BasicBlock* const bTarget : block->SwitchTargets())
-                {
-                    fgAddCheapPred(bTarget, block);
-                }
-                break;
-
-            case BBJ_EHFINALLYRET: // It's expensive to compute the preds for this case, so we don't for the cheap
-                                   // preds.
-            case BBJ_THROW:
-            case BBJ_RETURN:
-                break;
-
-            default:
-                noway_assert(!"Unexpected bbJumpKind");
-                break;
-        }
-    }
-
-    fgCheapPredsValid = true;
-
-#ifdef DEBUG
-    if (verbose)
-    {
-        printf("\n*************** After fgComputeCheapPreds()\n");
-        fgDispBasicBlocks();
-        printf("\n");
-    }
-#endif
-}
-
-//------------------------------------------------------------------------
-// fgAddCheapPred: Add 'blockPred' to the cheap predecessor list of 'block'.
-//
-// Arguments:
-//    block -- A block to operate on.
-//    blockPred -- The predecessor block to add to the cheap predecessors list. It must be a predecessor of "block".
-//
-// Assumptions:
-//    -- "blockPred" must be a predecessor block of "block".
-//    -- This only works on the cheap predecessor lists.
-//
-void Compiler::fgAddCheapPred(BasicBlock* block, BasicBlock* blockPred)
-{
-    assert(!fgComputePredsDone);
-    assert(block != nullptr);
-    assert(blockPred != nullptr);
-
-    block->bbCheapPreds = new (this, CMK_FlowList) BasicBlockList(blockPred, block->bbCheapPreds);
-
-#if MEASURE_BLOCK_SIZE
-    genFlowNodeCnt += 1;
-    genFlowNodeSize += sizeof(BasicBlockList);
-#endif // MEASURE_BLOCK_SIZE
-}
-
-//------------------------------------------------------------------------
-// fgRemoveCheapPred: Remove 'blockPred' from the cheap predecessor list of 'block'.
-// If there are duplicate edges, only remove one of them.
-//
-// Arguments:
-//    block     -- A block to operate on.
-//    blockPred -- The predecessor block to remove from the cheap predecessors list. It must be a
-//                 predecessor of "block".
-//
-// Assumptions:
-//    -- "blockPred" must be a predecessor block of "block".
-//    -- This only works on the cheap predecessor lists.
-//
-void Compiler::fgRemoveCheapPred(BasicBlock* block, BasicBlock* blockPred)
-{
-    assert(!fgComputePredsDone);
-    assert(fgCheapPredsValid);
-
-    assert(block != nullptr);
-    assert(blockPred != nullptr);
-    assert(block->bbCheapPreds != nullptr);
-
-    /* Is this the first block in the pred list? */
-    if (blockPred == block->bbCheapPreds->block)
-    {
-        block->bbCheapPreds = block->bbCheapPreds->next;
-    }
-    else
-    {
-        BasicBlockList* pred;
-        for (pred = block->bbCheapPreds; pred->next != nullptr; pred = pred->next)
-        {
-            if (blockPred == pred->next->block)
-            {
-                break;
-            }
-        }
-        noway_assert(pred->next != nullptr); // we better have found it!
-        pred->next = pred->next->next;       // splice it out
-    }
-}
-
-//------------------------------------------------------------------------
-// fgRemovePreds: Remove all pred information from blocks
-//
-void Compiler::fgRemovePreds()
-{
-    // bbPreds and bbCheapPreds are at the same place in a union
-    static_assert_no_msg(offsetof(BasicBlock, bbPreds) == offsetof(BasicBlock, bbCheapPreds));
-    // and are the same size. So, this function removes both.
-    static_assert_no_msg(sizeof(((BasicBlock*)nullptr)->bbPreds) == sizeof(((BasicBlock*)nullptr)->bbCheapPreds));
-
-    for (BasicBlock* const block : Blocks())
-    {
-        block->bbPreds = nullptr;
-    }
-    fgComputePredsDone = false;
-    fgCheapPredsValid  = false;
-}
-
-//------------------------------------------------------------------------
-// fgComputePreds: Compute the predecessor lists for each block.
-//
-// Notes:
-//    -- Resets and then fills in the list of `bbPreds` predecessor lists for each basic block.
-//    -- Sets the `bbRefs` reference count for each block.
-//    -- Uses `bbLastPred` to optimize inserting predecessors in increasing block number order.
-//    -- The first block of the function gets a `bbRefs` count of at least one because it is always
-//       reachable via the prolog.
-//    -- The first block of each EH handler and EH filter gets an artificial addition ref count to ensure they are
-//       considered reachable.
-//    -- `fgModified` is reset to `false` to indicate the flow graph is in an unmodified state.
-//    -- `fgComputePredsDone` is set to `true`.
-//
-// Assumptions:
-//    Assumes blocks (via bbNext) are in increasing bbNum order.
-//
-void Compiler::fgComputePreds()
-{
-    noway_assert(fgFirstBB != nullptr);
-
-#ifdef DEBUG
-    // Check that the block numbers are increasing order.
-    unsigned lastBBnum = fgFirstBB->bbNum;
-    for (BasicBlock* const block : Blocks(fgFirstBB->bbNext))
-    {
-        assert(lastBBnum < block->bbNum);
-        lastBBnum = block->bbNum;
-    }
-#endif // DEBUG
-
-    // Reset everything pred related
-    for (BasicBlock* const block : Blocks())
-    {
-        block->bbPreds    = nullptr;
-        block->bbLastPred = nullptr;
-        block->bbRefs     = 0;
-    }
-
-    // the first block is always reachable
-    fgFirstBB->bbRefs = 1;
-
-    for (BasicBlock* const block : Blocks())
-    {
-        switch (block->bbJumpKind)
-        {
-            case BBJ_CALLFINALLY:
-                if (!(block->bbFlags & BBF_RETLESS_CALL))
-                {
-                    assert(block->isBBCallAlwaysPair());
-
-                    /* Mark the next block as being a jump target,
-                       since the call target will return there */
-                    PREFIX_ASSUME(block->bbNext != nullptr);
-                }
-
-                FALLTHROUGH;
-
-            case BBJ_LEAVE: // Sometimes fgComputePreds is called before all blocks are imported, so BBJ_LEAVE
-                            // blocks are still in the BB list.
-            case BBJ_COND:
-            case BBJ_ALWAYS:
-            case BBJ_EHCATCHRET:
-
-                fgAddRefPred(block->bbJumpDest, block, nullptr, true);
-
-                /* Is the next block reachable? */
-
-                if (block->bbJumpKind != BBJ_COND)
-                {
-                    break;
-                }
-
-                noway_assert(block->bbNext);
-
-                /* Fall through, the next block is also reachable */
-                FALLTHROUGH;
-
-            case BBJ_NONE:
-
-                fgAddRefPred(block->bbNext, block, nullptr, true);
-                break;
-
-            case BBJ_EHFILTERRET:
-
-                // Connect end of filter to catch handler.
-                // In a well-formed program, this cannot be null.  Tolerate here, so that we can call
-                // fgComputePreds before fgImport on an ill-formed program; the problem will be detected in fgImport.
-                if (block->bbJumpDest != nullptr)
-                {
-                    fgAddRefPred(block->bbJumpDest, block, nullptr, true);
-                }
-                break;
-
-            case BBJ_EHFINALLYRET:
-            {
-                /* Connect the end of the finally to the successor of
-                  the call to this finally */
-
-                if (!block->hasHndIndex())
-                {
-                    BADCODE("endfinally outside a finally/fault block.");
-                }
-
-                unsigned  hndIndex = block->getHndIndex();
-                EHblkDsc* ehDsc    = ehGetDsc(hndIndex);
-
-                if (!ehDsc->HasFinallyOrFaultHandler())
-                {
-                    BADCODE("endfinally outside a finally/fault block.");
-                }
-
-                if (ehDsc->HasFinallyHandler())
-                {
-                    // Find all BBJ_CALLFINALLY that branched to this finally handler.
-                    BasicBlock* begBlk;
-                    BasicBlock* endBlk;
-                    ehGetCallFinallyBlockRange(hndIndex, &begBlk, &endBlk);
-
-                    BasicBlock* finBeg = ehDsc->ebdHndBeg;
-                    for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext)
-                    {
-                        if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg)
-                        {
-                            continue;
-                        }
-
-                        noway_assert(bcall->isBBCallAlwaysPair());
-                        fgAddRefPred(bcall->bbNext, block, nullptr, true);
-                    }
-                }
-            }
-            break;
-
-            case BBJ_THROW:
-            case BBJ_RETURN:
-                break;
-
-            case BBJ_SWITCH:
-                for (BasicBlock* const bTarget : block->SwitchTargets())
-                {
-                    fgAddRefPred(bTarget, block, nullptr, true);
-                }
-                break;
-
-            default:
-                noway_assert(!"Unexpected bbJumpKind");
-                break;
-        }
-    }
-
-    // Add artifical ref counts to the entry of filters and handlers.
-    // We don't inline methods with EH, so this is only relevant to the root method.
-    //
-    if (!compIsForInlining())
-    {
-        for (EHblkDsc* const ehDsc : EHClauses(this))
-        {
-            if (ehDsc->HasFilter())
-            {
-                // The first block of a filter has an artificial extra refcount.
-                ehDsc->ebdFilter->bbRefs++;
-            }
-
-            // The first block of a handler has an artificial extra refcount.
-            ehDsc->ebdHndBeg->bbRefs++;
-        }
-    }
-
-    fgModified         = false;
-    fgComputePredsDone = true;
-}
-
 unsigned Compiler::fgNSuccsOfFinallyRet(BasicBlock* block)
 {
     BasicBlock* bb;
index 642721d..77c4752 100644 (file)
@@ -29,7 +29,6 @@
 bool Compiler::fgDominate(BasicBlock* b1, BasicBlock* b2)
 {
     noway_assert(fgDomsComputed);
-    assert(!fgCheapPredsValid);
 
     //
     // If the fgModified flag is false then we made some modifications to
@@ -113,7 +112,6 @@ bool Compiler::fgDominate(BasicBlock* b1, BasicBlock* b2)
 bool Compiler::fgReachable(BasicBlock* b1, BasicBlock* b2)
 {
     noway_assert(fgDomsComputed);
-    assert(!fgCheapPredsValid);
 
     //
     // If the fgModified flag is false then we made some modifications to
@@ -233,7 +231,6 @@ void Compiler::fgUpdateChangedFlowGraph(FlowGraphUpdates updates)
 void Compiler::fgComputeReachabilitySets()
 {
     assert(fgComputePredsDone);
-    assert(!fgCheapPredsValid);
 
 #ifdef DEBUG
     fgReachabilitySetsValid = false;
@@ -436,8 +433,6 @@ void Compiler::fgComputeEnterBlocksSet()
 template <typename CanRemoveBlockBody>
 bool Compiler::fgRemoveUnreachableBlocks(CanRemoveBlockBody canRemoveBlock)
 {
-    assert(!fgCheapPredsValid);
-
     bool hasUnreachableBlocks = false;
     bool changed              = false;
 
@@ -931,8 +926,6 @@ void Compiler::fgDfsInvPostOrderHelper(BasicBlock* block, BlockSet& visited, uns
 //
 void Compiler::fgComputeDoms()
 {
-    assert(!fgCheapPredsValid);
-
 #ifdef DEBUG
     if (verbose)
     {
index db27df6..182cccc 100644 (file)
@@ -5393,7 +5393,6 @@ void Compiler::optMarkLoopHeads()
         printf("*************** In optMarkLoopHeads()\n");
     }
 
-    assert(!fgCheapPredsValid);
     assert(fgReachabilitySetsValid);
     fgDebugCheckBBNumIncreasing();