Skip to content

Commit

Permalink
Improve the as_register machinery and cleanup arch (#2003)
Browse files Browse the repository at this point in the history
  • Loading branch information
SadiinsoSnowfall authored Oct 18, 2024
1 parent cffc8de commit dddd90f
Show file tree
Hide file tree
Showing 31 changed files with 655 additions and 810 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ TTS_CASE("inclusive_scan")
T{3});
};

#if !defined(EVE_HW_POWERPC) // calling std::async crashes in our quemu run.
#if !defined(EVE_INCLUDE_POWERPC_HEADER) // calling std::async crashes in our quemu run.
TTS_CASE("inclusive_scan_par_unseq")
{
{
Expand Down
9 changes: 8 additions & 1 deletion include/eve/arch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,11 @@
//==================================================================================================
#pragma once

#include <eve/arch/tags.hpp>
#include <eve/arch/predef.hpp>

#include <eve/arch/cpu/tags.hpp>
#include <eve/arch/x86/tags.hpp>
#include <eve/arch/ppc/tags.hpp>
#include <eve/arch/arm/sve/tags.hpp>
#include <eve/arch/arm/neon/tags.hpp>
#include <eve/arch/riscv/tags.hpp>
2 changes: 1 addition & 1 deletion include/eve/arch/abi_of.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#pragma once

#include <eve/detail/spy.hpp>
#include <eve/arch/tags.hpp>
#include <eve/arch.hpp>
#include <eve/arch/spec.hpp>

namespace eve
Expand Down
127 changes: 59 additions & 68 deletions include/eve/arch/arm/neon/as_register.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,88 +17,79 @@ namespace eve
struct logical;
}

#if defined(EVE_HW_ARM)
namespace eve
{
// ---------------------------------------------------------------------------------------------
// NEON 64
template<typename T, typename Size> struct as_register<T, Size, eve::arm_64_>
template<typename T, typename N>
consteval auto find_register_type(as<T>, N, eve::arm_64_)
{
static constexpr auto find()
if constexpr (std::same_as<T, float> && (N::value <= 2))
{
if constexpr( std::is_same_v<T,float> && Size::value <= 2)
{
return float32x2_t{};
}
else if constexpr( std::is_same_v<T,double> && Size::value <= 1 )
{
#if defined(SPY_SIMD_IS_ARM_ASIMD)
return float64x1_t{};
#else
return emulated_{};
#endif
}
else if constexpr( std::is_integral_v<T> )
{
constexpr bool signed_v = std::is_signed_v<T>;

if constexpr( signed_v && (sizeof(T) == 1 )&& (Size::value <= 8) ) return int8x8_t{};
if constexpr( signed_v && (sizeof(T) == 2 )&& (Size::value <= 4) ) return int16x4_t{};
if constexpr( signed_v && (sizeof(T) == 4 )&& (Size::value <= 2) ) return int32x2_t{};
if constexpr( signed_v && (sizeof(T) == 8 )&& (Size::value <= 1) ) return int64x1_t{};
if constexpr( !signed_v && (sizeof(T) == 1 )&& (Size::value <= 8) ) return uint8x8_t{};
if constexpr( !signed_v && (sizeof(T) == 2 )&& (Size::value <= 4) ) return uint16x4_t{};
if constexpr( !signed_v && (sizeof(T) == 4 )&& (Size::value <= 2) ) return uint32x2_t{};
if constexpr( !signed_v && (sizeof(T) == 8 )&& (Size::value <= 1) ) return uint64x1_t{};
}
return float32x2_t{};
}

using type = decltype(find());
static_assert( !std::is_void_v<type>, "[eve arm] - Type is not usable in a SIMD register");
};
else if constexpr (std::same_as<T, double> && (N::value <= 1))
{
#if defined(SPY_SIMD_IS_ARM_ASIMD)
return float64x1_t{};
#else
return emulated_{};
#endif
}
else if constexpr (std::signed_integral<T>)
{
if constexpr((sizeof(T) == 1) && (N::value <= 8)) return int8x8_t{};
else if constexpr((sizeof(T) == 2) && (N::value <= 4)) return int16x4_t{};
else if constexpr((sizeof(T) == 4) && (N::value <= 2)) return int32x2_t{};
else if constexpr((sizeof(T) == 8) && (N::value <= 1)) return int64x1_t{};
}
else if constexpr (std::unsigned_integral<T>)
{
if constexpr((sizeof(T) == 1) && (N::value <= 8)) return uint8x8_t{};
else if constexpr((sizeof(T) == 2) && (N::value <= 4)) return uint16x4_t{};
else if constexpr((sizeof(T) == 4) && (N::value <= 2)) return uint32x2_t{};
else if constexpr((sizeof(T) == 8) && (N::value <= 1)) return uint64x1_t{};
}
}

// ---------------------------------------------------------------------------------------------
// NEON 128
template<typename T, typename Size>
struct as_register<T, Size, eve::arm_128_>
template<typename T, typename N>
consteval auto find_register_type(as<T>, N, eve::arm_128_)
{
static constexpr auto find()
if constexpr (std::same_as<T, float>)
{
if constexpr( std::is_same_v<T,float> )
{
return float32x4_t{};
}
else if constexpr( std::is_same_v<T,double> )
{
#if defined(SPY_SIMD_IS_ARM_ASIMD)
return float64x2_t{};
#else
return emulated_{};
#endif
}
else if constexpr( std::is_integral_v<T> )
{
constexpr bool signed_v = std::is_signed_v<T>;
if constexpr( signed_v && (sizeof(T) == 1 )&& (Size::value == 16) ) return int8x16_t{};
if constexpr( signed_v && (sizeof(T) == 2 )&& (Size::value == 8 ) ) return int16x8_t{};
if constexpr( signed_v && (sizeof(T) == 4 )&& (Size::value == 4 ) ) return int32x4_t{};
if constexpr( signed_v && (sizeof(T) == 8 )&& (Size::value == 2 ) ) return int64x2_t{};
if constexpr( !signed_v && (sizeof(T) == 1 )&& (Size::value == 16) ) return uint8x16_t{};
if constexpr( !signed_v && (sizeof(T) == 2 )&& (Size::value == 8 ) ) return uint16x8_t{};
if constexpr( !signed_v && (sizeof(T) == 4 )&& (Size::value == 4 ) ) return uint32x4_t{};
if constexpr( !signed_v && (sizeof(T) == 8 )&& (Size::value == 2 ) ) return uint64x2_t{};
}
return float32x4_t{};
}

using type = decltype(find());
static_assert( !std::is_void_v<type>, "[eve arm] - Type is not usable in a SIMD register");
};
else if constexpr (std::same_as<T, double>)
{
#if defined(SPY_SIMD_IS_ARM_ASIMD)
return float64x2_t{};
#else
return emulated_{};
#endif
}
else if constexpr (std::signed_integral<T>)
{
if constexpr ((sizeof(T) == 1) && (N::value == 16)) return int8x16_t{};
else if constexpr ((sizeof(T) == 2) && (N::value == 8 )) return int16x8_t{};
else if constexpr ((sizeof(T) == 4) && (N::value == 4 )) return int32x4_t{};
else if constexpr ((sizeof(T) == 8) && (N::value == 2 )) return int64x2_t{};
}
else if constexpr (std::unsigned_integral<T>)
{
if constexpr ((sizeof(T) == 1) && (N::value == 16)) return uint8x16_t{};
else if constexpr ((sizeof(T) == 2) && (N::value == 8 )) return uint16x8_t{};
else if constexpr ((sizeof(T) == 4) && (N::value == 4 )) return uint32x4_t{};
else if constexpr ((sizeof(T) == 8) && (N::value == 2 )) return uint64x2_t{};
}
}

