Repository: dotnet/runtime
File: src/coreclr/jit/lower.cpp (C++)

Code before:
        }
    }

    return next;
}

//----------------------------------------------------------------------------------------------
// LowerReturnSuspend:
//   Lower a GT_RETURN_SUSPEND by making it a terminator node.
//
// Arguments:
//   node - The node
//
void Lowering::LowerReturnSuspend(GenTree* node)
{
    assert(node->OperIs(GT_RETURN_SUSPEND));
    while (BlockRange().LastNode() != node)
    {
        BlockRange().Remove(BlockRange().LastNode(), true);
    }

    if (m_compiler->compMethodRequiresPInvokeFrame())
    {
        InsertPInvokeMethodEpilog(m_compiler->compCurBB DEBUGARG(node));
    }

    BasicBlock* block = m_compiler->compCurBB;
    if (!block->KindIs(BBJ_RETURN))
    {
        bool profileInconsistent = false;
        for (BasicBlock* const succBlock : block->Succs())
        {
            FlowEdge* const succEdge = m_compiler->fgRemoveAllRefPreds(succBlock, block);

            if (block->hasProfileWeight() && succBlock->hasProfileWeight())
            {
                succBlock->decreaseBBProfileWeight(succEdge->getLikelyWeight());
                profileInconsistent |= (succBlock->NumSucc() > 0);
            }
        }

        if (profileInconsistent)
        {
            JITDUMP("Flow removal of " FMT_BB " needs to be propagated. Data %s inconsistent.\n", block->bbNum,
                    m_compiler->fgPgoConsistent ? "is now" : "was already");
            m_compiler->fgPgoConsistent = false;
        }

        block->SetKind(BBJ_RETURN);

        m_compiler->fgInvalidateDfsTree();

Review comment (bug):
`InsertPInvokeMethodEpilog` asserts that `returnBB` is `BBJ_RETURN` (or ends with tailcall/jmp). In the scenario this change is addressing (`GT_RETURN_SUSPEND` in a non-`BBJ_RETURN` block), the epilog insertion still happens *before* the block is converted to `BBJ_RETURN`, so checked/debug builds can still trip the assertion. Convert the block to `BBJ_RETURN` (and clear outgoing edges) before calling `InsertPInvokeMethodEpilog`, or adjust the epilog insertion precondition accordingly.

Code after:
        }
    }

    return next;
}

//----------------------------------------------------------------------------------------------
// LowerReturnSuspend:
//   Lower a GT_RETURN_SUSPEND by making it a terminator node.
//
// Arguments:
//   node - The node
//
void Lowering::LowerReturnSuspend(GenTree* node)
{
    assert(node->OperIs(GT_RETURN_SUSPEND));
    while (BlockRange().LastNode() != node)
    {
        BlockRange().Remove(BlockRange().LastNode(), true);
    }

    BasicBlock* block = m_compiler->compCurBB;
    if (!block->KindIs(BBJ_RETURN))
    {
        bool profileInconsistent = false;
        for (BasicBlock* const succBlock : block->Succs())
        {
            FlowEdge* const succEdge = m_compiler->fgRemoveAllRefPreds(succBlock, block);

            if (block->hasProfileWeight() && succBlock->hasProfileWeight())
            {
                succBlock->decreaseBBProfileWeight(succEdge->getLikelyWeight());
                profileInconsistent |= (succBlock->NumSucc() > 0);
            }
        }

        if (profileInconsistent)
        {
            JITDUMP("Flow removal of " FMT_BB " needs to be propagated. Data %s inconsistent.\n", block->bbNum,
                    m_compiler->fgPgoConsistent ? "is now" : "was already");
            m_compiler->fgPgoConsistent = false;
        }

        block->SetKindAndTargetEdge(BBJ_RETURN);

        m_compiler->fgInvalidateDfsTree();
    }

    if (m_compiler->compMethodRequiresPInvokeFrame())
    {
        InsertPInvokeMethodEpilog(m_compiler->compCurBB DEBUGARG(node));