Skip to content

Commit b3fdde4

Browse files
BMW-Contributor4og
authored andcommitted
Merge pull request #1710 from swh/pm_unchecked_store
Add `unchecked_store` GIT_ORIGIN_FUTURE_CPP_REV_ID: a918e4cbf819b424b9b16db95947f5e1322da901
1 parent 588370e commit b3fdde4

2 files changed

Lines changed: 75 additions & 29 deletions

File tree

score/language/futurecpp/include/score/private/simd/data_types.hpp

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -471,31 +471,6 @@ class basic_vec<T, Abi, true>
471471
/// [parallel] 9.6.1 4
472472
explicit SCORE_LANGUAGE_FUTURECPP_SIMD_ALWAYS_INLINE operator typename Abi::impl::type() const { return v_; }
473473

474-
/// \brief Replaces the elements of the simd object from an aligned memory address.
475-
///
476-
/// @pre [v, v + size()) is a valid range.
477-
/// @pre v shall point to storage aligned to score::cpp::simd::alignment_v<basic_vec>.
478-
///
479-
/// [parallel] 9.6.5 4, 5 and 6
480-
void SCORE_LANGUAGE_FUTURECPP_SIMD_ALWAYS_INLINE copy_to(value_type* const v, vector_aligned_tag) const
481-
{
482-
static_assert(detail::is_simd_flag_type_v<vector_aligned_tag>, "vector_aligned_tag not a simd flag type tag");
483-
SCORE_LANGUAGE_FUTURECPP_PRECONDITION_DBG((score::cpp::bit_cast<std::uintptr_t>(v) % alignment_v<basic_vec>) == 0U);
484-
Abi::impl::store_aligned(v, v_);
485-
}
486-
487-
/// \brief Replaces the elements of the simd object from an unaligned memory address.
488-
///
489-
/// @pre [v, v + size()) is a valid range.
490-
/// @pre v shall point to storage aligned to alignof(value_type).
491-
///
492-
/// [parallel] 9.6.5 4, 5 and 6
493-
void SCORE_LANGUAGE_FUTURECPP_SIMD_ALWAYS_INLINE copy_to(value_type* const v, element_aligned_tag = {}) const
494-
{
495-
static_assert(detail::is_simd_flag_type_v<element_aligned_tag>, "element_aligned_tag not a simd flag type tag");
496-
Abi::impl::store(v, v_);
497-
}
498-
499474
/// \brief The value of the ith element.
500475
///
501476
/// @pre i < size()
@@ -790,6 +765,47 @@ inline where_expression<basic_mask<T, Abi>, basic_vec<T, Abi>> where(const typen
790765
return {m, v};
791766
}
792767

768+
/// \brief Stores the elements of the simd object to an aligned range.
769+
///
770+
/// Note: `R` is currently more constrained than the standard requires. It expects `r` be convertible to
771+
/// `span<T, N>{r}` with static_extent `N`, where `N` is `basic_vec<T, Abi>::size()`. The current definition of `span`
772+
/// essentially restricts the value type of `R` to be also `T` and the size of `R` to be a constant expression.
773+
///
774+
/// @pre r shall point to storage aligned to score::cpp::simd::alignment_v<basic_vec>.
775+
///
776+
/// [parallel] 9.6.5 4, 5 and 6
777+
template <typename T,
778+
typename Abi,
779+
typename R,
780+
typename = std::enable_if_t<std::is_constructible_v<span<T, basic_vec<T, Abi>::size()>, R> //
781+
&& std::is_convertible_v<R, span<T, basic_vec<T, Abi>::size()>> //
782+
>>
783+
inline void unchecked_store(const basic_vec<T, Abi>& v, R&& r, vector_aligned_tag)
784+
{
785+
SCORE_LANGUAGE_FUTURECPP_PRECONDITION_DBG((score::cpp::bit_cast<std::uintptr_t>(std::data(r)) % alignment_v<basic_vec<T, Abi>>) == 0U);
786+
Abi::impl::store_aligned(std::data(std::forward<R>(r)), static_cast<typename Abi::impl::type>(v));
787+
}
788+
789+
/// \brief Store the elements of the simd object to an unaligned range.
790+
///
791+
/// Note: `R` is currently more constrained than the standard requires. It expects `r` be convertible to
792+
/// `span<T, N>{r}` with static_extent `N`, where `N` is `basic_vec<T, Abi>::size()`. The current definition of `span`
793+
/// essentially restricts the value type of `R` to be also `T` and the size of `R` to be a constant expression.
794+
///
795+
/// @pre r shall point to storage aligned to alignof(value_type).
796+
///
797+
/// [parallel] 9.6.5 4, 5 and 6
798+
template <typename T,
799+
typename Abi,
800+
typename R,
801+
typename = std::enable_if_t<std::is_constructible_v<span<T, basic_vec<T, Abi>::size()>, R> //
802+
&& std::is_convertible_v<R, span<T, basic_vec<T, Abi>::size()>> //
803+
>>
804+
inline void unchecked_store(const basic_vec<T, Abi>& v, R&& r, element_aligned_tag = {})
805+
{
806+
Abi::impl::store(std::data(std::forward<R>(r)), static_cast<typename Abi::impl::type>(v));
807+
}
808+
793809
} // namespace simd
794810
} // namespace score::cpp
795811

