Repository: dotnet/runtime
File: src/libraries/System.IO.Hashing/src/System/IO/Hashing/Adler32.cs (C#)

Code before:
                vs3 <<= 6;
                vs2 += vs3;

                s1 = (uint)Vector512.Sum(vs1.AsUInt64());
                s2 = Vector512.Sum(vs2);

                s1 %= ModBase;
                s2 %= ModBase;
            }
            while (length >= BlockSize);

            if (length >= Vector256<byte>.Count)
            {
                return UpdateVector256((s2 << 16) | s1, MemoryMarshal.CreateReadOnlySpan(ref sourceRef, length));
            }

            if (length > 0)
            {
                UpdateScalarTail(ref sourceRef, length, ref s1, ref s2);
            }

            return (s2 << 16) | s1;
        }

        [MethodImpl(MethodImplOptions.NoInlining)]
        private static uint UpdateArm128(uint adler, ReadOnlySpan<byte> source)
        {
            Debug.Assert(source.Length >= Vector128<byte>.Count * 2);

            const int BlockSize = 32; // two Vector128<byte> loads

            uint s1 = adler & 0xFFFF;
            uint s2 = (adler >> 16) & 0xFFFF;

            ref byte sourceRef = ref MemoryMarshal.GetReference(source);
            int length = source.Length;

            do
            {
                int n = Math.Min(length, NMax);
                int blocks = n / BlockSize;
                n = blocks * BlockSize;
                length -= n;

                Vector128<uint> vs1 = Vector128<uint>.Zero;
                Vector128<uint> vps = Vector128.CreateScalar(s1 * (uint)blocks);

                Vector128<ushort> vColumnSum1 = Vector128<ushort>.Zero;
                Vector128<ushort> vColumnSum2 = Vector128<ushort>.Zero;
                Vector128<ushort> vColumnSum3 = Vector128<ushort>.Zero;
                Vector128<ushort> vColumnSum4 = Vector128<ushort>.Zero;

Review comment (suggestion):
It's not clear why this needs to be its own method instead of being part of the platform specific lightup in `Vector128`.

AdvSimd has general equivalents to widening sum, widening multiply w/ horizontal add, and widening horizontal add, so shouldn't really need its "own" method.

Code after:
                {
                    Vector512<byte> data = Vector512.LoadUnsafe(ref sourceRef);
                    sourceRef = ref Unsafe.Add(ref sourceRef, BlockSize);

                    Vector512<uint> vs1_0 = vs1;
                    vs1 += Avx512BW.SumAbsoluteDifferences(data, Vector512<byte>.Zero).AsUInt32();
                    vs3 += vs1_0;
                    vs2 += Avx512BW.MultiplyAddAdjacent(Avx512BW.MultiplyAddAdjacent(data, weights), Vector512<short>.One).AsUInt32();

                    Vector256<uint> sumLo = Avx2.SumAbsoluteDifferences(data.GetLower(), Vector256<byte>.Zero).AsUInt32();
                    vs2 += Vector512.Create(sumLo << 5, Vector256<uint>.Zero);
                }
                while (--blocks > 0);

                vs3 <<= 6;
                vs2 += vs3;

                s1 = (uint)Vector512.Sum(vs1.AsUInt64());
                s2 = Vector512.Sum(vs2);

                s1 %= ModBase;
                s2 %= ModBase;
            }
            while (length >= BlockSize);

            if (length >= Vector256<byte>.Count)
            {
                return UpdateVector256((s2 << 16) | s1, MemoryMarshal.CreateReadOnlySpan(ref sourceRef, length));
            }

            if (length > 0)
            {
                UpdateScalarTail(ref sourceRef, length, ref s1, ref s2);
            }

            return (s2 << 16) | s1;
        }

        private static void UpdateScalarTail(ref byte sourceRef, int length, ref uint s1, ref uint s2)
        {
            Debug.Assert(length is > 0 and < NMax);

            foreach (byte b in MemoryMarshal.CreateReadOnlySpan(ref sourceRef, length))
            {
                s1 += b;
                s2 += s1;
            }

            s1 %= ModBase;
            s2 %= ModBase;
        }