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

Code before:
    }

    // Try to lower CORINFO_HELP_MEMSET to unrollable STORE_BLK
    if (call->IsHelperCall(m_compiler, CORINFO_HELP_MEMSET) && LowerCallMemset(call, &nextNode))
    {
        return nextNode;
    }
#endif

    call->ClearOtherRegs();

#if HAS_FIXED_REGISTER_SET
    if ((call->gtCallType == CT_INDIRECT) && m_compiler->opts.Tier0OptimizationEnabled())
    {
        OptimizeCallIndirectTargetEvaluation(call);
    }
#endif

#if defined(TARGET_WASM)
    if (call->NeedsNullCheck())
    {
        // Prepare for explicit null check
        CallArg* thisArg = call->gtArgs.GetThisArg();
        thisArg->GetNode()->gtLIRFlags |= LIR::Flags::MultiplyUsed;
    }
#endif

    LowerArgsForCall(call);

    // note that everything generated from this point might run AFTER the outgoing args are placed
    GenTree* controlExpr          = nullptr;
    bool     callWasExpandedEarly = false;

    // for x86, this is where we record ESP for checking later to make sure stack is balanced

    // Check for Delegate.Invoke(). If so, we inline it. We get the
    // target-object and target-function from the delegate-object, and do
    // an indirect call.
    if (call->IsDelegateInvoke())
    {
        controlExpr = LowerDelegateInvoke(call);
    }
    else
    {
        //  Virtual and interface calls
        switch (call->gtFlags & GTF_CALL_VIRT_KIND_MASK)
        {
            case GTF_CALL_VIRT_STUB:
                controlExpr = LowerVirtualStubCall(call);
                break;


Review comment (suggestion):
This should be hidden in a method like `AfterLowerArgsForCall` that will be empty for `!TARGET_WASM` (in `lower.cpp`) and implemented in `lowerwasm.cpp`. Like `AfterLowerBlock`.

Also, this should technically be after `LowerArgsForCall` since it may modify the arguments (I don't think it is an actual problem for `this`).

Code after:
            case NI_System_SpanHelpers_ClearWithoutReferences:
                if (LowerCallMemset(call, &nextNode))
                {
                    return nextNode;
                }
                break;

            default:
                break;
        }
    }

    // Try to lower CORINFO_HELP_MEMCPY to unrollable STORE_BLK
    if (call->IsHelperCall(m_compiler, CORINFO_HELP_MEMCPY) && LowerCallMemmove(call, &nextNode))
    {
        return nextNode;
    }

    // Try to lower CORINFO_HELP_MEMSET to unrollable STORE_BLK
    if (call->IsHelperCall(m_compiler, CORINFO_HELP_MEMSET) && LowerCallMemset(call, &nextNode))
    {
        return nextNode;
    }
#endif

    call->ClearOtherRegs();

#if HAS_FIXED_REGISTER_SET
    if ((call->gtCallType == CT_INDIRECT) && m_compiler->opts.Tier0OptimizationEnabled())
    {
        OptimizeCallIndirectTargetEvaluation(call);
    }
#endif

    LowerArgsForCall(call);

    // note that everything generated from this point might run AFTER the outgoing args are placed
    GenTree* controlExpr          = nullptr;
    bool     callWasExpandedEarly = false;

    // for x86, this is where we record ESP for checking later to make sure stack is balanced

    // Check for Delegate.Invoke(). If so, we inline it. We get the
    // target-object and target-function from the delegate-object, and do
    // an indirect call.
    if (call->IsDelegateInvoke())
    {
        controlExpr = LowerDelegateInvoke(call);
    }
    else
    {