diff --git a/AK/SIMD.h b/AK/SIMD.h index b923f7a1110..f109899d02a 100644 --- a/AK/SIMD.h +++ b/AK/SIMD.h @@ -6,6 +6,7 @@ #pragma once +#include #include namespace AK::SIMD { @@ -61,4 +62,55 @@ using f32x8 = float __attribute__((vector_size(32))); using f64x2 = double __attribute__((vector_size(16))); using f64x4 = double __attribute__((vector_size(32))); +// FIXME: Is this really the best/simplest way? +// Ideally we should look for the presence of the vector_size attribute instead +// FIXME: This cannot just be vector as that would somehow clash with AK::Vector, even without being exported +template +concept SIMDVector = requires { __builtin_convertvector(declval(), T); }; + +template +using ElementOf = RemoveReference()[0])>; + +static_assert(IsSame, i8>); +static_assert(IsSame, float>); + +template +constexpr static size_t vector_length = sizeof(V) / sizeof(ElementOf); + +static_assert(vector_length == 4); +static_assert(vector_length == 4); + +namespace Detail { +template +struct IndexVectorFor; + +template +requires(IsIntegral>) +struct IndexVectorFor { + using Type = T; +}; + +template +requires(IsFloatingPoint>) +struct IndexVectorFor { + using Type = Conditional< + IsSame, float>, + u32 __attribute__((vector_size(sizeof(T)))), + u64 __attribute__((vector_size(sizeof(T))))>; +}; + +} + +template +using IndexVectorFor = typename Detail::IndexVectorFor::Type; + +static_assert(IsSame, i8x16>); +static_assert(IsSame, u32x4>); +static_assert(IsSame, u64x4>); +#if defined(AK_COMPILER_CLANG) +// FIXME: GCC silently ignores the dependent vector_size attribute, this seems to be a bug +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68703 +static_assert(IsSame, u32x4>); +static_assert(IsSame, u64x4>); +#endif }