diff --git a/src/coreclr/jit/codegenarm64.cpp b/src/coreclr/jit/codegenarm64.cpp index 3aca70997906dc..ebe7245fb424af 100644 --- a/src/coreclr/jit/codegenarm64.cpp +++ b/src/coreclr/jit/codegenarm64.cpp @@ -5937,7 +5937,7 @@ BasicBlock* CodeGen::genGetThrowHelper(SpecialCodeKind codeKind) { // For code with throw helper blocks, find and use the helper block for // raising the exception. The block may be shared by other trees too. - Compiler::AddCodeDsc* add = compiler->fgFindExcptnTarget(codeKind, compiler->compCurBB); + Compiler::AddCodeDsc* add = compiler->fgGetExcptnTarget(codeKind, compiler->compCurBB); assert((add != nullptr) && ("ERROR: failed to find exception throw block")); assert(add->acdUsed); excpRaisingBlock = add->acdDstBlk; diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index 892933a516b183..2e383354652941 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -1623,7 +1623,7 @@ void CodeGen::genExitCode(BasicBlock* block) // genJumpToThrowHlpBlk: Generate code for an out-of-line exception. // // Notes: -// For code that uses throw helper blocks, we share the helper blocks created by fgAddCodeRef(). +// For code that uses throw helper blocks, we share the helper blocks. // Otherwise, we generate the 'throw' inline. // // Arguments: @@ -1653,7 +1653,7 @@ void CodeGen::genJumpToThrowHlpBlk(emitJumpKind jumpKind, SpecialCodeKind codeKi excpRaisingBlock = failBlk; #ifdef DEBUG - Compiler::AddCodeDsc* add = compiler->fgFindExcptnTarget(codeKind, compiler->compCurBB); + Compiler::AddCodeDsc* add = compiler->fgGetExcptnTarget(codeKind, compiler->compCurBB); assert(add->acdUsed); assert(excpRaisingBlock == add->acdDstBlk); #if !FEATURE_FIXED_OUT_ARGS @@ -1664,7 +1664,7 @@ void CodeGen::genJumpToThrowHlpBlk(emitJumpKind jumpKind, SpecialCodeKind codeKi else { // Find the helper-block which raises the exception. - Compiler::AddCodeDsc* add = compiler->fgFindExcptnTarget(codeKind, compiler->compCurBB); + Compiler::AddCodeDsc* add = compiler->fgGetExcptnTarget(codeKind, compiler->compCurBB); assert((add != nullptr) && ("ERROR: failed to find exception throw block")); assert(add->acdUsed); excpRaisingBlock = add->acdDstBlk; diff --git a/src/coreclr/jit/codegenloongarch64.cpp b/src/coreclr/jit/codegenloongarch64.cpp index f05e22fbcd0510..25968b11ee863c 100644 --- a/src/coreclr/jit/codegenloongarch64.cpp +++ b/src/coreclr/jit/codegenloongarch64.cpp @@ -6514,7 +6514,7 @@ inline void CodeGen::genJumpToThrowHlpBlk_la( excpRaisingBlock = failBlk; #ifdef DEBUG - Compiler::AddCodeDsc* add = compiler->fgFindExcptnTarget(codeKind, compiler->compCurBB); + Compiler::AddCodeDsc* add = compiler->fgGetExcptnTarget(codeKind, compiler->compCurBB); assert(add->acdUsed); assert(excpRaisingBlock == add->acdDstBlk); #if !FEATURE_FIXED_OUT_ARGS @@ -6525,7 +6525,7 @@ inline void CodeGen::genJumpToThrowHlpBlk_la( else { // Find the helper-block which raises the exception. - Compiler::AddCodeDsc* add = compiler->fgFindExcptnTarget(codeKind, compiler->compCurBB); + Compiler::AddCodeDsc* add = compiler->fgGetExcptnTarget(codeKind, compiler->compCurBB); assert((add != nullptr) && ("ERROR: failed to find exception throw block")); assert(add->acdUsed); excpRaisingBlock = add->acdDstBlk; diff --git a/src/coreclr/jit/codegenriscv64.cpp b/src/coreclr/jit/codegenriscv64.cpp index 3b107cebce0aa1..d5aba4d3d59ec0 100644 --- a/src/coreclr/jit/codegenriscv64.cpp +++ b/src/coreclr/jit/codegenriscv64.cpp @@ -6202,7 +6202,7 @@ void CodeGen::genJumpToThrowHlpBlk_la( excpRaisingBlock = failBlk; #ifdef DEBUG - Compiler::AddCodeDsc* add = compiler->fgFindExcptnTarget(codeKind, compiler->compCurBB); + Compiler::AddCodeDsc* add = compiler->fgGetExcptnTarget(codeKind, compiler->compCurBB); assert(add->acdUsed); assert(excpRaisingBlock == add->acdDstBlk); #if !FEATURE_FIXED_OUT_ARGS @@ -6213,7 +6213,7 @@ void CodeGen::genJumpToThrowHlpBlk_la( else { // Find the helper-block which raises the exception. - Compiler::AddCodeDsc* add = compiler->fgFindExcptnTarget(codeKind, compiler->compCurBB); + Compiler::AddCodeDsc* add = compiler->fgGetExcptnTarget(codeKind, compiler->compCurBB); assert((add != nullptr) && ("ERROR: failed to find exception throw block")); assert(add->acdUsed); excpRaisingBlock = add->acdDstBlk; diff --git a/src/coreclr/jit/codegenwasm.cpp b/src/coreclr/jit/codegenwasm.cpp index 3f9520e66cf165..db5bdaede2f718 100644 --- a/src/coreclr/jit/codegenwasm.cpp +++ b/src/coreclr/jit/codegenwasm.cpp @@ -1192,7 +1192,7 @@ void CodeGen::genCodeForNullCheck(GenTreeIndir* tree) // TODO-WASM: refactor once we have implemented other cases invoking throw helpers if (compiler->fgUseThrowHelperBlocks()) { - Compiler::AddCodeDsc* const add = compiler->fgFindExcptnTarget(SCK_NULL_CHECK, compiler->compCurBB); + Compiler::AddCodeDsc* const add = compiler->fgGetExcptnTarget(SCK_NULL_CHECK, compiler->compCurBB); if (add == nullptr) { diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index d3bc2641d63acd..005999a216356f 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -4898,10 +4898,6 @@ 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()) { // Conditional to switch conversion, and switch peeling diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 72e049f1e5aa2d..8a6d3ce89eec17 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -6774,7 +6774,7 @@ class Compiler struct AddCodeDsc { - // After fgCreateThrowHelperBlocks, the block to which + // The block to which // we jump to raise the exception. BasicBlock* acdDstBlk; @@ -6838,16 +6838,15 @@ class Compiler private: static unsigned acdHelper(SpecialCodeKind codeKind); - bool fgRngChkThrowAdded = false; AddCodeDscMap* fgAddCodeDscMap = nullptr; - - void fgAddCodeRef(BasicBlock* srcBlk, SpecialCodeKind kind); - PhaseStatus fgCreateThrowHelperBlocks(); + AddCodeDsc* fgCreateAddCodeDsc(BasicBlock* fromBlock, SpecialCodeKind kind); + void fgCreateThrowHelperBlock(AddCodeDsc* add); public: + bool fgRngChkThrowAdded = false; bool fgHasAddCodeDscMap() const { return fgAddCodeDscMap != nullptr; } - AddCodeDsc* fgFindExcptnTarget(SpecialCodeKind kind, BasicBlock* fromBlock); + AddCodeDsc* fgGetExcptnTarget(SpecialCodeKind kind, BasicBlock* fromBlock, bool createIfNeeded = false); bool fgUseThrowHelperBlocks(); void fgCreateThrowHelperBlockCode(AddCodeDsc* add); void fgSequenceLocals(Statement* stmt); diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index b255293417d487..1a288a4bed8293 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -3384,53 +3384,30 @@ Compiler::AddCodeDscMap* Compiler::fgGetAddCodeDscMap() } //------------------------------------------------------------------------ -// fgAddCodeRef: Indicate that a particular throw helper block will +// fgCreateAddCodeDsc: Indicate that a particular throw helper block will // be needed by the method. // // Arguments: // srcBlk - the block that needs an entry; // kind - the kind of exception; // -// Notes: -// You can call this method after throw helpers have been created, -// but it will assert if this entails creation of a new helper. +// Returns: +// newly added AddCodeDsc // -void Compiler::fgAddCodeRef(BasicBlock* srcBlk, SpecialCodeKind kind) +Compiler::AddCodeDsc* Compiler::fgCreateAddCodeDsc(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. + // Cannot allow new demands once we have created throw helper blocks // - compUsesThrowHelper = true; - - if (!fgUseThrowHelperBlocks() && (kind != SCK_FAIL_FAST)) - { - // FailFast will still use a common throw helper, even in debuggable modes. - // - return; - } + assert(!fgRngChkThrowAdded); // Fetch block data and designator // AcdKeyDesignator dsg = AcdKeyDesignator::KD_NONE; unsigned const refData = (kind == SCK_FAIL_FAST) ? 0 : bbThrowIndex(srcBlk, &dsg); - // Look for an existing entry that matches what we're looking for - // - AddCodeDsc* add = fgFindExcptnTarget(kind, srcBlk); - - if (add != nullptr) - { - JITDUMP(FMT_BB " requires throw helper block for %s, sharing ACD%u (data 0x%08x)\n", srcBlk->bbNum, - sckName(kind), add->acdNum, refData); - return; - } - - assert(!fgRngChkThrowAdded); - // Allocate a new entry and prepend it to the list // - add = new (this, CMK_Unknown) AddCodeDsc; + AddCodeDsc* add = new (this, CMK_BasicBlock) AddCodeDsc; add->acdDstBlk = nullptr; add->acdTryIndex = srcBlk->bbTryIndex; @@ -3467,25 +3444,26 @@ void Compiler::fgAddCodeRef(BasicBlock* srcBlk, SpecialCodeKind kind) assert(map->Lookup(key2, &add2)); assert(add == add2); #endif + + return add; } //------------------------------------------------------------------------ -// fgCreateThrowHelperBlocks: create the needed throw helpers +// fgCreateThrowHelperBlock: create a throw helper block // -// Returns: -// Suitable phase status +// Arguments: +// add -- addCodeDesc describing the block to create // -PhaseStatus Compiler::fgCreateThrowHelperBlocks() +// Notes: +// Creates a new block if necessary, and sets the add->acdDstBlk to the new block. +// +void Compiler::fgCreateThrowHelperBlock(AddCodeDsc* add) { - if (fgAddCodeDscMap == nullptr) + if (add->acdDstBlk != nullptr) { - return PhaseStatus::MODIFIED_NOTHING; + return; } - // We should not have added throw helper blocks yet. - // - assert(!fgRngChkThrowAdded); - const static BBKinds jumpKinds[] = { BBJ_ALWAYS, // SCK_NONE BBJ_THROW, // SCK_RNGCHK_FAIL @@ -3499,89 +3477,82 @@ PhaseStatus Compiler::fgCreateThrowHelperBlocks() noway_assert(sizeof(jumpKinds) == SCK_COUNT); // sanity check - for (AddCodeDsc* const add : AddCodeDscMap::ValueIteration(fgAddCodeDscMap)) - { - // Create the target basic block in the region indicated by the acd info - // - assert(add->acdKind != SCK_NONE); - bool const putInFilter = (add->acdKeyDsg == AcdKeyDesignator::KD_FLT); - BasicBlock* const newBlk = fgNewBBinRegion(jumpKinds[add->acdKind], add->acdTryIndex, add->acdHndIndex, - /* nearBlk */ nullptr, putInFilter, - /* runRarely */ true, /* insertAtEnd */ true); + // Create the target basic block in the region indicated by the acd info + // + assert(add->acdKind != SCK_NONE); + bool const putInFilter = (add->acdKeyDsg == AcdKeyDesignator::KD_FLT); + BasicBlock* const newBlk = fgNewBBinRegion(jumpKinds[add->acdKind], add->acdTryIndex, add->acdHndIndex, + /* nearBlk */ nullptr, putInFilter, + /* runRarely */ true, /* insertAtEnd */ true); - // Update the descriptor so future lookups can find the block - // - add->acdDstBlk = newBlk; + // Update the descriptor so future lookups can find the block + // + add->acdDstBlk = newBlk; #ifdef DEBUG - if (verbose) + if (verbose) + { + const char* msgWhere = ""; + switch (add->acdKeyDsg) { - const char* msgWhere = ""; - switch (add->acdKeyDsg) - { - case AcdKeyDesignator::KD_NONE: - msgWhere = "non-EH region"; - break; - - case AcdKeyDesignator::KD_HND: - msgWhere = "handler"; - break; + case AcdKeyDesignator::KD_NONE: + msgWhere = "non-EH region"; + break; - case AcdKeyDesignator::KD_TRY: - msgWhere = "try"; - break; + case AcdKeyDesignator::KD_HND: + msgWhere = "handler"; + break; - case AcdKeyDesignator::KD_FLT: - msgWhere = "filter"; - break; + case AcdKeyDesignator::KD_TRY: + msgWhere = "try"; + break; - default: - msgWhere = "? unexpected"; - } + case AcdKeyDesignator::KD_FLT: + msgWhere = "filter"; + break; - 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; - case SCK_NULL_CHECK: - msg = " for NULL_CHECK"; - break; - default: - msg = " for ??"; - break; - } + default: + msgWhere = "? unexpected"; + } - printf("\nAdding throw helper " FMT_BB " for ACD%u %s in %s%s\n", newBlk->bbNum, add->acdNum, - sckName(add->acdKind), msgWhere, msg); + 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; + case SCK_NULL_CHECK: + msg = " for NULL_CHECK"; + break; + default: + msg = " for ??"; + break; } -#endif // DEBUG - // Mark the block as added by the compiler and not removable by future flow - // graph optimizations. Note that no target block points to these blocks. - // - newBlk->SetFlags(BBF_IMPORTED | BBF_DONT_REMOVE); + printf("\nAdding throw helper " FMT_BB " for ACD%u %s in %s%s\n", newBlk->bbNum, add->acdNum, + sckName(add->acdKind), msgWhere, msg); } +#endif // DEBUG - fgRngChkThrowAdded = true; - - return PhaseStatus::MODIFIED_EVERYTHING; + // Mark the block as added by the compiler and not removable by future flow + // graph optimizations. Note that no target block points to these blocks. + // + newBlk->SetFlags(BBF_IMPORTED | BBF_DONT_REMOVE); } //------------------------------------------------------------------------ @@ -3627,6 +3598,10 @@ void Compiler::fgCreateThrowHelperBlockCode(AddCodeDsc* add) helper = CORINFO_HELP_FAIL_FAST; break; + case SCK_NULL_CHECK: + helper = CORINFO_HELP_THROWNULLREF; + break; + default: noway_assert(!"unexpected code addition kind"); } @@ -3637,7 +3612,9 @@ void Compiler::fgCreateThrowHelperBlockCode(AddCodeDsc* add) // GenTreeCall* tree = gtNewHelperCallNode(helper, TYP_VOID); - // There are no args here but fgMorphArgs has side effects + // For Wasm we may add an arg to the throw helper. + // + // Also fgMorphArgs has side effects // such as setting the outgoing arg area (which is necessary // on AMD if there are any calls). // @@ -3651,24 +3628,28 @@ void Compiler::fgCreateThrowHelperBlockCode(AddCodeDsc* add) } else { - LIR::AsRange(block).InsertAtEnd(tree); - LIR::ReadOnlyRange range(tree, tree); - m_pLowering->LowerRange(block, range); + LIR::Range range = LIR::SeqTree(this, tree); + GenTree* const firstNode = range.FirstNode(); + GenTree* const lastNode = range.LastNode(); + LIR::AsRange(block).InsertAtEnd(std::move(range)); + LIR::ReadOnlyRange blockRange(firstNode, lastNode); + m_pLowering->LowerRange(block, blockRange); } } //------------------------------------------------------------------------ -// fgFindExcptnTarget: finds the block to jump to that will throw a given kind of exception +// fgGetExcptnTarget: finds the block to jump to that will throw a given kind of exception // // Arguments: // kind -- kind of exception to throw // fromBlock -- block that will jump to the throw helper +// createIfNeeded -- create the block if it does not already exist // // Return Value: // Code descriptor for the appropriate throw helper block, or nullptr if no such -// descriptor exists. +// descriptor exists (only when createIfNeeded is false). // -Compiler::AddCodeDsc* Compiler::fgFindExcptnTarget(SpecialCodeKind kind, BasicBlock* fromBlock) +Compiler::AddCodeDsc* Compiler::fgGetExcptnTarget(SpecialCodeKind kind, BasicBlock* fromBlock, bool createIfNeeded) { assert(fgUseThrowHelperBlocks() || (kind == SCK_FAIL_FAST)); AddCodeDsc* add = nullptr; @@ -3678,20 +3659,14 @@ Compiler::AddCodeDsc* Compiler::fgFindExcptnTarget(SpecialCodeKind kind, BasicBl if (add == nullptr) { - // We shouldn't be asking for these blocks late in compilation - // unless we know there are entries to be found. - if (fgRngChkThrowAdded) - { - JITDUMP(FMT_BB ": unexpected request for new throw helper: kind %d (%s), data 0x%08x\n", fromBlock->bbNum, - kind, sckName(kind), key.Data()); + add = fgCreateAddCodeDsc(fromBlock, kind); - if (kind == SCK_NULL_CHECK) - { - NYI_WASM("Missing null check demand"); - } + // Create the block... + // + if (createIfNeeded) + { + fgCreateThrowHelperBlock(add); } - - assert(!fgRngChkThrowAdded); } return add; diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index de0064ca3a1b4d..1af33251457f5f 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -12115,7 +12115,7 @@ void Lowering::FinalizeOutgoingArgSpace() // Finish computing the outgoing args area size // // Need to make sure the MIN_ARG_AREA_FOR_CALL space is added to the frame if: - // 1. there are calls to THROW_HELPER methods. + // 1. there may be calls to THROW_HELPER methods. // 2. we are generating profiling Enter/Leave/TailCall hooks. This will ensure // that even methods without any calls will have outgoing arg area space allocated. // 3. We will be generating calls to PInvoke helpers. TODO: This shouldn't be required because diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 96d72b392793e0..ab9ede0e15e61f 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -2978,13 +2978,6 @@ GenTree* Compiler::fgMorphIndexAddr(GenTreeIndexAddr* indexAddr) indexAddr->Index() = fgMorphTree(indexAddr->Index()); indexAddr->AddAllEffectsFlags(indexAddr->Arr(), indexAddr->Index()); - // Mark the indirection node as needing a range check if necessary. - // Note this will always be true unless JitSkipArrayBoundCheck() is used - if (indexAddr->IsBoundsChecked()) - { - fgAddCodeRef(compCurBB, SCK_RNGCHK_FAIL); - } - return indexAddr; } @@ -3213,7 +3206,6 @@ GenTree* Compiler::fgMorphIndexAddr(GenTreeIndexAddr* indexAddr) addr->SetHasOrderingSideEffect(); tree = gtNewOperNode(GT_COMMA, tree->TypeGet(), boundsCheck, tree); - fgAddCodeRef(compCurBB, boundsCheck->gtThrowKind); } if (indexDefn != nullptr) @@ -7799,10 +7791,6 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA { return tree; } - if (tree->OperIs(GT_CAST) && tree->gtOverflow()) - { - fgAddCodeRef(compCurBB, SCK_OVERFLOW); - } typ = tree->TypeGet(); oper = tree->OperGet(); @@ -8031,21 +8019,13 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA if ((oper == GT_DIV) || (oper == GT_MOD)) { - if ((exSetFlags & ExceptionSetFlags::ArithmeticException) != ExceptionSetFlags::None) - { - fgAddCodeRef(compCurBB, SCK_OVERFLOW); - } - else + if ((exSetFlags & ExceptionSetFlags::ArithmeticException) == ExceptionSetFlags::None) { tree->gtFlags |= GTF_DIV_MOD_NO_OVERFLOW; } } - if ((exSetFlags & ExceptionSetFlags::DivideByZeroException) != ExceptionSetFlags::None) - { - fgAddCodeRef(compCurBB, SCK_DIV_BY_ZERO); - } - else + if ((exSetFlags & ExceptionSetFlags::DivideByZeroException) == ExceptionSetFlags::None) { tree->gtFlags |= GTF_DIV_MOD_NO_BY_ZERO; } @@ -8110,12 +8090,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA CM_OVF_OP: if (tree->gtOverflow()) { - // Add the excptn-throwing basic block to jump to on overflow - - fgAddCodeRef(compCurBB, SCK_OVERFLOW); - // We can't do any commutative morphing for overflow instructions - break; } @@ -8211,13 +8186,10 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA case GT_CKFINITE: noway_assert(varTypeIsFloating(op1->TypeGet())); - - fgAddCodeRef(compCurBB, SCK_ARITH_EXCPN); break; case GT_BOUNDS_CHECK: setMethodHasBoundsChecks(); - fgAddCodeRef(compCurBB, tree->AsBoundsChk()->gtThrowKind); break; case GT_IND: @@ -11366,14 +11338,6 @@ GenTree* Compiler::fgMorphHWIntrinsic(GenTreeHWIntrinsic* tree) hasImmediateOperand = true; } -#ifdef TARGET_XARCH - if (intrinsicId == NI_Vector128_op_Division || intrinsicId == NI_Vector256_op_Division) - { - fgAddCodeRef(compCurBB, SCK_DIV_BY_ZERO); - fgAddCodeRef(compCurBB, SCK_OVERFLOW); - } -#endif // TARGET_XARCH - // ------------------------------------------------------------------------ // Process the operands, if any // @@ -12576,11 +12540,6 @@ GenTree* Compiler::fgMorphTree(GenTree* tree, MorphAddrContext* mac) { tree->gtFlags |= tree->AsArrElem()->gtArrInds[dim]->gtFlags & GTF_ALL_EFFECT; } - - if (fgGlobalMorph) - { - fgAddCodeRef(compCurBB, SCK_RNGCHK_FAIL); - } break; case GT_PHI: diff --git a/src/coreclr/jit/stacklevelsetter.cpp b/src/coreclr/jit/stacklevelsetter.cpp index a7729322e0f942..87bb409001b2af 100644 --- a/src/coreclr/jit/stacklevelsetter.cpp +++ b/src/coreclr/jit/stacklevelsetter.cpp @@ -14,7 +14,7 @@ StackLevelSetter::StackLevelSetter(Compiler* compiler) , maxStackLevel(0) , memAllocator(compiler->getAllocator(CMK_CallArgs)) , putArgNumSlots(memAllocator) - , throwHelperBlocksUsed(comp->fgUseThrowHelperBlocks() && comp->compUsesThrowHelper) + , throwHelperBlocksUsed(comp->fgUseThrowHelperBlocks()) #if !FEATURE_FIXED_OUT_ARGS , framePointerRequired(compiler->codeGen->isFramePointerRequired()) #endif // !FEATURE_FIXED_OUT_ARGS @@ -50,11 +50,12 @@ PhaseStatus StackLevelSetter::DoPhase() // bool madeChanges = false; + comp->compUsesThrowHelper = false; + if (comp->fgHasAddCodeDscMap()) { if (comp->opts.OptimizationEnabled()) { - comp->compUsesThrowHelper = false; for (Compiler::AddCodeDsc* const add : Compiler::AddCodeDscMap::ValueIteration(comp->fgGetAddCodeDscMap())) { if (add->acdUsed) @@ -84,13 +85,17 @@ PhaseStatus StackLevelSetter::DoPhase() // for (Compiler::AddCodeDsc* const add : Compiler::AddCodeDscMap::ValueIteration(comp->fgGetAddCodeDscMap())) { - add->acdUsed = true; + comp->compUsesThrowHelper = true; + add->acdUsed = true; comp->fgCreateThrowHelperBlockCode(add); madeChanges = true; } } } + // We have added whatever throw helpers are needed, so set this flag + comp->fgRngChkThrowAdded = true; + return madeChanges ? PhaseStatus::MODIFIED_EVERYTHING : PhaseStatus::MODIFIED_NOTHING; } @@ -101,9 +106,10 @@ void StackLevelSetter::ProcessBlocks() { #ifndef TARGET_X86 // Outside x86 we do not need to compute pushed/popped stack slots. - // However, we do optimize throw-helpers and need to process the blocks for - // that, but only when optimizing. - if (!throwHelperBlocksUsed || comp->opts.OptimizationDisabled()) + // However, if we are using throw helpers, we also need to process the blocks + // to find where the helpers are needed and create the blocks and calls. + // + if (!throwHelperBlocksUsed) { return; } @@ -169,7 +175,7 @@ void StackLevelSetter::ProcessBlock(BasicBlock* block) // morph are likely still accurate, so we don't bother checking // if helpers are indeed used. // - bool checkForHelpers = comp->opts.OptimizationEnabled(); + bool checkForHelpers = true; #if !FEATURE_FIXED_OUT_ARGS // Even if not optimizing, if we have a moving SP frame, a shared helper may @@ -303,7 +309,7 @@ void StackLevelSetter::SetThrowHelperBlocks(GenTree* node, BasicBlock* block) // void StackLevelSetter::SetThrowHelperBlock(SpecialCodeKind kind, BasicBlock* block) { - Compiler::AddCodeDsc* add = comp->fgFindExcptnTarget(kind, block); + Compiler::AddCodeDsc* add = comp->fgGetExcptnTarget(kind, block, /* createIfNeeded */ true); assert(add != nullptr); // We expect we'll actually need this helper. @@ -326,15 +332,9 @@ void StackLevelSetter::SetThrowHelperBlock(SpecialCodeKind kind, BasicBlock* blo // For Linux/x86, we possibly need to insert stack alignment adjustment // before the first stack argument pushed for every call. But we // don't know what the stack alignment adjustment will be when - // we morph a tree that calls fgAddCodeRef(), so the stack depth + // we morph a tree that calls a throw helper, so the stack depth // number will be incorrect. For now, simply force all functions with - // these helpers to have EBP frames. It might be possible to make - // this less conservative. E.g., for top-level (not nested) calls - // without stack args, the stack pointer hasn't changed and stack - // depth will be known to be zero. Or, figure out a way to update - // or generate all required helpers after all stack alignment - // has been added, and the stack level at each call to fgAddCodeRef() - // is known, or can be recalculated. + // these helpers to have EBP frames. #if defined(UNIX_X86_ABI) framePointerRequired = true; #else // !defined(UNIX_X86_ABI)