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

Code before:
        /// <param name="source">The data to hash.</param>
        /// <returns>
        /// The computed Adler-32 hash.
        /// </returns>
        [CLSCompliant(false)]
        public static uint HashToUInt32(ReadOnlySpan<byte> source)
            => Update(InitialState, source);

        private static uint Update(uint adler, ReadOnlySpan<byte> source)
        {
            if (source.IsEmpty)
            {
                return adler;
            }

#if NET
            if (BitConverter.IsLittleEndian &&
                Vector128.IsHardwareAccelerated &&
                source.Length >= Vector128<byte>.Count * 2)
            {
                if (AdvSimd.IsSupported)
                {
                    return UpdateArm128(adler, source);
                }

                if (Avx512BW.IsSupported && source.Length >= Vector512<byte>.Count)
                {
                    return UpdateVector512(adler, source);
                }

                if (Avx2.IsSupported && source.Length >= Vector256<byte>.Count)
                {
                    return UpdateVector256(adler, source);
                }

                return UpdateVector128(adler, source);
            }
#endif

            return UpdateScalar(adler, source);
        }

        private static uint UpdateScalar(uint adler, ReadOnlySpan<byte> source)
        {
            uint s1 = adler & 0xFFFF;
            uint s2 = (adler >> 16) & 0xFFFF;
            Debug.Assert(!source.IsEmpty);

            do
            {
                int k = source.Length < NMax ? source.Length : NMax;

Review comment (suggestion):
This guard isn't correct. We need to be checking `Vector512.IsHardwareAccelerated` in addition to any platform specific ISA usage checks to ensure that we aren't using V512 on hardware which may actually hurt perf by default.

Code after:
        /// <param name="source">The data to hash.</param>
        /// <returns>
        /// The computed Adler-32 hash.
        /// </returns>
        [CLSCompliant(false)]
        public static uint HashToUInt32(ReadOnlySpan<byte> source)
            => Update(InitialState, source);

        private static uint Update(uint adler, ReadOnlySpan<byte> source)
        {
            if (source.IsEmpty)
            {
                return adler;
            }

#if NET
            if (BitConverter.IsLittleEndian &&
                Vector128.IsHardwareAccelerated &&
                source.Length >= Vector128<byte>.Count * 2)
            {
                if (Vector512.IsHardwareAccelerated && Avx512BW.IsSupported && source.Length >= Vector512<byte>.Count)
                {
                    return UpdateVector512(adler, source);
                }

                if (Vector256.IsHardwareAccelerated && Avx2.IsSupported && source.Length >= Vector256<byte>.Count)
                {
                    return UpdateVector256(adler, source);
                }

                return UpdateVector128(adler, source);
            }
#endif

            return UpdateScalar(adler, source);
        }

        private static uint UpdateScalar(uint adler, ReadOnlySpan<byte> source)
        {
            uint s1 = adler & 0xFFFF;
            uint s2 = (adler >> 16) & 0xFFFF;
            Debug.Assert(!source.IsEmpty);

            do
            {
                int k = source.Length < NMax ? source.Length : NMax;
                foreach (byte b in source.Slice(0, k))
                {
                    s1 += b;
                    s2 += s1;
                }