diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 6fe0555691bd8..bf53fe28e025f 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -5316,6 +5316,8 @@ class Compiler unsigned xcptnIndex, bool putInTryRegion); + BasicBlock* fgNewBBatTryRegionEnd(BBKinds jumpKind, unsigned tryIndex); + void fgInsertBBbefore(BasicBlock* insertBeforeBlk, BasicBlock* newBlk); void fgInsertBBafter(BasicBlock* insertAfterBlk, BasicBlock* newBlk); void fgUnlinkBlock(BasicBlock* block); diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp index f8e7ead56b323..774e456f5e761 100644 --- a/src/coreclr/jit/fgbasic.cpp +++ b/src/coreclr/jit/fgbasic.cpp @@ -6723,6 +6723,39 @@ BasicBlock* Compiler::fgNewBBinRegionWorker(BBKinds jumpKind, return newBlk; } +//----------------------------------------------------------------------------- +// fgNewBBatTryRegionEnd: Creates and inserts a new block at the end of the specified +// try region, updating the try end pointers in the EH table as necessary. +// +// Arguments: +// jumpKind - The jump kind of the new block +// tryIndex - The index of the try region to insert the new block in +// +// Returns: +// The new block +// +BasicBlock* Compiler::fgNewBBatTryRegionEnd(BBKinds jumpKind, unsigned tryIndex) +{ + BasicBlock* const oldTryLast = ehGetDsc(tryIndex)->ebdTryLast; + BasicBlock* const newBlock = fgNewBBafter(jumpKind, oldTryLast, /* extendRegion */ false); + newBlock->setTryIndex(tryIndex); + newBlock->clearHndIndex(); + + // Update this try region's (and all parent try regions') last block pointer + // + for (unsigned XTnum = tryIndex; XTnum < compHndBBtabCount; XTnum++) + { + EHblkDsc* const HBtab = ehGetDsc(XTnum); + if (HBtab->ebdTryLast == oldTryLast) + { + assert((XTnum == tryIndex) || (ehGetDsc(tryIndex)->ebdEnclosingTryIndex != EHblkDsc::NO_ENCLOSING_INDEX)); + fgSetTryEnd(HBtab, newBlock); + } + } + + return newBlock; +} + //------------------------------------------------------------------------ // fgUseThrowHelperBlocks: Determinate does compiler use throw helper blocks. // diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index 27aedb6eb9af2..f9880026eab26 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -2891,16 +2891,10 @@ bool Compiler::optCreatePreheader(FlowGraphNaturalLoop* loop) } } - BasicBlock* insertBefore = loop->GetLexicallyTopMostBlock(); - if (!BasicBlock::sameEHRegion(insertBefore, header)) - { - insertBefore = header; - } - - BasicBlock* preheader = fgNewBBbefore(BBJ_ALWAYS, insertBefore, false); + BasicBlock* preheader = fgNewBBbefore(BBJ_ALWAYS, header, false); preheader->SetFlags(BBF_INTERNAL); fgSetEHRegionForNewPreheaderOrExit(preheader); - preheader->bbCodeOffs = insertBefore->bbCodeOffs; + preheader->bbCodeOffs = header->bbCodeOffs; JITDUMP("Created new preheader " FMT_BB " for " FMT_LP "\n", preheader->bbNum, loop->GetIndex()); @@ -3003,21 +2997,11 @@ bool Compiler::optCanonicalizeExit(FlowGraphNaturalLoop* loop, BasicBlock* exit) { // Branches to a BBJ_CALLFINALLY _must_ come from inside its associated // try region, and when we have callfinally thunks the BBJ_CALLFINALLY - // is outside it. First try to see if the lexically bottom most block - // is part of the try; if so, inserting after that is a good choice. + // is outside it. Thus, insert newExit at the end of the finally's + // try region. BasicBlock* finallyBlock = exit->GetTarget(); assert(finallyBlock->hasHndIndex()); - BasicBlock* bottom = loop->GetLexicallyBottomMostBlock(); - if (bottom->hasTryIndex() && (bottom->getTryIndex() == finallyBlock->getHndIndex()) && !bottom->hasHndIndex()) - { - newExit = fgNewBBafter(BBJ_ALWAYS, bottom, true); - } - else - { - // Otherwise just do the heavy-handed thing and insert it anywhere in the right region. - newExit = fgNewBBinRegion(BBJ_ALWAYS, finallyBlock->bbHndIndex, 0, nullptr, /* putInFilter */ false, - /* runRarely */ false, /* insertAtEnd */ true); - } + newExit = fgNewBBatTryRegionEnd(BBJ_ALWAYS, finallyBlock->getHndIndex()); } else {