Skip to content

Commit

Permalink
Make make callable
Browse files Browse the repository at this point in the history
  • Loading branch information
SadiinsoSnowfall committed Jul 6, 2024
1 parent 33f81a5 commit 293ecb9
Show file tree
Hide file tree
Showing 8 changed files with 299 additions and 498 deletions.
6 changes: 3 additions & 3 deletions include/eve/arch/cpu/logical_wide.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,11 @@ namespace eve
//! Constructs a eve::logical by splatting a scalar value in all lanes
template<scalar_value S>
EVE_FORCEINLINE explicit logical(S v) noexcept
: storage_base(detail::make(eve::as<logical>{}, v)) {}
: storage_base(make(eve::as<logical>{}, v)) {}

//! Construct from a `bool`
EVE_FORCEINLINE explicit logical(bool v) noexcept
: storage_base(detail::make(eve::as<logical>{}, v)) {}
: storage_base(make(eve::as<logical>{}, v)) {}

//! Constructs a eve::logical from a sequence of scalar values of proper size
template<typename T0, typename T1, typename... Ts>
Expand All @@ -138,7 +138,7 @@ namespace eve
&& (... && std::convertible_to<Ts,logical<Type>>)
&& (Cardinal::value == 2 + sizeof...(Ts))
)
: storage_base(detail::make(eve::as<logical>{}, v0, v1, vs...))
: storage_base(make(eve::as<logical>{}, v0, v1, vs...))
{}

//==============================================================================================
Expand Down
4 changes: 2 additions & 2 deletions include/eve/arch/cpu/wide.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ namespace eve
template<typename S>
requires std::constructible_from<Type,S>
EVE_FORCEINLINE explicit wide(S const& v) noexcept
: storage_base(detail::make(eve::as<wide>{}, Type(v)))
: storage_base(make(eve::as<wide>{}, Type(v)))
{}