// ---------------------------------------------------------------------------------------------
// logical cases
template<typename T, typename Size, arm_abi ABI>
struct as_logical_register<T, Size, ABI>
: as_register<as_integer_t<T, unsigned>, Size, ABI>
{};
template<typename T, typename N>
consteval auto find_logical_register_type(as<T>, N n, arm_abi auto abi)
{
return find_register_type(as<as_integer_t<T, unsigned>>{}, n, abi);
}
}
#endif
33 changes: 12 additions & 21 deletions include/eve/arch/arm/neon/spec.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
//==================================================================================================
// Register count
//==================================================================================================
#if defined(EVE_HW_ARM)

namespace eve
{
Expand All @@ -28,26 +27,18 @@ struct register_count
//==================================================================================================
// NEON SIMD ABI
//==================================================================================================
# if !defined(EVE_CURRENT_API) && defined(SPY_SIMD_IS_ARM)
# include <arm_neon.h>
# if !defined(EVE_ABI_DETECTED) && defined(SPY_SIMD_IS_ARM_ASIMD)
# define EVE_CURRENT_ABI ::eve::arm_128_
# define EVE_CURRENT_API ::eve::asimd_
# define EVE_ABI_NAMESPACE arm_abi_v0
# define EVE_ABI_DETECTED
# endif
# if !defined(EVE_ABI_DETECTED) && defined(SPY_SIMD_IS_ARM_NEON)
# define EVE_CURRENT_ABI ::eve::arm_128_
# define EVE_CURRENT_API ::eve::neon128_
# define EVE_ABI_NAMESPACE arm_abi_v0
# define EVE_ABI_DETECTED
# endif
# endif
#include <arm_neon.h>

# if !defined(__aarch64__)
# ifndef EVE_NO_DENORMALS
# define EVE_NO_DENORMALS
# endif
# endif
#if defined(SPY_SIMD_IS_ARM_ASIMD)
# define EVE_CURRENT_ABI ::eve::arm_128_
# define EVE_CURRENT_API ::eve::asimd_
# define EVE_ABI_NAMESPACE arm_abi_v0
#elif defined(SPY_SIMD_IS_ARM_NEON)
# define EVE_CURRENT_ABI ::eve::arm_128_
# define EVE_CURRENT_API ::eve::neon128_
# define EVE_ABI_NAMESPACE arm_abi_v0
#endif

#if !defined(__aarch64__) && !defined(EVE_NO_DENORMALS)
# define EVE_NO_DENORMALS
#endif
21 changes: 11 additions & 10 deletions include/eve/arch/arm/predef.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,17 @@
//==================================================================================================
#pragma once

#include <eve/detail/spy.hpp>
#include <eve/arch/cpu/predef.hpp>
#if defined(SPY_SIMD_IS_ARM_FIXED_SVE) || defined(SPY_SIMD_IS_ARM_FIXED_SVE2)
# define EVE_SIMD_IS_ANY_FIXED_SVE
#endif

// We successfully detected some native SIMD
#if defined(EVE_SIMD_IS_ANY_FIXED_SVE) && !defined(EVE_NO_SIMD)
# define EVE_SUPPORTS_NATIVE_SIMD
# define EVE_HW_ARM_SVE
# define EVE_INCLUDE_ARM_SVE_HEADER
#elif defined(SPY_SIMD_IS_ARM) && !defined(EVE_NO_SIMD)
# define EVE_SUPPORTS_NATIVE_SIMD
# define EVE_HW_ARM
# define EVE_INCLUDE_ARM_NEON_HEADER
#if !defined(EVE_NO_SIMD)
# if defined(EVE_SIMD_IS_ANY_FIXED_SVE)
# define EVE_SUPPORTS_NATIVE_SIMD
# define EVE_INCLUDE_ARM_SVE_HEADER
# elif defined(SPY_SIMD_IS_ARM)
# define EVE_SUPPORTS_NATIVE_SIMD
# define EVE_INCLUDE_ARM_NEON_HEADER
# endif
#endif
81 changes: 36 additions & 45 deletions include/eve/arch/arm/sve/as_register.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,94 +17,85 @@ namespace eve
struct logical;
}

