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

Code before:
{
    if ((node->gtLIRFlags & LIR::Flags::MultiplyUsed) == LIR::Flags::None)
    {
        return;
    }

    assert(node->IsValue());
    if (node->IsUnusedValue())
    {
        // Liveness removed the parent node - no need to do anything.
        node->gtLIRFlags &= ~LIR::Flags::MultiplyUsed;
        return;
    }

    if (node->OperIs(GT_LCL_VAR) && m_compiler->lvaGetDesc(node->AsLclVar())->lvIsRegCandidate())
    {
        // Will be allocated into its own register, no need for a temporary.
        node->gtLIRFlags &= ~LIR::Flags::MultiplyUsed;
        return;
    }

    // Note how due to the fact we're processing nodes in stack order,
    // we don't need to maintain free/busy sets, only a simple stack.
    regNumber reg = AllocateTemporaryRegister(genActualType(node));
    // If the node already has a regnum, trying to assign it a second one is no good.
    assert(node->GetRegNum() == REG_NA);
    node->SetRegNum(reg);
}

//------------------------------------------------------------------------
// ConsumeTemporaryRegForOperand: Consume the temporary register for a multiply-used operand.
//
// The contract with codegen is that such operands will have their register
// number set to a valid WASM local, to be "local.tee"d after the node is
// generated.
//
// Arguments:
//    operand - The node to consume the register for
//    reason  - What was the register allocated for
//
void WasmRegAlloc::ConsumeTemporaryRegForOperand(GenTree* operand DEBUGARG(const char* reason))
{
    if ((operand->gtLIRFlags & LIR::Flags::MultiplyUsed) == LIR::Flags::None)
    {
        return;
    }

    regNumber reg = ReleaseTemporaryRegister(genActualType(operand));
    // If this assert fails you likely called ConsumeTemporaryRegForOperand on your operands in the wrong order.
    assert(reg == operand->GetRegNum());
    CollectReference(operand);

Review comment (suggestion):
```suggestion
    assert((node->GetRegNum() == REG_NA) && "Trying to double-assign a temporary register");
```
We can use this trick to save some looking into the source.

Code after:
{
    if ((node->gtLIRFlags & LIR::Flags::MultiplyUsed) == LIR::Flags::None)
    {
        return;
    }

    assert(node->IsValue());
    if (node->IsUnusedValue())
    {
        // Liveness removed the parent node - no need to do anything.
        node->gtLIRFlags &= ~LIR::Flags::MultiplyUsed;
        return;
    }

    if (node->OperIs(GT_LCL_VAR) && m_compiler->lvaGetDesc(node->AsLclVar())->lvIsRegCandidate())
    {
        // Will be allocated into its own register, no need for a temporary.
        node->gtLIRFlags &= ~LIR::Flags::MultiplyUsed;
        return;
    }

    // Note how due to the fact we're processing nodes in stack order,
    // we don't need to maintain free/busy sets, only a simple stack.
    regNumber reg = AllocateTemporaryRegister(genActualType(node));
    assert((node->GetRegNum() == REG_NA) && "Trying to double-assign a temporary register");
    node->SetRegNum(reg);
}

//------------------------------------------------------------------------
// ConsumeTemporaryRegForOperand: Consume the temporary register for a multiply-used operand.
//
// The contract with codegen is that such operands will have their register
// number set to a valid WASM local, to be "local.tee"d after the node is
// generated.
//
// Arguments:
//    operand - The node to consume the register for
//    reason  - What was the register allocated for
//
void WasmRegAlloc::ConsumeTemporaryRegForOperand(GenTree* operand DEBUGARG(const char* reason))
{
    if ((operand->gtLIRFlags & LIR::Flags::MultiplyUsed) == LIR::Flags::None)
    {
        return;
    }

    regNumber reg = ReleaseTemporaryRegister(genActualType(operand));
    assert((reg == operand->GetRegNum()) && "Temporary reg being consumed out of order");
    CollectReference(operand);

    operand->gtLIRFlags &= ~LIR::Flags::MultiplyUsed;