score/language/futurecpp/tests/simd_vec_test.cpp

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ TYPED_TEST(simd_vec_fixture, StoreByDefaultIsUnaligned)
241241
const auto scalars{integer_sequence<TypeParam>()};
242242
const TypeParam vector{scalars};
243243
std::array<typename TypeParam::value_type, vector.size()> result;
244-
vector.copy_to(result.data());
244+
score::cpp::simd::unchecked_store(vector, result);
245245

246246
EXPECT_EQ(result, scalars);
247247
}
@@ -253,7 +253,7 @@ TYPED_TEST(simd_vec_fixture, StoreUnaligned)
253253
const auto scalars{integer_sequence<TypeParam>()};
254254
const TypeParam vector{scalars};
255255
std::array<typename TypeParam::value_type, vector.size()> result;
256-
vector.copy_to(result.data(), score::cpp::simd::element_aligned);
256+
score::cpp::simd::unchecked_store(vector, result, score::cpp::simd::element_aligned);
257257

258258
EXPECT_EQ(result, scalars);
259259
}
@@ -266,7 +266,7 @@ TYPED_TEST(simd_vec_fixture, StoreAligned)
266266
const auto scalars{integer_sequence<TypeParam>()};
267267
const TypeParam vector{scalars};
268268
alignas(score::cpp::simd::alignment_v<TypeParam>) std::array<value_type, vector.size()> result;
269-
vector.copy_to(result.data(), score::cpp::simd::vector_aligned);
269+
score::cpp::simd::unchecked_store(vector, result, score::cpp::simd::vector_aligned);
270270

271271
EXPECT_EQ(result, scalars);
272272
}
@@ -283,8 +283,38 @@ TYPED_TEST(simd_vec_fixture, StoreAligned_WhenCopyingToUnalignedMemory_ThenPreco
283283
using value_type = typename TypeParam::value_type;
284284
const TypeParam vector{value_type{23}};
285285
alignas(score::cpp::simd::alignment_v<TypeParam>) std::array<value_type, vector.size() + 1U> scalars;
286+
const score::cpp::span<value_type, TypeParam::size()> result{&scalars[1U], vector.size()};
286287

287-
SCORE_LANGUAGE_FUTURECPP_EXPECT_CONTRACT_VIOLATED(vector.copy_to(&scalars[1], score::cpp::simd::vector_aligned));
288+
SCORE_LANGUAGE_FUTURECPP_EXPECT_CONTRACT_VIOLATED(score::cpp::simd::unchecked_store(vector, result, score::cpp::simd::vector_aligned));
289+
}
290+
291+
/// @testmethods TM_REQUIREMENT
292+
/// @requirement CB-#18398050
293+
TYPED_TEST(simd_vec_fixture, CannotConstruct_WhenSizeIsNotAConstantExpression)
294+
{
295+
const auto test = [](auto&& r) -> decltype(score::cpp::simd::unchecked_store(std::declval<TypeParam>(),
296+
std::forward<decltype(r)>(r))) {};
297+
298+
using value_type = typename TypeParam::value_type;
299+
300+
{ // cannot call `unchecked_store` because types have runtime size
301+
static_assert(!std::is_invocable_v<decltype(test), std::vector<value_type>>);
302+
static_assert(!std::is_invocable_v<decltype(test), std::vector<value_type>&>);
303+
static_assert(!std::is_invocable_v<decltype(test), score::cpp::span<value_type>>);
304+
static_assert(!std::is_invocable_v<decltype(test), score::cpp::span<value_type>&>);
305+
}
306+
307+
{ // cannot store to range because it is `const`, i.e., non-modifiable
308+
static_assert(!std::is_invocable_v<decltype(test), score::cpp::span<const value_type, TypeParam::size()>>);
309+
static_assert(!std::is_invocable_v<decltype(test), score::cpp::span<const value_type, TypeParam::size()>&>);
310+
static_assert(!std::is_invocable_v<decltype(test), std::array<value_type, TypeParam::size()>>);
311+
}
312+
313+
{ // sanity check that test works
314+
static_assert(std::is_invocable_v<decltype(test), score::cpp::span<value_type, TypeParam::size()>>);
315+
static_assert(std::is_invocable_v<decltype(test), score::cpp::span<value_type, TypeParam::size()>&>);
316+
static_assert(std::is_invocable_v<decltype(test), std::array<value_type, TypeParam::size()>&>);
317+
}
288318
}
289319

290320
/// @testmethods TM_REQUIREMENT

0 commit comments

Comments
 (0)