//! Constructs a eve::wide from a sequence of scalar values of proper size
Expand All @@ -153,7 +153,7 @@ namespace eve
&& std::is_convertible_v<S0,Type>
&& (std::is_convertible_v<S1, Type> && ... && std::is_convertible_v<Ss, Type>)
)
: storage_base(detail::make(eve::as<wide> {},
: storage_base(make(eve::as<wide> {},
static_cast<Type>(v0),
static_cast<Type>(v1),
static_cast<Type>(vs)...))
Expand Down
31 changes: 21 additions & 10 deletions include/eve/detail/function/make.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,30 @@
#pragma once

#include <eve/arch.hpp>
#include <eve/detail/function/simd/common/make.hpp>
#include <eve/traits/overload.hpp>

#if defined(EVE_INCLUDE_X86_HEADER)
# include <eve/detail/function/simd/x86/make.hpp>
#endif
namespace eve
{
template<typename Options>
struct make_t : callable<make_t, Options>
{
template<typename Target, typename... T>
EVE_FORCEINLINE constexpr auto operator()(as<Target> tgt, T... vs) const noexcept
{
return EVE_DISPATCH_CALL(tgt, vs...);
}

#if defined(EVE_INCLUDE_POWERPC_HEADER)
# include <eve/detail/function/simd/ppc/make.hpp>
#endif
EVE_CALLABLE_OBJECT(make_t, make_);
};

#if defined(EVE_INCLUDE_ARM_HEADER)
# include <eve/detail/function/simd/arm/neon/make.hpp>
#endif
inline constexpr auto make = functor<make_t>;
}

#include <eve/detail/function/simd/common/make.hpp>

// #if defined(EVE_INCLUDE_X86_HEADER)
// # include <eve/detail/function/simd/x86/make.hpp>
// #endif

#if defined(EVE_INCLUDE_SVE_HEADER)
# include <eve/detail/function/simd/arm/sve/make.hpp>
Expand Down
95 changes: 0 additions & 95 deletions include/eve/detail/function/simd/arm/neon/make.hpp

This file was deleted.

128 changes: 57 additions & 71 deletions include/eve/detail/function/simd/arm/sve/make.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,95 +18,81 @@

namespace eve::detail
{
//============================s====================================================================
// Enumerated make
//================================================================================================
template<arithmetic_scalar_value T, typename N, typename... Vs>
EVE_FORCEINLINE auto
make(eve::as<wide<T, N>>, Vs... vs) noexcept
requires sve_abi<abi_t<T, N>>
{
static_assert(sizeof...(Vs) == N::value, "[eve::make] - Invalid number of arguments");

if constexpr( wide<T, N>::size() < eve::fundamental_cardinal_v<T> )
template<callable_options O, arithmetic_scalar_value T, typename N, typename V0, typename... Vs>
requires sve_abi<abi_t<T, N>> && (N::value > 1)
EVE_FORCEINLINE auto make_(EVE_REQUIRES(sve_), O const&, as<wide<T, N>> tgt, V0 v, Vs... vs) noexcept
{
if constexpr (sizeof...(Vs) == 0)
{
return [&]<std::size_t... i>(std::index_sequence<i...>)
// This may be suboptimal, we a one instruction iota on sve
if constexpr(N::value < fundamental_cardinal_t<T>::value)
{
return make(as<wide<T, fundamental_cardinal_t<T>>> {}, vs..., ((void)i, 0)...);
// Use svdup then mask using optimized iota comparison
return wide<T>{v} & (iota(as<wide<as_integer_t<T>>>{}) < N::value).mask();
}
(std::make_index_sequence<fundamental_cardinal_v<T> - N::value> {});
}
else
{
std::array on_stack {static_cast<T>(vs)...};
return load(on_stack.data(), N {});
}
}
else
{
constexpr auto c = categorize<wide<T, N>>();

//================================================================================================
// splat make
//================================================================================================
template<arithmetic_scalar_value T, typename N>
EVE_FORCEINLINE auto
make(eve::as<wide<T, N>>, T x) noexcept
requires sve_abi<abi_t<T, N>> && (N::value > 1)
{
// This may be suboptimal, we a one instruction iota on sve
if constexpr( N::value < eve::fundamental_cardinal_v<T> )
{
// Use svdup then mask using optimized iota comparison
return wide<T>{x} & (iota(as<wide<as_integer_t<T>>>{}) < N::value).mask();
if constexpr( match(c, category::int8) ) return svdup_s8(v);
else if constexpr( match(c, category::uint8) ) return svdup_u8(v);
else if constexpr( match(c, category::int16) ) return svdup_s16(v);
else if constexpr( match(c, category::uint16) ) return svdup_u16(v);
else if constexpr( match(c, category::int32) ) return svdup_s32(v);
else if constexpr( match(c, category::uint32) ) return svdup_u32(v);
else if constexpr( match(c, category::int64) ) return svdup_s64(v);
else if constexpr( match(c, category::uint64) ) return svdup_u64(v);
else if constexpr( match(c, category::float32) ) return svdup_f32(v);
else if constexpr( match(c, category::float64) ) return svdup_f64(v);
}
}
else
{
constexpr auto c = categorize<wide<T, N>>();
static_assert(sizeof...(Vs) == N::value, "[eve::make] - Invalid number of arguments");

if constexpr( match(c, category::int8) ) return svdup_s8(x);
else if constexpr( match(c, category::uint8) ) return svdup_u8(x);
else if constexpr( match(c, category::int16) ) return svdup_s16(x);
else if constexpr( match(c, category::uint16) ) return svdup_u16(x);
else if constexpr( match(c, category::int32) ) return svdup_s32(x);
else if constexpr( match(c, category::uint32) ) return svdup_u32(x);
else if constexpr( match(c, category::int64) ) return svdup_s64(x);
else if constexpr( match(c, category::uint64) ) return svdup_u64(x);
else if constexpr( match(c, category::float32) ) return svdup_f32(x);
else if constexpr( match(c, category::float64) ) return svdup_f64(x);
if constexpr( wide<T, N>::size() < eve::fundamental_cardinal_v<T> )
{
return [&]<std::size_t... i>(std::index_sequence<i...>)
{
return make(as<wide<T, fundamental_cardinal_t<T>>> {}, vs..., ((void)i, 0)...);
}
(std::make_index_sequence<fundamental_cardinal_v<T> - N::value> {});
}
else
{
std::array on_stack {static_cast<T>(vs)...};
return load(on_stack.data(), N {});
}
}
}

//================================================================================================
// logical cases
//================================================================================================
template<arithmetic_scalar_value T, typename N, typename... Vs>
EVE_FORCEINLINE auto
make(as<logical<wide<T, N>>>, Vs... vs) noexcept
requires sve_abi<abi_t<T, N>>
{
using bits_type = typename logical<wide<T, N>>::bits_type;
using e_t = element_type_t<bits_type>;

auto bits = make(as<bits_type> {}, (vs ? (e_t)-1 : 0)...);
return svcmpne(sve_true<T>(), bits, (e_t)0);
}

template<arithmetic_scalar_value T, typename N, typename V>
EVE_FORCEINLINE auto
make(eve::as<logical<wide<T, N>>>, V x) noexcept
template<callable_options O, arithmetic_scalar_value T, typename N, typename V0, typename... Vs>
requires sve_abi<abi_t<T, N>> && (N::value > 1)
EVE_FORCEINLINE auto make_(EVE_REQUIRES(sve_), O const&, as<logical<wide<T, N>>> tgt, V0 v, Vs... vs) noexcept
{
using f_t = fundamental_cardinal_t<T>;

if constexpr( N::value < f_t::value )
if constexpr (sizeof...(Vs) == 0)
{
// Use svdup then mask using optimized iota comparison
return logical<wide<T>>{(bool)x} && (iota(as<wide<as_integer_t<T>>>{}) < N::value);
if constexpr(N::value < fundamental_cardinal_t<T>::value)
{
// Use svdup then mask using optimized iota comparison
return logical<wide<T>>{(bool) v} && (iota(as<wide<as_integer_t<T>>>{}) < N::value);
}
else
{
if constexpr( sizeof(T) == 1 ) return svdup_b8(v);
else if constexpr( sizeof(T) == 2 ) return svdup_b16(v);
else if constexpr( sizeof(T) == 4 ) return svdup_b32(v);
else if constexpr( sizeof(T) == 8 ) return svdup_b64(v);
}
}
else
{
if constexpr( sizeof(T) == 1 ) return svdup_b8(x);
else if constexpr( sizeof(T) == 2 ) return svdup_b16(x);
else if constexpr( sizeof(T) == 4 ) return svdup_b32(x);
else if constexpr( sizeof(T) == 8 ) return svdup_b64(x);
using bits_type = typename logical<wide<T, N>>::bits_type;
using e_t = element_type_t<bits_type>;

auto bits = make(as<bits_type> {}, (vs ? (e_t)-1 : 0)...);
return svcmpne(sve_true<T>(), bits, (e_t)0);
}
}

Expand Down
Loading

0 comments on commit 293ecb9

Please sign in to comment.