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

Code before:
    bb0->SetFlagsRaw(BBF_EMPTY);
    bb0->bbPreorderNum       = numBlocks;
    bb0->bbPostorderNum      = dfsTree->GetPostOrderCount();
    initialLayout[numBlocks] = bb0;

    // -----------------------------------------------
    // (2) Build the intervals
    //
    // Allocate interval and scratch vectors. We'll use the scratch vector to keep track of
    // block intervals that end at a certain point.
    //
    fgWasmIntervals = new (this, CMK_WasmCfgLowering) jitstd::vector<WasmInterval*>(getAllocator(CMK_WasmCfgLowering));
    jitstd::vector<WasmInterval*> scratch(numBlocks, nullptr, getAllocator(CMK_WasmCfgLowering));

    for (unsigned int cursor = 0; cursor < numBlocks; cursor++)
    {
        BasicBlock* const block = initialLayout[cursor];

        // See if we entered any loops
        //
        FlowGraphNaturalLoop* const loop = loops->GetLoopByHeader(block);

        if (loop != nullptr)
        {
            // Find the loop's lexical extent given our ordering
            // (maybe memoize this during loop finding...)
            //
            // Note that cursor may end up pointing at BB0
            //
            unsigned endCursor = cursor;
            while ((endCursor < numBlocks) && loop->ContainsBlock(initialLayout[endCursor]))
            {
                endCursor++;
            }

            WasmInterval* const loopInterval = WasmInterval::NewLoop(this, block, initialLayout[endCursor]);

            // We assume here that a block is only the header of one loop.
            //
            fgWasmIntervals->push_back(loopInterval);
        }

        // Now see where block branches to...
        //
        WasmSuccessorEnumerator successors(this, block, /* useProfile */ true);
        for (BasicBlock* const succ : successors)
        {
            unsigned const succNum = succ->bbPreorderNum;

            // We ignore back edges; they don't inspire blocks.
            //

Review comment (suggestion):
Would `VisitLoopBlocksPostOrder` work too and be even faster? `NumLoopBlocks` still requires iterating the full set.

Code after:
    bb0->bbPostorderNum      = dfsTree->GetPostOrderCount();
    initialLayout[numBlocks] = bb0;

    // -----------------------------------------------
    // (2) Build the intervals
    //
    // Allocate interval and scratch vectors. We'll use the scratch vector to keep track of
    // block intervals that end at a certain point.
    //
    fgWasmIntervals = new (this, CMK_WasmCfgLowering) jitstd::vector<WasmInterval*>(getAllocator(CMK_WasmCfgLowering));
    jitstd::vector<WasmInterval*> scratch(numBlocks, nullptr, getAllocator(CMK_WasmCfgLowering));

    for (unsigned int cursor = 0; cursor < numBlocks; cursor++)
    {
        BasicBlock* const block = initialLayout[cursor];

        // See if we entered any loops
        //
        FlowGraphNaturalLoop* const loop = loops->GetLoopByHeader(block);

        if (loop != nullptr)
        {
            // Loop bodies are contiguous in the LaRPO, so the end position
            // is the header position plus the number of blocks in the loop.
            //
            unsigned endCursor = cursor + loop->NumLoopBlocks();
            assert(endCursor <= numBlocks);

#ifdef DEBUG
            unsigned endCursorCheck = cursor;
            while ((endCursorCheck < numBlocks) && loop->ContainsBlock(initialLayout[endCursorCheck]))
            {
                endCursorCheck++;
            }
            assert(endCursor == endCursorCheck);
#endif

            WasmInterval* const loopInterval = WasmInterval::NewLoop(this, block, initialLayout[endCursor]);

            // We assume here that a block is only the header of one loop.
            //
            fgWasmIntervals->push_back(loopInterval);
        }

        // Now see where block branches to...
        //
        WasmSuccessorEnumerator successors(this, block, /* useProfile */ true);
        for (BasicBlock* const succ : successors)
        {
            unsigned const succNum = succ->bbPreorderNum;