diff --git a/src/coreclr/jit/fgdiagnostic.cpp b/src/coreclr/jit/fgdiagnostic.cpp index 8a36ae86c9e941..bb70210f7d62ef 100644 --- a/src/coreclr/jit/fgdiagnostic.cpp +++ b/src/coreclr/jit/fgdiagnostic.cpp @@ -4295,7 +4295,7 @@ void Compiler::fgDebugCheckSsa() } }; - // Visit the blocks that SSA intially renamed + // Visit the blocks that SSA initially renamed // SsaCheckVisitor scv(this); SsaCheckDomTreeVisitor visitor(this, scv); @@ -4659,6 +4659,32 @@ void Compiler::fgDebugCheckLoopTable() loop.VERIFY_lpIterTree(); loop.VERIFY_lpTestTree(); } + + // If we have dominators, we check more things: + // 1. The pre-header dominates the entry (if pre-headers are required). + // 2. The entry dominates the exit. + // 3. The IDom tree from the exit reaches the entry. + if (fgDomsComputed) + { + if (optLoopsRequirePreHeaders) + { + assert(fgDominate(loop.lpHead, loop.lpEntry)); + } + + if (loop.lpExitCnt == 1) + { + assert(loop.lpExit != nullptr); + assert(fgDominate(loop.lpEntry, loop.lpExit)); + + BasicBlock* cur = loop.lpExit; + while ((cur != nullptr) && (cur != loop.lpEntry)) + { + assert(fgDominate(cur, loop.lpExit)); + cur = cur->bbIDom; + } + assert(cur == loop.lpEntry); // We must be able to reach the entry from the exit via the IDom tree. + } + } } // Check basic blocks for loop annotations. diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index 96790a373513c8..ec0208e1596a90 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -2088,7 +2088,7 @@ class LoopSearch continue; } - // This blocks is lexically between TOP and BOTTOM, but it does not + // This block is lexically between TOP and BOTTOM, but it does not // participate in the flow cycle. Check for a run of consecutive // such blocks. // @@ -2502,6 +2502,21 @@ class LoopSearch if (!loopBlocks.IsMember(exitPoint->bbNum)) { // Exit from a block other than BOTTOM + CLANG_FORMAT_COMMENT_ANCHOR; + +#if !defined(FEATURE_EH_FUNCLETS) + // On non-funclet platforms (x86), the catch exit is a BBJ_ALWAYS, but we don't want that to + // be considered a loop exit block, as catch handlers don't have predecessor lists and don't + // show up as might be expected in the dominator tree. + if (block->bbJumpKind == BBJ_ALWAYS) + { + if (!BasicBlock::sameHndRegion(block, exitPoint)) + { + break; + } + } +#endif // !defined(FEATURE_EH_FUNCLETS) + lastExit = block; exitCount++; } @@ -6986,7 +7001,6 @@ bool Compiler::optHoistThisLoop(unsigned lnum, LoopHoistContext* hoistCtxt) // convenient). But note that it is arbitrary because there is not guaranteed execution order amongst // the child loops. - int childLoopPreHeaders = 0; for (BasicBlock::loopNumber childLoop = pLoopDsc->lpChild; // childLoop != BasicBlock::NOT_IN_LOOP; // childLoop = optLoopTable[childLoop].lpSibling) @@ -7016,7 +7030,6 @@ bool Compiler::optHoistThisLoop(unsigned lnum, LoopHoistContext* hoistCtxt) } JITDUMP(" -- " FMT_BB " (child loop pre-header)\n", childPreHead->bbNum); defExec.Push(childPreHead); - ++childLoopPreHeaders; } if (pLoopDsc->lpExitCnt == 1) @@ -7029,22 +7042,14 @@ bool Compiler::optHoistThisLoop(unsigned lnum, LoopHoistContext* hoistCtxt) // Push dominators, until we reach "entry" or exit the loop. BasicBlock* cur = pLoopDsc->lpExit; - while (cur != nullptr && pLoopDsc->lpContains(cur) && cur != pLoopDsc->lpEntry) + while ((cur != nullptr) && (cur != pLoopDsc->lpEntry)) { JITDUMP(" -- " FMT_BB " (dominate exit block)\n", cur->bbNum); + assert(pLoopDsc->lpContains(cur)); defExec.Push(cur); cur = cur->bbIDom; } - - // If we didn't reach the entry block, give up and *just* push the entry block (and the pre-headers). - if (cur != pLoopDsc->lpEntry) - { - JITDUMP(" -- odd, we didn't reach entry from exit via dominators. Only considering hoisting in entry " - "block " FMT_BB "\n", - pLoopDsc->lpEntry->bbNum); - defExec.Pop(defExec.Height() - childLoopPreHeaders); - assert(defExec.Height() == childLoopPreHeaders); - } + noway_assert(cur == pLoopDsc->lpEntry); } else // More than one exit {