diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 012696d52c907..b4497b98f0bfd 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -5038,6 +5038,10 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl // Insert GC Polls DoPhase(this, PHASE_INSERT_GC_POLLS, &Compiler::fgInsertGCPolls); + // Create any throw helper blocks that might be needed + // + DoPhase(this, PHASE_CREATE_THROW_HELPERS, &Compiler::fgCreateThrowHelperBlocks); + if (opts.OptimizationEnabled()) { // Optimize boolean conditions diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 39ec04aeae178..e2fe9144ed4e8 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -6119,12 +6119,11 @@ class Compiler static unsigned acdHelper(SpecialCodeKind codeKind); AddCodeDsc* fgAddCodeList; - bool fgAddCodeModf; + bool fgRngChkThrowAdded; AddCodeDsc* fgExcptnTargetCache[SCK_COUNT]; - BasicBlock* fgRngChkTarget(BasicBlock* block, SpecialCodeKind kind); - - BasicBlock* fgAddCodeRef(BasicBlock* srcBlk, unsigned refData, SpecialCodeKind kind); + void fgAddCodeRef(BasicBlock* srcBlk, SpecialCodeKind kind); + PhaseStatus fgCreateThrowHelperBlocks(); public: AddCodeDsc* fgFindExcptnTarget(SpecialCodeKind kind, unsigned refData); @@ -6137,8 +6136,6 @@ class Compiler } private: - bool fgIsCodeAdded(); - bool fgIsThrowHlpBlk(BasicBlock* block); #if !FEATURE_FIXED_OUT_ARGS diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index df4ee073969be..47c9007ddee4f 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -3069,7 +3069,7 @@ inline Compiler::fgWalkResult Compiler::fgWalkTree(GenTree** pTree, inline bool Compiler::fgIsThrowHlpBlk(BasicBlock* block) { - if (!fgIsCodeAdded()) + if (!fgRngChkThrowAdded) { return false; } @@ -3157,16 +3157,6 @@ inline unsigned Compiler::fgThrowHlpBlkStkLevel(BasicBlock* block) #endif // !FEATURE_FIXED_OUT_ARGS -/***************************************************************************** - * - * Return true if we've added any new basic blocks. - */ - -inline bool Compiler::fgIsCodeAdded() -{ - return fgAddCodeModf; -} - /***************************************************************************** Is the offset too big? */ diff --git a/src/coreclr/jit/compphases.h b/src/coreclr/jit/compphases.h index 36eb647f04eba..dd1606c4a8a25 100644 --- a/src/coreclr/jit/compphases.h +++ b/src/coreclr/jit/compphases.h @@ -99,6 +99,7 @@ CompPhaseNameMacro(PHASE_EXPAND_RTLOOKUPS, "Expand runtime lookups", CompPhaseNameMacro(PHASE_EXPAND_STATIC_INIT, "Expand static init", false, -1, true) CompPhaseNameMacro(PHASE_EXPAND_TLS, "Expand TLS access", false, -1, true) CompPhaseNameMacro(PHASE_INSERT_GC_POLLS, "Insert GC Polls", false, -1, true) +CompPhaseNameMacro(PHASE_CREATE_THROW_HELPERS, "Create throw helper blocks", false, -1, true) CompPhaseNameMacro(PHASE_DETERMINE_FIRST_COLD_BLOCK, "Determine first cold block", false, -1, true) CompPhaseNameMacro(PHASE_RATIONALIZE, "Rationalize IR", false, -1, false) CompPhaseNameMacro(PHASE_SIMPLE_LOWERING, "Do 'simple' lowering", false, -1, false) diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp index 3455eeca8d649..5218d9a679454 100644 --- a/src/coreclr/jit/fgbasic.cpp +++ b/src/coreclr/jit/fgbasic.cpp @@ -96,7 +96,6 @@ void Compiler::fgInit() // as the code that raises an exception when an array range check fails. fgAddCodeList = nullptr; - fgAddCodeModf = false; for (int i = 0; i < SCK_COUNT; i++) { @@ -109,6 +108,9 @@ void Compiler::fgInit() /* This global flag is set whenever we remove a statement */ fgStmtRemoved = false; + // This global flag is set when we create throw helper blocks + fgRngChkThrowAdded = false; + /* Keep track of whether or not EH statements have been optimized */ fgOptimizedFinally = false; diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index f656718387443..2dbb470d99974 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -2789,7 +2789,7 @@ PhaseStatus Compiler::fgFindOperOrder() // Suitable phase status // // Notes: -// Lowers GT_ARR_LENGTH, GT_MDARR_LENGTH, GT_MDARR_LOWER_BOUND, GT_BOUNDS_CHECK. +// Lowers GT_ARR_LENGTH, GT_MDARR_LENGTH, GT_MDARR_LOWER_BOUND // PhaseStatus Compiler::fgSimpleLowering() { @@ -2874,14 +2874,6 @@ PhaseStatus Compiler::fgSimpleLowering() break; } - case GT_BOUNDS_CHECK: - { - // Add in a call to an error routine. - fgSetRngChkTarget(tree, false); - madeChanges = true; - break; - } - case GT_CAST: { if (tree->AsCast()->CastOp()->OperIsSimple() && fgSimpleLowerCastOfSmpOp(range, tree->AsCast())) @@ -3569,7 +3561,15 @@ EXIT:; return PhaseStatus::MODIFIED_EVERYTHING; } -/* static */ +//------------------------------------------------------------------------ +// acdHelper: map from special code kind to runtime helper +// +// Arguments: +// codeKind - kind of special code desired +// +// Returns: +// Helper to throw the correct exception +// unsigned Compiler::acdHelper(SpecialCodeKind codeKind) { switch (codeKind) @@ -3592,54 +3592,81 @@ unsigned Compiler::acdHelper(SpecialCodeKind codeKind) } } +#ifdef DEBUG //------------------------------------------------------------------------ -// fgAddCodeRef: Find/create an added code entry associated with the given block and with the given kind. +// acdHelper: map from special code kind to descriptive name +// +// Arguments: +// codeKind - kind of special code +// +// Returns: +// String describing the special code kind +// +const char* sckName(SpecialCodeKind codeKind) +{ + switch (codeKind) + { + case SCK_RNGCHK_FAIL: + return "SCK_RNGCHK_FAIL"; + case SCK_ARG_EXCPN: + return "SCK_ARG_EXCPN"; + case SCK_ARG_RNG_EXCPN: + return "SCK_ARG_RNG_EXCPN"; + case SCK_DIV_BY_ZERO: + return "SCK_DIV_BY_ZERO"; + case SCK_ARITH_EXCPN: + return "SCK_ARITH_EXCPN"; + case SCK_FAIL_FAST: + return "SCK_FAIL_FAST"; + default: + return "SCK_UNKNOWN"; + } +} +#endif + +//------------------------------------------------------------------------ +// fgAddCodeRef: Indicate that a particular throw helper block will +// be needed by the method. // // Arguments: // srcBlk - the block that needs an entry; -// refData - the index to use as the cache key for sharing throw blocks; // kind - the kind of exception; // -// Return Value: -// The target throw helper block or nullptr if throw helper blocks are disabled. +// Notes: +// You can call this method after throw helpers have been created, +// but it will assert if this entails creation of a new helper. // -BasicBlock* Compiler::fgAddCodeRef(BasicBlock* srcBlk, unsigned refData, SpecialCodeKind kind) +void Compiler::fgAddCodeRef(BasicBlock* srcBlk, SpecialCodeKind kind) { - // Record that the code will call a THROW_HELPER - // so on Windows Amd64 we can allocate the 4 outgoing - // arg slots on the stack frame if there are no other calls. - compUsesThrowHelper = true; - if (!fgUseThrowHelperBlocks() && (kind != SCK_FAIL_FAST)) { - // We'll create a throw block in-place then (for better debugging) - // It's not needed for fail fast, since it's not recoverable anyway. - return nullptr; + // FailFast will still use a thrwo helper, even in debuggable modes. + // + return; } - const static BBjumpKinds jumpKinds[] = { - BBJ_NONE, // SCK_NONE - BBJ_THROW, // SCK_RNGCHK_FAIL - BBJ_THROW, // SCK_DIV_BY_ZERO - BBJ_THROW, // SCK_ARITH_EXCP, SCK_OVERFLOW - BBJ_THROW, // SCK_ARG_EXCPN - BBJ_THROW, // SCK_ARG_RNG_EXCPN - BBJ_THROW, // SCK_FAIL_FAST - }; + JITDUMP(FMT_BB " requires throw helper block for %s\n", srcBlk->bbNum, sckName(kind)); - noway_assert(sizeof(jumpKinds) == SCK_COUNT); // sanity check + unsigned const refData = (kind == SCK_FAIL_FAST) ? 0 : bbThrowIndex(srcBlk); - /* First look for an existing entry that matches what we're looking for */ + // Record that the code will call a THROW_HELPER + // so on Windows Amd64 we can allocate the 4 outgoing + // arg slots on the stack frame if there are no other calls. + compUsesThrowHelper = true; + // Look for an existing entry that matches what we're looking for + // AddCodeDsc* add = fgFindExcptnTarget(kind, refData); - if (add) // found it + if (add != nullptr) { - return add->acdDstBlk; + return; } - /* We have to allocate a new entry and prepend it to the list */ + assert(!fgRngChkThrowAdded); + // Allocate a new entry and prepend it to the list + // add = new (this, CMK_Unknown) AddCodeDsc; add->acdData = refData; add->acdKind = kind; @@ -3651,147 +3678,205 @@ BasicBlock* Compiler::fgAddCodeRef(BasicBlock* srcBlk, unsigned refData, Special fgAddCodeList = add; - /* Create the target basic block */ + // Defer creating of the blocks until later. + // + add->acdDstBlk = srcBlk; +} - BasicBlock* newBlk; +//------------------------------------------------------------------------ +// fgCreateThrowHelperBlocks: create the needed throw helpers +// +// Returns: +// Suitable phase status +// +PhaseStatus Compiler::fgCreateThrowHelperBlocks() +{ + if (fgAddCodeList == nullptr) + { + return PhaseStatus::MODIFIED_NOTHING; + } - newBlk = add->acdDstBlk = fgNewBBinRegion(jumpKinds[kind], srcBlk, /* runRarely */ true, /* insertAtEnd */ true); + // We should not have added throw helper blocks yet. + // + assert(!fgRngChkThrowAdded); -#ifdef DEBUG - if (verbose) + const static BBjumpKinds jumpKinds[] = { + BBJ_NONE, // SCK_NONE + BBJ_THROW, // SCK_RNGCHK_FAIL + BBJ_THROW, // SCK_DIV_BY_ZERO + BBJ_THROW, // SCK_ARITH_EXCP, SCK_OVERFLOW + BBJ_THROW, // SCK_ARG_EXCPN + BBJ_THROW, // SCK_ARG_RNG_EXCPN + BBJ_THROW, // SCK_FAIL_FAST + }; + + noway_assert(sizeof(jumpKinds) == SCK_COUNT); // sanity check + + for (AddCodeDsc* add = fgAddCodeList; add != nullptr; add = add->acdNext) { - const char* msgWhere = ""; - if (!srcBlk->hasTryIndex() && !srcBlk->hasHndIndex()) - { - msgWhere = "non-EH region"; - } - else if (!srcBlk->hasTryIndex()) - { - msgWhere = "handler"; - } - else if (!srcBlk->hasHndIndex()) - { - msgWhere = "try"; - } - else if (srcBlk->getTryIndex() < srcBlk->getHndIndex()) - { - msgWhere = "try"; - } - else + // Create the target basic block in the region indicated by srcBlk. + // + BasicBlock* const srcBlk = add->acdDstBlk; + + // Double-check that this is a fail fast, or that srcBlk hasn't changed EH + // regions since the time the descriptor was created. + // + assert((add->acdKind == SCK_FAIL_FAST) || (bbThrowIndex(srcBlk) == add->acdData)); + + BasicBlock* const newBlk = + fgNewBBinRegion(jumpKinds[add->acdKind], srcBlk, /* runRarely */ true, /* insertAtEnd */ true); + + // Update the descriptor + // + add->acdDstBlk = newBlk; + +#ifdef DEBUG + if (verbose) { - msgWhere = "handler"; + const char* msgWhere = ""; + if (!srcBlk->hasTryIndex() && !srcBlk->hasHndIndex()) + { + msgWhere = "non-EH region"; + } + else if (!srcBlk->hasTryIndex()) + { + msgWhere = "handler"; + } + else if (!srcBlk->hasHndIndex()) + { + msgWhere = "try"; + } + else if (srcBlk->getTryIndex() < srcBlk->getHndIndex()) + { + msgWhere = "try"; + } + else + { + msgWhere = "handler"; + } + + const char* msg; + switch (add->acdKind) + { + case SCK_RNGCHK_FAIL: + msg = " for RNGCHK_FAIL"; + break; + case SCK_DIV_BY_ZERO: + msg = " for DIV_BY_ZERO"; + break; + case SCK_OVERFLOW: + msg = " for OVERFLOW"; + break; + case SCK_ARG_EXCPN: + msg = " for ARG_EXCPN"; + break; + case SCK_ARG_RNG_EXCPN: + msg = " for ARG_RNG_EXCPN"; + break; + case SCK_FAIL_FAST: + msg = " for FAIL_FAST"; + break; + default: + msg = " for ??"; + break; + } + + printf("\nAdding throw helper " FMT_BB " for %s in %s%s (inspired by " FMT_BB ")\n", newBlk->bbNum, + sckName(add->acdKind), msgWhere, msg, srcBlk->bbNum); } +#endif // DEBUG + + // Mark the block as added by the compiler and not removable by future flow + // graph optimizations. Note that no bbJumpDest points to these blocks. + // + newBlk->bbFlags |= BBF_IMPORTED; + newBlk->bbFlags |= BBF_DONT_REMOVE; + + // Figure out what code to insert + // + int helper = CORINFO_HELP_UNDEF; - const char* msg; - switch (kind) + switch (add->acdKind) { case SCK_RNGCHK_FAIL: - msg = " for RNGCHK_FAIL"; + helper = CORINFO_HELP_RNGCHKFAIL; break; + case SCK_DIV_BY_ZERO: - msg = " for DIV_BY_ZERO"; + helper = CORINFO_HELP_THROWDIVZERO; break; - case SCK_OVERFLOW: - msg = " for OVERFLOW"; + + case SCK_ARITH_EXCPN: + helper = CORINFO_HELP_OVERFLOW; + noway_assert(SCK_OVERFLOW == SCK_ARITH_EXCPN); break; + case SCK_ARG_EXCPN: - msg = " for ARG_EXCPN"; + helper = CORINFO_HELP_THROW_ARGUMENTEXCEPTION; break; + case SCK_ARG_RNG_EXCPN: - msg = " for ARG_RNG_EXCPN"; + helper = CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION; break; + case SCK_FAIL_FAST: - msg = " for FAIL_FAST"; + helper = CORINFO_HELP_FAIL_FAST; break; + default: - msg = " for ??"; - break; + noway_assert(!"unexpected code addition kind"); } - printf("\nfgAddCodeRef - Add BB in %s%s, new block %s\n", msgWhere, msg, add->acdDstBlk->dspToString()); - } -#endif // DEBUG - - /* Mark the block as added by the compiler and not removable by future flow - graph optimizations. Note that no bbJumpDest points to these blocks. */ - - newBlk->bbFlags |= BBF_IMPORTED; - newBlk->bbFlags |= BBF_DONT_REMOVE; - - /* Remember that we're adding a new basic block */ - - fgAddCodeModf = true; - - /* Now figure out what code to insert */ + noway_assert(helper != CORINFO_HELP_UNDEF); - GenTreeCall* tree; - int helper = CORINFO_HELP_UNDEF; - - switch (kind) - { - case SCK_RNGCHK_FAIL: - helper = CORINFO_HELP_RNGCHKFAIL; - break; - - case SCK_DIV_BY_ZERO: - helper = CORINFO_HELP_THROWDIVZERO; - break; - - case SCK_ARITH_EXCPN: - helper = CORINFO_HELP_OVERFLOW; - noway_assert(SCK_OVERFLOW == SCK_ARITH_EXCPN); - break; - - case SCK_ARG_EXCPN: - helper = CORINFO_HELP_THROW_ARGUMENTEXCEPTION; - break; - - case SCK_ARG_RNG_EXCPN: - helper = CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION; - break; + // Add the appropriate helper call. + // + GenTreeCall* tree = gtNewHelperCallNode(helper, TYP_VOID); - case SCK_FAIL_FAST: - helper = CORINFO_HELP_FAIL_FAST; - break; + // There are no args here but fgMorphArgs has side effects + // such as setting the outgoing arg area (which is necessary + // on AMD if there are any calls). + // + tree = fgMorphArgs(tree); - default: - noway_assert(!"unexpected code addition kind"); - return nullptr; + // Store the tree in the new basic block. + // + if (fgNodeThreading != NodeThreading::LIR) + { + fgInsertStmtAtEnd(newBlk, fgNewStmtFromTree(tree)); + } + else + { + LIR::AsRange(newBlk).InsertAtEnd(LIR::SeqTree(this, tree)); + } } - noway_assert(helper != CORINFO_HELP_UNDEF); - - // Add the appropriate helper call. - tree = gtNewHelperCallNode(helper, TYP_VOID); + fgRngChkThrowAdded = true; - // There are no args here but fgMorphArgs has side effects - // such as setting the outgoing arg area (which is necessary - // on AMD if there are any calls). - tree = fgMorphArgs(tree); - - // Store the tree in the new basic block. - if (!srcBlk->IsLIR()) - { - fgInsertStmtAtEnd(newBlk, fgNewStmtFromTree(tree)); - } - else - { - LIR::AsRange(newBlk).InsertAtEnd(LIR::SeqTree(this, tree)); - } - - return add->acdDstBlk; + return PhaseStatus::MODIFIED_EVERYTHING; } -/***************************************************************************** - * Finds the block to jump to, to throw a given kind of exception - * We maintain a cache of one AddCodeDsc for each kind, to make searching fast. - * Note : Each block uses the same (maybe shared) block as the jump target for - * a given type of exception - */ - +//------------------------------------------------------------------------ +// fgFindExcptnTarget: finds the block to jump that will throw a given kind of exception +// +// Arguments: +// kind - kind of exception to throw +// block - block where we need to throw an exception +// +// Return Value: +// Code descriptor for the appropriate throw helper block, or nullptr if no such +// descriptor exists +// +// Notes: +// We maintain a cache of one AddCodeDsc for each kind, to make searching fast. +// +// Each block in an EH region uses the same (maybe shared) block as the jump target for +// this exception kind. +// Compiler::AddCodeDsc* Compiler::fgFindExcptnTarget(SpecialCodeKind kind, unsigned refData) { assert(fgUseThrowHelperBlocks() || (kind == SCK_FAIL_FAST)); + if (!(fgExcptnTargetCache[kind] && // Try the cached value first fgExcptnTargetCache[kind]->acdData == refData)) { @@ -3807,46 +3892,12 @@ Compiler::AddCodeDsc* Compiler::fgFindExcptnTarget(SpecialCodeKind kind, unsigne } } - fgExcptnTargetCache[kind] = add; // Cache it + fgExcptnTargetCache[kind] = add; } return fgExcptnTargetCache[kind]; } -/***************************************************************************** - * - * The given basic block contains an array range check; return the label this - * range check is to jump to upon failure. - */ - -//------------------------------------------------------------------------ -// fgRngChkTarget: Create/find the appropriate "range-fail" label for the block. -// -// Arguments: -// srcBlk - the block that needs an entry; -// kind - the kind of exception; -// -// Return Value: -// The target throw helper block this check jumps to upon failure. -// -BasicBlock* Compiler::fgRngChkTarget(BasicBlock* block, SpecialCodeKind kind) -{ -#ifdef DEBUG - if (verbose) - { - printf("*** Computing fgRngChkTarget for block " FMT_BB "\n", block->bbNum); - if (!block->IsLIR()) - { - gtDispStmt(compCurStmt); - } - } -#endif // DEBUG - - /* We attach the target label to the containing try block (if any) */ - noway_assert(!compIsForInlining()); - return fgAddCodeRef(block, bbThrowIndex(block), kind); -} - //------------------------------------------------------------------------ // fgSetTreeSeq: Sequence the tree, setting the "gtPrev" and "gtNext" links. // diff --git a/src/coreclr/jit/gschecks.cpp b/src/coreclr/jit/gschecks.cpp index 228d14d48b887..11752d9f90f5f 100644 --- a/src/coreclr/jit/gschecks.cpp +++ b/src/coreclr/jit/gschecks.cpp @@ -30,7 +30,7 @@ PhaseStatus Compiler::gsPhase() unsigned const prevBBCount = fgBBcount; gsGSChecksInitCookie(); - fgAddCodeRef(fgLastBB, 0, SCK_FAIL_FAST); + fgAddCodeRef(fgLastBB, SCK_FAIL_FAST); if (compGSReorderStackLayout) { diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 57d3b7d801e88..8c02648ca9405 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -4243,62 +4243,6 @@ void Compiler::fgMoveOpsLeft(GenTree* tree) #endif -/*****************************************************************************/ - -void Compiler::fgSetRngChkTarget(GenTree* tree, bool delay) -{ - if (tree->OperIs(GT_BOUNDS_CHECK)) - { - GenTreeBoundsChk* const boundsChk = tree->AsBoundsChk(); - BasicBlock* const failBlock = fgSetRngChkTargetInner(boundsChk->gtThrowKind, delay); - if (failBlock != nullptr) - { - boundsChk->gtIndRngFailBB = failBlock; - } - } - else if (tree->OperIs(GT_INDEX_ADDR)) - { - GenTreeIndexAddr* const indexAddr = tree->AsIndexAddr(); - BasicBlock* const failBlock = fgSetRngChkTargetInner(SCK_RNGCHK_FAIL, delay); - if (failBlock != nullptr) - { - indexAddr->gtIndRngFailBB = failBlock; - } - } - else - { - noway_assert(tree->OperIs(GT_ARR_ELEM)); - fgSetRngChkTargetInner(SCK_RNGCHK_FAIL, delay); - } -} - -BasicBlock* Compiler::fgSetRngChkTargetInner(SpecialCodeKind kind, bool delay) -{ - if (opts.MinOpts()) - { - delay = false; - } - - if (!opts.compDbgCode) - { - if (!delay && !compIsForInlining()) - { - // Create/find the appropriate "range-fail" label - return fgRngChkTarget(compCurBB, kind); - } - } - else - { - // Tell downstream code that we will end up with a call so that it - // knows this is not a leaf function. For optimized code this is - // handled by fgRngChkTarget that is called above either in morph or - // simple lowering. - compUsesThrowHelper = true; - } - - return nullptr; -} - //------------------------------------------------------------------------ // fgMorphIndexAddr: Expand a GT_INDEX_ADDR node and fully morph the child operands. // @@ -4358,7 +4302,7 @@ GenTree* Compiler::fgMorphIndexAddr(GenTreeIndexAddr* indexAddr) // Note this will always be true unless JitSkipArrayBoundCheck() is used if (indexAddr->IsBoundsChecked()) { - fgSetRngChkTarget(indexAddr); + fgAddCodeRef(compCurBB, SCK_RNGCHK_FAIL); } return indexAddr; @@ -4562,7 +4506,7 @@ GenTree* Compiler::fgMorphIndexAddr(GenTreeIndexAddr* indexAddr) addr->SetHasOrderingSideEffect(); tree = gtNewOperNode(GT_COMMA, tree->TypeGet(), boundsCheck, tree); - fgSetRngChkTarget(boundsCheck); + fgAddCodeRef(compCurBB, boundsCheck->gtThrowKind); } if (indexDefn != nullptr) @@ -9242,7 +9186,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA } if (tree->OperIs(GT_CAST) && tree->gtOverflow()) { - fgAddCodeRef(compCurBB, bbThrowIndex(compCurBB), SCK_OVERFLOW); + fgAddCodeRef(compCurBB, SCK_OVERFLOW); } typ = tree->TypeGet(); @@ -9438,7 +9382,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA if ((exSetFlags & ExceptionSetFlags::ArithmeticException) != ExceptionSetFlags::None) { - fgAddCodeRef(compCurBB, bbThrowIndex(compCurBB), SCK_OVERFLOW); + fgAddCodeRef(compCurBB, SCK_OVERFLOW); } else { @@ -9447,7 +9391,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA if ((exSetFlags & ExceptionSetFlags::DivideByZeroException) != ExceptionSetFlags::None) { - fgAddCodeRef(compCurBB, bbThrowIndex(compCurBB), SCK_DIV_BY_ZERO); + fgAddCodeRef(compCurBB, SCK_DIV_BY_ZERO); } else { @@ -9464,7 +9408,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA ExceptionSetFlags exSetFlags = tree->OperExceptions(this); if ((exSetFlags & ExceptionSetFlags::DivideByZeroException) != ExceptionSetFlags::None) { - fgAddCodeRef(compCurBB, bbThrowIndex(compCurBB), SCK_DIV_BY_ZERO); + fgAddCodeRef(compCurBB, SCK_DIV_BY_ZERO); } else { @@ -9483,7 +9427,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA // Add the excptn-throwing basic block to jump to on overflow - fgAddCodeRef(compCurBB, bbThrowIndex(compCurBB), SCK_OVERFLOW); + fgAddCodeRef(compCurBB, SCK_OVERFLOW); // We can't do any commutative morphing for overflow instructions @@ -9563,11 +9507,12 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA noway_assert(varTypeIsFloating(op1->TypeGet())); - fgAddCodeRef(compCurBB, bbThrowIndex(compCurBB), SCK_ARITH_EXCPN); + fgAddCodeRef(compCurBB, SCK_ARITH_EXCPN); break; case GT_BOUNDS_CHECK: - fgSetRngChkTarget(tree); + + fgAddCodeRef(compCurBB, tree->AsBoundsChk()->gtThrowKind); break; case GT_IND: @@ -12876,7 +12821,7 @@ GenTree* Compiler::fgMorphTree(GenTree* tree, MorphAddrContext* mac) if (fgGlobalMorph) { - fgSetRngChkTarget(tree, false); + fgAddCodeRef(compCurBB, SCK_RNGCHK_FAIL); } break;