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

Code before:
            JITDUMP("Merge assertions created by " FMT_BB " for " FMT_BB "\n", pred->bbNum, block->bbNum);
            Compiler::optDumpAssertionIndices(assertions, "\n");
        }
    }
    // Get assertions from bbAssertionIn.
    else if (op->IsLocal())
    {
        assertions = block->bbAssertionIn;

        // bbAssertionIn is a bit conservative and will not include intra-block assertions.
        // e.g. created by GT_BOUNDS_CHECK nodes prior to the 'op' in the current block.
        // For that, we walk the trees in the block until we find "op" and collect assertions
        // along the way. It doesn't seem to be profitable for anything other than bounds checks
        // (ArrBnds assertions), so we limit the search to only those blocks that may have bounds
        // checks. It also helps reduce the cost of this search as it's not cheap.
        //
        if (block->HasFlag(BBF_MAY_HAVE_BOUNDS_CHECKS))
        {
            // We're going to be adding to 'assertions', so make a copy first.
            assertions = BitVecOps::MakeCopy(m_pCompiler->apTraits, assertions);

            // JIT-TP: Limit the search budget to avoid spending too much time here.
            int budget = 32;
            for (Statement* stmt : block->Statements())
            {
                AssertionsAccumulator visitor(m_pCompiler, &budget, &assertions, op);
                if (visitor.WalkTree(stmt->GetRootNodePointer(), nullptr) == Compiler::fgWalkResult::WALK_ABORT)
                {
                    break;
                }
            }
        }
    }

    if (!BitVecOps::MayBeUninit(assertions))
    {
        // Perform the merge step to fine tune the range value.
        MergeEdgeAssertions(op->AsLclVarCommon(), assertions, pRange);
    }
}

// Compute the range for a binary operation.
Range RangeCheck::ComputeRangeForBinOp(BasicBlock* block, GenTreeOp* binop, bool monIncreasing DEBUGARG(int indent))
{
    assert(binop->OperIs(GT_ADD, GT_XOR, GT_AND, GT_RSH, GT_RSZ, GT_LSH, GT_UMOD, GT_MUL));

    // For XOR we only care about Log2 pattern for now
    if (binop->OperIs(GT_XOR))
    {
        int upperBound;
        if (m_pCompiler->vnStore->IsVNLog2(m_pCompiler->vnStore->VNConservativeNormalValue(binop->gtVNPair),

Review comment (suggestion):
NIT: you don't access `budget` later, so it could be passed to the visitor by value.

Code after:
    {
        const BasicBlock* pred = op->AsPhiArg()->gtPredBB;
        assertions             = m_pCompiler->optGetEdgeAssertions(block, pred);
        if (!BitVecOps::MayBeUninit(assertions))
        {
            JITDUMP("Merge assertions created by " FMT_BB " for " FMT_BB "\n", pred->bbNum, block->bbNum);
            Compiler::optDumpAssertionIndices(assertions, "\n");
        }
    }
    // Get assertions from bbAssertionIn.
    else if (op->IsLocal())
    {
        assertions = block->bbAssertionIn;

        // bbAssertionIn is a bit conservative and will not include intra-block assertions.
        // e.g. created by GT_BOUNDS_CHECK nodes prior to the 'op' in the current block.
        // For that, we walk the trees in the block until we find "op" and collect assertions
        // along the way. It doesn't seem to be profitable for anything other than bounds checks
        // (ArrBnds assertions), so we limit the search to only those blocks that may have bounds
        // checks. It also helps reduce the cost of this search as it's not cheap.
        //
        if (block->HasFlag(BBF_MAY_HAVE_BOUNDS_CHECKS))
        {
            // We're going to be adding to 'assertions', so make a copy first.
            assertions = BitVecOps::MakeCopy(m_pCompiler->apTraits, assertions);

            // JIT-TP: Limit the search budget to avoid spending too much time here.
            int budget = 50;
            for (Statement* stmt : block->Statements())
            {
                AssertionsAccumulator visitor(m_pCompiler, budget, &assertions, op);
                if (visitor.WalkTree(stmt->GetRootNodePointer(), nullptr) == Compiler::fgWalkResult::WALK_ABORT)
                {
                    break;
                }
                budget = visitor.GetBudgetLeft();
            }
        }
    }

    if (!BitVecOps::MayBeUninit(assertions))
    {
        // Perform the merge step to fine tune the range value.
        MergeEdgeAssertions(op->AsLclVarCommon(), assertions, pRange);
    }
}

// Compute the range for a binary operation.
Range RangeCheck::ComputeRangeForBinOp(BasicBlock* block, GenTreeOp* binop, bool monIncreasing DEBUGARG(int indent))
{
    assert(binop->OperIs(GT_ADD, GT_XOR, GT_AND, GT_RSH, GT_RSZ, GT_LSH, GT_UMOD, GT_MUL));