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

Code before:
            return next;
        }
        else if (TryLowerZextAddToAddUw(node, &next))
        {
            return next;
        }
    }
#endif

    if (node->OperIs(GT_ADD))
    {
        ContainCheckBinary(node);
    }

    return nullptr;
}

//------------------------------------------------------------------------
// LowerUnsignedDivOrMod: Lowers a GT_UDIV/GT_UMOD node.
//
// Arguments:
//    divMod - pointer to the GT_UDIV/GT_UMOD node to be lowered
//
// Return Value:
//    Returns a boolean indicating whether the node was transformed.
//
// Notes:
//    - Transform UDIV/UMOD by power of 2 into RSZ/AND
//    - Transform UDIV by constant >= 2^(N-1) into GE
//    - Transform UDIV/UMOD by constant >= 3 into "magic division"
//

bool Lowering::LowerUnsignedDivOrMod(GenTreeOp* divMod)
{
    assert(divMod->OperIs(GT_UDIV, GT_UMOD));

#if defined(USE_HELPERS_FOR_INT_DIV)
    if (!varTypeIsIntegral(divMod->TypeGet()))
    {
        assert(!"unreachable: integral GT_UDIV/GT_UMOD should get morphed into helper calls");
    }
    assert(varTypeIsFloating(divMod->TypeGet()));
#endif // USE_HELPERS_FOR_INT_DIV
#if defined(TARGET_ARM64)
    assert(!divMod->OperIs(GT_UMOD));
#endif // TARGET_ARM64

    GenTree* dividend = divMod->gtGetOp1();
    GenTree* divisor  = divMod->gtGetOp2();

#if !defined(TARGET_64BIT)

Review comment (suggestion):
I think it'd be possible to also match index scale in `genCreateAddrMode` reusing the code paths for x64 instead of maintaining RISC-V specific `TryLowerShiftAddToShxadd`. I'll leave it for another PR.

Code after:
            // where there is no room for additional offsets/scales on ARM64. 'shiftBy' has to match target's width.
            if (cast->CastOp()->TypeIs(TYP_INT) && cast->TypeIs(TYP_LONG) &&
                (genTypeSize(targetType) == (1U << shiftBy)) && (scale == 1) && (offset == 0))
            {
                if (IsInvariantInRange(index, parent))
                {
                    // Check containment safety against the parent node - this will ensure that LEA with the contained
                    // index will itself always be contained. We do not support uncontained LEAs with contained indices.

                    // TODO: Make sure that genCreateAddrMode marks such BFIZ candidates as GTF_DONT_CSE for better CQ.
                    MakeSrcContained(addrMode, index);
                }
            }
        }
    }
#elif defined(TARGET_RISCV64)
    if (index != nullptr)
    {
        // RISC-V doesn't have indexed load/stores, explicitly add the index into the base
        assert(base != nullptr);
        assert(scale <= 1);
        base = comp->gtNewOperNode(GT_ADD, addrMode->TypeGet(), base, index);
        BlockRange().InsertBefore(addrMode, base);
        addrMode->SetBase(base);
        addrMode->SetIndex(nullptr);
        LowerAdd(base->AsOp());
    }
#endif

    JITDUMP("New addressing mode node:\n  ");
    DISPNODE(addrMode);
    JITDUMP("\n");

    return true;
}

//------------------------------------------------------------------------
// LowerAdd: turn this add into a GT_LEA if that would be profitable
//
// Arguments:
//    node - the node we care about
//
// Returns:
//    nullptr if no transformation was done, or the next node in the transformed node sequence that
//    needs to be lowered.
//
GenTree* Lowering::LowerAdd(GenTreeOp* node)
{
    if (varTypeIsIntegralOrI(node->TypeGet()))
    {
        GenTree* op1 = node->gtGetOp1();