Skip to content

Commit

Permalink
Implement fundamental_cardinal (#815)
Browse files Browse the repository at this point in the history
The fundamental cardinal of a Type x ABI is the smallest cardinal we can use before having to let some lanes unused.
  • Loading branch information
jfalcou authored Oct 16, 2021
1 parent 74611dd commit 90ee1b1
Show file tree
Hide file tree
Showing 9 changed files with 221 additions and 3 deletions.
3 changes: 3 additions & 0 deletions include/eve/arch/arm/tags.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ namespace eve

template<typename Type>
static constexpr std::size_t expected_cardinal = bytes / sizeof(Type);

template<typename Type>
static constexpr std::size_t fundamental_cardinal = 8 / sizeof(Type);
};

struct arm_64_ : arm_abi_<64,true> {};
Expand Down
3 changes: 3 additions & 0 deletions include/eve/arch/cpu/tags.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ namespace eve

template<typename Type>
static constexpr std::size_t expected_cardinal = bytes / sizeof(Type);

template<typename Type>
static constexpr std::size_t fundamental_cardinal = bytes / sizeof(Type);
};

template<typename T>
Expand Down
45 changes: 44 additions & 1 deletion include/eve/arch/expected_cardinal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,49 @@

namespace eve
{
//================================================================================================
//! @addtogroup arch
//! @{
//! @struct expected_cardinal
//! @brief Computes the expected cardinal of a given type
//!
//! **Required header:** `#include <eve/arch/expected_cardinal.hpp>`
//!
//! eve::expected_cardinal computed the cardinal of the register able to store
//! values of type `Type` for a given SIMD `ABI` as a native register type.
//!
//! @tparam Type Type of value to assess
//! @tparam ABI SIMD ABI to use as reference. Must models eve::regular_abi.
//!
//! #### Member types
//!
//! |Name | Definition |
//! |:------|:-----------------------------------------|
//! |`type` | The type of cardinal computed for `Type` |
//!
//! <br/>
//! #### Helper types
//!
//! @code{.cpp}
//! template<typename Type, regular_abi ABI = EVE_CURRENT_ABI>
//! using expected_cardinal_t = typename expected_cardinal<Type, ABI>::type;
//! @endcode
//!
//! <br/>
//! #### Helper variable template
//!
//! @code{.cpp}
//! template<typename Type, regular_abi ABI = EVE_CURRENT_ABI>
//! inline constexpr auto expected_cardinal_v = expected_cardinal_t<Type, ABI>::value;
//! @endcode
//!
//! @code{.cpp}
//! // Cardinal template inline variable to use with functions like eve::load
//! template<typename Type, typename ABI = EVE_CURRENT_ABI>
//! inline constexpr expected_cardinal<Type,ABI> const expected = {};
//! @endcode
//! @}
//================================================================================================
template<typename Type, regular_abi ABI = EVE_CURRENT_ABI>
struct expected_cardinal
: fixed<ABI::template expected_cardinal<Type>>
Expand All @@ -32,7 +75,7 @@ namespace eve
constexpr inline auto expected_cardinal_v = expected_cardinal<Type, ABI>::value;

//================================================================================================
// produtc_type special case
// product_type special case
//================================================================================================
namespace detail
{
Expand Down
99 changes: 99 additions & 0 deletions include/eve/arch/fundamental_cardinal.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//==================================================================================================
/*
EVE - Expressive Vector Engine
Copyright : EVE Contributors & Maintainers
SPDX-License-Identifier: MIT
*/
//==================================================================================================
#pragma once

#include <cstddef>
#include <eve/arch/cardinals.hpp>
#include <eve/arch/spec.hpp>
#include <eve/detail/meta.hpp>
#include <eve/detail/kumi.hpp>
#include <type_traits>
#include <limits>
#include <utility>

namespace eve
{
//================================================================================================
//! @addtogroup arch
//! @{
//! @struct fundamental_cardinal
//! @brief Computes the fundamental cardinal of a given type
//!
//! **Required header:** `#include <eve/arch/fundamental_cardinal.hpp>`
//!
//! eve::fundamental_cardinal computed the cardinal of the smallest register able to store
//! values of type `Type` for a given SIMD `ABI` with no uninitialized lanes.
//!
//! @tparam Type Type of value to assess
//! @tparam ABI SIMD ABI to use as reference. Must models eve::regular_abi.
//!
//! #### Member types
//!
//! |Name | Definition |
//! |:------|:-----------------------------------------|
//! |`type` | The type of cardinal computed for `Type` |
//!
//! <br/>
//! #### Helper types
//!
//! @code{.cpp}
//! template<typename Type, regular_abi ABI = EVE_CURRENT_ABI>
//! using fundamental_cardinal_t = typename fundamental_cardinal<Type, ABI>::type;
//! @endcode
//!
//! <br/>
//! #### Helper variable template
//!
//! @code{.cpp}
//! template<typename Type, regular_abi ABI = EVE_CURRENT_ABI>
//! inline constexpr auto fundamental_cardinal_v = fundamental_cardinal_t<Type, ABI>::value;
//! @endcode
//!
//! @code{.cpp}
//! // Cardinal template inline variable to use with functions like eve::load
//! template<typename Type, typename ABI = EVE_CURRENT_ABI>
//! inline constexpr fundamental_cardinal<Type,ABI> const fundamental = {};
//! @endcode
//! @}
//================================================================================================
template<typename Type, regular_abi ABI = EVE_CURRENT_ABI>
struct fundamental_cardinal
: fixed<ABI::template fundamental_cardinal<Type>>
{
using type = fixed<ABI::template fundamental_cardinal<Type>>;
};

template<typename Type, regular_abi ABI = EVE_CURRENT_ABI>
using fundamental_cardinal_t = typename fundamental_cardinal<Type, ABI>::type;

template<typename Type, regular_abi ABI = EVE_CURRENT_ABI>
constexpr inline auto fundamental_cardinal_v = fundamental_cardinal<Type, ABI>::value;

//================================================================================================
// product_type special case
//================================================================================================
namespace detail
{
template<typename T, regular_abi ABI> struct min_fundamental;

template<typename... T, regular_abi ABI>
struct min_fundamental<kumi::tuple<T...>,ABI>
{
static constexpr std::ptrdiff_t value = std::min({fundamental_cardinal<T,ABI>::value...});
};
}

template<kumi::product_type T, regular_abi ABI>
struct fundamental_cardinal<T,ABI> : fixed<detail::min_fundamental<kumi::as_tuple_t<T>,ABI>::value>
{
using type = fixed<detail::min_fundamental<kumi::as_tuple_t<T>,ABI>::value>;
};

template<typename Type, typename ABI = EVE_CURRENT_ABI>
inline constexpr fundamental_cardinal<Type,ABI> const fundamental = {};
}
3 changes: 3 additions & 0 deletions include/eve/arch/ppc/tags.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ namespace eve

template<typename Type>
static constexpr std::size_t expected_cardinal = bytes / sizeof(Type);

template<typename Type>
static constexpr std::size_t fundamental_cardinal = 16 / sizeof(Type);
};

//================================================================================================
Expand Down
7 changes: 5 additions & 2 deletions include/eve/arch/x86/tags.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,18 @@ namespace eve
//================================================================================================
template<std::size_t Size, bool Logical> struct x86_abi_
{
static constexpr std::size_t bits = Size;
static constexpr std::size_t bytes = Size/8;
static constexpr std::size_t bits = Size;
static constexpr std::size_t bytes = Size/8;
static constexpr bool is_wide_logical = Logical;

template<typename Type>
static constexpr bool is_full = ((Type::size() * sizeof(typename Type::value_type)) >= 16);

template<typename Type>
static constexpr std::size_t expected_cardinal = bytes / sizeof(Type);

template<typename Type>
static constexpr std::size_t fundamental_cardinal = 16 / sizeof(Type);
};

# if defined(SPY_SIMD_IS_X86_AVX512)
Expand Down
6 changes: 6 additions & 0 deletions include/eve/eve.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@
//! @godbolt{quick-start/constant.cpp}
//==================================================================================================

//==================================================================================================
//! @defgroup arch Architecture related Types and Helpers
//! @brief This module defines the types and helpers functions to properly handle
//! architecture specific components
//==================================================================================================

//==================================================================================================
//! @defgroup simd SIMD Types and Helpers
//! @brief This module defines the types and helpers functions to properly handle SIMD registers
Expand Down
1 change: 1 addition & 0 deletions test/unit/arch/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ set( SOURCES
is_supported.cpp
current_api.cpp
expected_cardinal.cpp
fundamental_cardinal.cpp
)

make_unit( "unit.arch" ${SOURCES} )
57 changes: 57 additions & 0 deletions test/unit/arch/fundamental_cardinal.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//==================================================================================================
/**
EVE - Expressive Vector Engine
Copyright : EVE Contributors & Maintainers
SPDX-License-Identifier: MIT
**/
//==================================================================================================
#include "test.hpp"
#include <eve/wide.hpp>
#include <eve/arch/fundamental_cardinal.hpp>

TTS_CASE("Check for 64 bits ABI fundamental cardinal")
{
TTS_EQUAL( (eve::fundamental_cardinal_v<double, eve::arm_64_>), 1);
TTS_EQUAL( (eve::fundamental_cardinal_v<float , eve::arm_64_>), 2);
TTS_EQUAL( (eve::fundamental_cardinal_v<short , eve::arm_64_>), 4);
TTS_EQUAL( (eve::fundamental_cardinal_v<char , eve::arm_64_>), 8);
};

TTS_CASE("Check for 128 bits ABI fundamental cardinal")
{
TTS_EQUAL( (eve::fundamental_cardinal_v<double, eve::arm_128_>), 1);
TTS_EQUAL( (eve::fundamental_cardinal_v<float , eve::arm_128_>), 2);
TTS_EQUAL( (eve::fundamental_cardinal_v<short , eve::arm_128_>), 4);
TTS_EQUAL( (eve::fundamental_cardinal_v<char , eve::arm_128_>), 8);

TTS_EQUAL( (eve::fundamental_cardinal_v<double, eve::ppc_>), 2 );
TTS_EQUAL( (eve::fundamental_cardinal_v<float , eve::ppc_>), 4 );
TTS_EQUAL( (eve::fundamental_cardinal_v<short , eve::ppc_>), 8 );
TTS_EQUAL( (eve::fundamental_cardinal_v<char , eve::ppc_>), 16 );

TTS_EQUAL( (eve::fundamental_cardinal_v<double, eve::x86_128_>), 2 );
TTS_EQUAL( (eve::fundamental_cardinal_v<float , eve::x86_128_>), 4 );
TTS_EQUAL( (eve::fundamental_cardinal_v<short , eve::x86_128_>), 8 );
TTS_EQUAL( (eve::fundamental_cardinal_v<char , eve::x86_128_>), 16 );

TTS_EQUAL( (eve::fundamental_cardinal_v<double, eve::emulated_>), 2 );
TTS_EQUAL( (eve::fundamental_cardinal_v<float , eve::emulated_>), 4 );
TTS_EQUAL( (eve::fundamental_cardinal_v<short , eve::emulated_>), 8 );
TTS_EQUAL( (eve::fundamental_cardinal_v<char , eve::emulated_>), 16 );
};

TTS_CASE("Check for 256 bits ABI fundamental cardinal")
{
TTS_EQUAL( (eve::fundamental_cardinal_v<double, eve::x86_256_>), 2 );
TTS_EQUAL( (eve::fundamental_cardinal_v<float , eve::x86_256_>), 4 );
TTS_EQUAL( (eve::fundamental_cardinal_v<short , eve::x86_256_>), 8 );
TTS_EQUAL( (eve::fundamental_cardinal_v<char , eve::x86_256_>), 16 );
};

TTS_CASE("Check for 512 bits ABI fundamental cardinal")
{
TTS_EQUAL( (eve::fundamental_cardinal_v<double, eve::x86_512_>), 2 );
TTS_EQUAL( (eve::fundamental_cardinal_v<float , eve::x86_512_>), 4 );
TTS_EQUAL( (eve::fundamental_cardinal_v<short , eve::x86_512_>), 8 );
TTS_EQUAL( (eve::fundamental_cardinal_v<char , eve::x86_512_>), 16 );
};

0 comments on commit 90ee1b1

Please sign in to comment.