#if defined(EVE_HW_ARM_SVE)
namespace eve
{
template<typename Type, typename Size, sve_abi ABI> struct as_register<Type, Size, ABI>
template<typename T, typename N, sve_abi ABI>
consteval auto find_register_type(as<T>, N, ABI)
{
static constexpr auto find()
{
constexpr auto width = sizeof(Type)*Size::value*8;
constexpr auto width = sizeof(T) * N::value * 8;

if constexpr(width <= __ARM_FEATURE_SVE_BITS)
if constexpr (width <= __ARM_FEATURE_SVE_BITS)
{
if constexpr (std::same_as<T, float>)
{
constexpr bool signed_v = std::is_signed_v<Type>;

if constexpr( std::is_same_v<Type,float> )
{
using type = svfloat32_t __attribute__((arm_sve_vector_bits(__ARM_FEATURE_SVE_BITS)));
return type{};
}
else if constexpr( std::is_same_v<Type,double> )
{
using type = svfloat64_t __attribute__((arm_sve_vector_bits(__ARM_FEATURE_SVE_BITS)));
return type{};
}
else if constexpr( signed_v && sizeof(Type) == 1 )
using type = svfloat32_t __attribute__((arm_sve_vector_bits(__ARM_FEATURE_SVE_BITS)));
return type{};
}
else if constexpr (std::same_as<T, double>)
{
using type = svfloat64_t __attribute__((arm_sve_vector_bits(__ARM_FEATURE_SVE_BITS)));
return type{};
}
else if constexpr (std::signed_integral<T>)
{
if constexpr (sizeof(T) == 1)
{
using type = svint8_t __attribute__((arm_sve_vector_bits(__ARM_FEATURE_SVE_BITS)));
return type{};
}
else if constexpr( signed_v && sizeof(Type) == 2 )
else if constexpr (sizeof(T) == 2)
{
using type = svint16_t __attribute__((arm_sve_vector_bits(__ARM_FEATURE_SVE_BITS)));
return type{};
}
else if constexpr( signed_v && sizeof(Type) == 4 )
else if constexpr (sizeof(T) == 4)
{
using type = svint32_t __attribute__((arm_sve_vector_bits(__ARM_FEATURE_SVE_BITS)));
return type{};
}
else if constexpr( signed_v && sizeof(Type) == 8 )
else if constexpr (sizeof(T) == 8)
{
using type = svint64_t __attribute__((arm_sve_vector_bits(__ARM_FEATURE_SVE_BITS)));
return type{};
}
else if constexpr( !signed_v && sizeof(Type) == 1 )
}
else if constexpr (std::unsigned_integral<T>)
{
if constexpr (sizeof(T) == 1)
{
using type = svuint8_t __attribute__((arm_sve_vector_bits(__ARM_FEATURE_SVE_BITS)));
return type{};
}
else if constexpr( !signed_v && sizeof(Type) == 2 )
else if constexpr (sizeof(T) == 2)
{
using type = svuint16_t __attribute__((arm_sve_vector_bits(__ARM_FEATURE_SVE_BITS)));
return type{};
}
else if constexpr( !signed_v && sizeof(Type) == 4 )
else if constexpr (sizeof(T) == 4)
{
using type = svuint32_t __attribute__((arm_sve_vector_bits(__ARM_FEATURE_SVE_BITS)));
return type{};
}
else if constexpr( !signed_v && sizeof(Type) == 8 )
else if constexpr (sizeof(T) == 8)
{
using type = svuint64_t __attribute__((arm_sve_vector_bits(__ARM_FEATURE_SVE_BITS)));
return type{};
}
}
}

using type = decltype(find());
static_assert( !std::is_void_v<type>, "[eve arm sve] - Type is not usable in a SIMD register");
};
}

// ---------------------------------------------------------------------------------------------
// logical cases
template<typename Type, typename Size, sve_abi ABI>
struct as_logical_register<Type, Size, ABI>
template<typename T, typename N>
consteval auto find_logical_register_type(as<T>, N, sve_abi auto)
{
static constexpr auto find()
{
constexpr auto width = sizeof(Type)*Size::value*8;
constexpr size_t width = sizeof(T) * N::value * 8;

if constexpr(width <= __ARM_FEATURE_SVE_BITS)
{
using type = svbool_t __attribute__((arm_sve_vector_bits(__ARM_FEATURE_SVE_BITS)));
return type{};
}
if constexpr (width <= __ARM_FEATURE_SVE_BITS)
{
using type = svbool_t __attribute__((arm_sve_vector_bits(__ARM_FEATURE_SVE_BITS)));
return type{};
}

using type = decltype(find());
static_assert( !std::is_void_v<type>, "[eve arm sve] - Type is not usable in a SIMD register");
};
}
}
#endif
Loading

0 comments on commit dddd90f

Please sign in to comment.