Repository: SerenityOS/serenity
File: Userland/Libraries/LibCrypto/Hash/SHA2.cpp (C++)

Code before:
        } else {
            msgs[(i + 0) % 4] = bit_cast<u32x4>(__builtin_ia32_sha256msg1(bit_cast<i32x4>(msgs[(i + 0) % 4]), bit_cast<i32x4>(msgs[(i + 1) % 4])));
            tmp = u32x4 { msgs[(i + 2) % 4][1], msgs[(i + 2) % 4][2], msgs[(i + 2) % 4][3], msgs[(i + 3) % 4][0] };
            msgs[(i + 0) % 4] += tmp;
            msgs[(i + 0) % 4] = bit_cast<u32x4>(__builtin_ia32_sha256msg2(bit_cast<i32x4>(msgs[(i + 0) % 4]), bit_cast<i32x4>(msgs[(i + 3) % 4])));
            tmp = AK::SIMD::load_unaligned<u32x4>(&SHA256Constants::RoundConstants[i * 4]);
            msg = msgs[(i + 0) % 4] + tmp;
        }
        states[1] = bit_cast<u32x4>(__builtin_ia32_sha256rnds2(bit_cast<i32x4>(states[1]), bit_cast<i32x4>(states[0]), bit_cast<i32x4>(msg)));
        msg = u32x4 { msg[2], msg[3], 0, 0 };
        states[0] = bit_cast<u32x4>(__builtin_ia32_sha256rnds2(bit_cast<i32x4>(states[0]), bit_cast<i32x4>(states[1]), bit_cast<i32x4>(msg)));
    }
    states[0] += old[0];
    states[1] += old[1];

    tmp = u32x4 { states[0][3], states[0][2], states[0][1], states[0][0] };
    states[1] = u32x4 { states[1][1], states[1][0], states[1][3], states[1][2] };
    states[0] = u32x4 { tmp[0], tmp[1], states[1][2], states[1][3] };
    states[1] = u32x4 { tmp[2], tmp[3], states[1][0], states[1][1] };
    AK::SIMD::store_unaligned(&state[0], states[0]);
    AK::SIMD::store_unaligned(&state[4], states[1]);
}
#endif

decltype(SHA256::transform_dispatched) SHA256::transform_dispatched = [] {
#ifndef KERNEL
    CPUFeatures features = detect_cpu_features();
    if constexpr (is_valid_feature(CPUFeatures::X86_SHA | CPUFeatures::X86_SSE42)) {
        if (has_flag(features, CPUFeatures::X86_SHA | CPUFeatures::X86_SSE42))
            return &SHA256::transform_impl<CPUFeatures::X86_SHA | CPUFeatures::X86_SSE42>;
    }
#endif
    return &SHA256::transform_impl<CPUFeatures::None>;
}();

template<size_t BlockSize, typename Callback>
void update_buffer(u8* buffer, u8 const* input, size_t length, size_t& data_length, Callback callback)
{
    while (length > 0) {
        size_t copy_bytes = AK::min(length, BlockSize - data_length);
        __builtin_memcpy(buffer + data_length, input, copy_bytes);
        input += copy_bytes;
        length -= copy_bytes;
        data_length += copy_bytes;
        if (data_length == BlockSize) {
            callback();
            data_length = 0;
        }
    }
}


Review comment (suggestion):
Wait, what, does this break the build? `CPUFeatures::X86_SHA` etc. are not supposed to pass `is_valid_feature` constexpr check in the kernel.

https://github.com/SerenityOS/serenity/blob/4f7ac757f62962d9d0bc13de0180c7f4c2d99a28/AK/CPUFeatures.h#L18-L32

Code after:
        } else {
            msgs[(i + 0) % 4] = bit_cast<u32x4>(__builtin_ia32_sha256msg1(bit_cast<i32x4>(msgs[(i + 0) % 4]), bit_cast<i32x4>(msgs[(i + 1) % 4])));
            tmp = u32x4 { msgs[(i + 2) % 4][1], msgs[(i + 2) % 4][2], msgs[(i + 2) % 4][3], msgs[(i + 3) % 4][0] };
            msgs[(i + 0) % 4] += tmp;
            msgs[(i + 0) % 4] = bit_cast<u32x4>(__builtin_ia32_sha256msg2(bit_cast<i32x4>(msgs[(i + 0) % 4]), bit_cast<i32x4>(msgs[(i + 3) % 4])));
            tmp = AK::SIMD::load_unaligned<u32x4>(&SHA256Constants::RoundConstants[i * 4]);
            msg = msgs[(i + 0) % 4] + tmp;
        }
        states[1] = bit_cast<u32x4>(__builtin_ia32_sha256rnds2(bit_cast<i32x4>(states[1]), bit_cast<i32x4>(states[0]), bit_cast<i32x4>(msg)));
        msg = u32x4 { msg[2], msg[3], 0, 0 };
        states[0] = bit_cast<u32x4>(__builtin_ia32_sha256rnds2(bit_cast<i32x4>(states[0]), bit_cast<i32x4>(states[1]), bit_cast<i32x4>(msg)));
    }
    states[0] += old[0];
    states[1] += old[1];

    tmp = u32x4 { states[0][3], states[0][2], states[0][1], states[0][0] };
    states[1] = u32x4 { states[1][1], states[1][0], states[1][3], states[1][2] };
    states[0] = u32x4 { tmp[0], tmp[1], states[1][2], states[1][3] };
    states[1] = u32x4 { tmp[2], tmp[3], states[1][0], states[1][1] };
    AK::SIMD::store_unaligned(&state[0], states[0]);
    AK::SIMD::store_unaligned(&state[4], states[1]);
}
#endif

decltype(SHA256::transform_dispatched) SHA256::transform_dispatched = [] {
    CPUFeatures features = detect_cpu_features();

    if constexpr (is_valid_feature(CPUFeatures::X86_SHA | CPUFeatures::X86_SSE42)) {
        if (has_flag(features, CPUFeatures::X86_SHA | CPUFeatures::X86_SSE42))
            return &SHA256::transform_impl<CPUFeatures::X86_SHA | CPUFeatures::X86_SSE42>;
    }

    return &SHA256::transform_impl<CPUFeatures::None>;
}();

template<size_t BlockSize, typename Callback>
void update_buffer(u8* buffer, u8 const* input, size_t length, size_t& data_length, Callback callback)
{
    while (length > 0) {
        size_t copy_bytes = AK::min(length, BlockSize - data_length);
        __builtin_memcpy(buffer + data_length, input, copy_bytes);
        input += copy_bytes;
        length -= copy_bytes;
        data_length += copy_bytes;
        if (data_length == BlockSize) {
            callback();
            data_length = 0;
        }
    }
}