diff --git a/sycl/include/sycl/detail/common.hpp b/sycl/include/sycl/detail/common.hpp index 79659769418fa..610b6dfa12d20 100644 --- a/sycl/include/sycl/detail/common.hpp +++ b/sycl/include/sycl/detail/common.hpp @@ -466,6 +466,56 @@ static T convertToArrayOfN(T OldObj) { return NewObj; } +// Helper function for concatenating two std::array. +template +constexpr std::array +ConcatArrays(const std::array &A1, + const std::array &A2, + std::index_sequence, std::index_sequence) { + return {A1[Is1]..., A2[Is2]...}; +} +template +constexpr std::array ConcatArrays(const std::array &A1, + const std::array &A2) { + return ConcatArrays(A1, A2, std::make_index_sequence(), + std::make_index_sequence()); +} + +// Utility for creating an std::array from the results of flattening the +// arguments using a flattening functor. +template typename FlattenF, + typename... ArgTN> +struct ArrayCreator; +template typename FlattenF, + typename ArgT, typename... ArgTN> +struct ArrayCreator { + static constexpr auto Create(const ArgT &Arg, const ArgTN &...Args) { + auto ImmArray = FlattenF()(Arg); + if constexpr (sizeof...(Args)) + return ConcatArrays( + ImmArray, ArrayCreator::Create(Args...)); + else + return ImmArray; + } +}; +template typename FlattenF> +struct ArrayCreator { + static constexpr auto Create() { return std::array{}; } +}; + +// Helper function for creating an arbitrary sized array with the same value +// repeating. +template +static constexpr std::array +RepeatValueHelper(const T &Arg, std::index_sequence) { + auto ReturnArg = [&](size_t) { return Arg; }; + return {ReturnArg(Is)...}; +} +template +static constexpr std::array RepeatValue(const T &Arg) { + return RepeatValueHelper(Arg, std::make_index_sequence()); +} + } // namespace detail } // __SYCL_INLINE_VER_NAMESPACE(_V1) } // namespace sycl diff --git a/sycl/include/sycl/half_type.hpp b/sycl/include/sycl/half_type.hpp index ace7be7352c6c..b080028d71a5c 100644 --- a/sycl/include/sycl/half_type.hpp +++ b/sycl/include/sycl/half_type.hpp @@ -252,6 +252,11 @@ template struct half_vec { StorageT s[NumElements]; __SYCL_CONSTEXPR_HALF half_vec() : s{0.0f} { initialize_data(); } + template && ...)>> + __SYCL_CONSTEXPR_HALF half_vec(const Ts &...hs) : s{hs...} {} + constexpr void initialize_data() { for (size_t i = 0; i < NumElements; ++i) { s[i] = StorageT(0.0f); diff --git a/sycl/include/sycl/marray.hpp b/sycl/include/sycl/marray.hpp index f13453d0691de..fab94a5657bb9 100644 --- a/sycl/include/sycl/marray.hpp +++ b/sycl/include/sycl/marray.hpp @@ -39,65 +39,6 @@ template struct GetMArrayArgsSize { static constexpr std::size_t value = 1 + GetMArrayArgsSize::value; }; -// Helper function for concatenating two std::array. -template -constexpr std::array -ConcatArrays(const std::array &A1, - const std::array &A2, - std::index_sequence, std::index_sequence) { - return {A1[Is1]..., A2[Is2]...}; -} -template -constexpr std::array ConcatArrays(const std::array &A1, - const std::array &A2) { - return ConcatArrays(A1, A2, std::make_index_sequence(), - std::make_index_sequence()); -} - -// Utility trait for creating an std::array from an marray. -template -constexpr std::array -MArrayToArray(const marray &A, std::index_sequence) { - return {static_cast(A.MData[Is])...}; -} -template -constexpr std::array MArrayToArray(const marray &A) { - return MArrayToArray(A, std::make_index_sequence()); -} - -// Utility for creating an std::array from a arguments of either types -// convertible to DataT or marrays of a type convertible to DataT. -template struct ArrayCreator; -template -struct ArrayCreator { - static constexpr std::array::value> - Create(const ArgT &Arg, const ArgTN &...Args) { - std::array ImmArray{static_cast(Arg)}; - if constexpr (sizeof...(Args)) - return ConcatArrays(ImmArray, - ArrayCreator::Create(Args...)); - else - return ImmArray; - } -}; -template -struct ArrayCreator, ArgTN...> { - static constexpr std::array, ArgTN...>::value> - Create(const marray &Arg, const ArgTN &...Args) { - auto ImmArray = MArrayToArray(Arg); - if constexpr (sizeof...(Args)) - return ConcatArrays(ImmArray, - ArrayCreator::Create(Args...)); - else - return ImmArray; - } -}; -template struct ArrayCreator { - static constexpr std::array Create() { - return std::array{}; - } -}; } // namespace detail /// Provides a cross-platform math array class template that works on @@ -129,12 +70,35 @@ template class marray { template struct AllSuitableArgTypes : std::conjunction...> {}; - // FIXME: MArrayToArray needs to be a friend to access MData. If the subscript - // operator is made constexpr this can be removed. - template - friend constexpr std::array - detail::MArrayToArray(const marray &, - std::index_sequence); + // Utility trait for creating an std::array from an marray argument. + template + static constexpr std::array + MArrayToArray(const marray &A, std::index_sequence) { + return {static_cast(A.MData[Is])...}; + } + template + static constexpr std::array + FlattenMArrayArgHelper(const marray &A) { + return MArrayToArray(A, std::make_index_sequence()); + } + template + static constexpr auto FlattenMArrayArgHelper(const T &A) { + return std::array{static_cast(A)}; + } + template struct FlattenMArrayArg { + constexpr auto operator()(const T &A) const { + return FlattenMArrayArgHelper(A); + } + }; + + // Alias for shortening the marray arguments to array converter. + template + using MArrayArgArrayCreator = + detail::ArrayCreator; + + // FIXME: Other marray specializations needs to be a friend to access MData. + // If the subscript operator is made constexpr this can be removed. + template friend class marray; constexpr void initialize_data(const Type &Arg) { for (size_t i = 0; i < NumElements; ++i) { @@ -159,7 +123,7 @@ template class marray { AllSuitableArgTypes::value && detail::GetMArrayArgsSize::value == NumElements>> constexpr marray(const ArgTN &...Args) - : marray{detail::ArrayCreator::Create(Args...), + : marray{MArrayArgArrayCreator::Create(Args...), std::make_index_sequence()} {} constexpr marray(const marray &Rhs) = default; diff --git a/sycl/include/sycl/types.hpp b/sycl/include/sycl/types.hpp index f9aa883009e09..a37dc0f76a978 100644 --- a/sycl/include/sycl/types.hpp +++ b/sycl/include/sycl/types.hpp @@ -585,6 +585,58 @@ template class vec { SizeChecker, std::false_type> {}; + // Utility trait for creating an std::array from an vector argument. + template + static constexpr std::array + VecToArray(const vec &V, std::index_sequence) { + return {static_cast(V.getValue(Is))...}; + } + template class T4, int... T5, std::size_t... Is> + static constexpr std::array + VecToArray(const detail::SwizzleOp, T2, T3, T4, T5...> &V, + std::index_sequence) { + return {static_cast(V.getValue(Is))...}; + } + template class T4, int... T5, std::size_t... Is> + static constexpr std::array + VecToArray(const detail::SwizzleOp, T2, T3, T4, T5...> &V, + std::index_sequence) { + return {static_cast(V.getValue(Is))...}; + } + template + static constexpr std::array + FlattenVecArgHelper(const vec &A) { + return VecToArray(A, std::make_index_sequence()); + } + template class T4, int... T5> + static constexpr std::array FlattenVecArgHelper( + const detail::SwizzleOp, T2, T3, T4, T5...> &A) { + return VecToArray(A, std::make_index_sequence()); + } + template class T4, int... T5> + static constexpr std::array FlattenVecArgHelper( + const detail::SwizzleOp, T2, T3, T4, T5...> &A) { + return VecToArray(A, std::make_index_sequence()); + } + template + static constexpr auto FlattenVecArgHelper(const T &A) { + return std::array{vec_data::get(A)}; + } + template struct FlattenVecArg { + constexpr auto operator()(const T &A) const { + return FlattenVecArgHelper(A); + } + }; + + // Alias for shortening the vec arguments to array converter. + template + using VecArgArrayCreator = + detail::ArrayCreator; + #define __SYCL_ALLOW_VECTOR_SIZES(num_elements) \ template \ struct SizeChecker, tail...> \ @@ -672,6 +724,14 @@ template class vec { using EnableIfSuitableNumElements = typename detail::enable_if_t< SizeChecker<0, NumElements, argTN...>::value>; + template + constexpr vec(const std::array, NumElements> &Arr, + std::index_sequence) + : m_Data{Arr[Is]...} {} + + constexpr vec(const std::array, NumElements> &Arr) + : vec{Arr, std::make_index_sequence()} {} + public: using element_type = DataT; using rel_t = detail::rel_t; @@ -720,9 +780,8 @@ template class vec { T>; template - explicit constexpr vec(const EnableIfNotHostHalf &arg) { - m_Data = (DataType)vec_data::get(arg); - } + explicit constexpr vec(const EnableIfNotHostHalf &arg) + : m_Data{(DataType)vec_data::get(arg)} {} template typename detail::enable_if_t< @@ -735,11 +794,9 @@ template class vec { } template - explicit constexpr vec(const EnableIfHostHalf &arg) { - for (int i = 0; i < NumElements; ++i) { - setValue(i, arg); - } - } + explicit constexpr vec(const EnableIfHostHalf &arg) + : vec{detail::RepeatValue( + static_cast>(arg))} {} template typename detail::enable_if_t< @@ -753,11 +810,9 @@ template class vec { return *this; } #else - explicit constexpr vec(const DataT &arg) { - for (int i = 0; i < NumElements; ++i) { - setValue(i, arg); - } - } + explicit constexpr vec(const DataT &arg) + : vec{detail::RepeatValue( + static_cast>(arg))} {} template typename detail::enable_if_t< @@ -827,9 +882,8 @@ template class vec { // base types are match and that the NumElements == sum of lengths of args. template , typename = EnableIfSuitableNumElements> - constexpr vec(const argTN &...args) { - vaargCtorHelper(0, args...); - } + constexpr vec(const argTN &...args) + : vec{VecArgArrayCreator, argTN...>::Create(args...)} {} // TODO: Remove, for debug purposes only. void dump() { @@ -1268,7 +1322,7 @@ template class vec { template > - DataT getValue(EnableIfNotHostHalf Index, int) const { + constexpr DataT getValue(EnableIfNotHostHalf Index, int) const { return vec_data::get(m_Data[Index]); } @@ -1280,7 +1334,7 @@ template class vec { template > - DataT getValue(EnableIfHostHalf Index, int) const { + constexpr DataT getValue(EnableIfHostHalf Index, int) const { return vec_data::get(m_Data.s[Index]); } #else // __SYCL_USE_EXT_VECTOR_TYPE__ @@ -1292,7 +1346,7 @@ template class vec { template > - DataT getValue(int Index, int) const { + constexpr DataT getValue(int Index, int) const { return vec_data::get(m_Data.s[Index]); } #endif // __SYCL_USE_EXT_VECTOR_TYPE__ @@ -1321,59 +1375,6 @@ template class vec { return (NumElements == 1) ? getValue(Index, 0) : getValue(Index, 0.f); } - // Helpers for variadic template constructor of vec. - template - constexpr int vaargCtorHelper(int Idx, const T &arg) { - setValue(Idx, arg); - return Idx + 1; - } - - template - constexpr int vaargCtorHelper(int Idx, const vec &arg) { - for (size_t I = 0; I < NumElements_; ++I) { - setValue(Idx + I, arg.getValue(I)); - } - return Idx + NumElements_; - } - - template class T4, int... T5> - constexpr int - vaargCtorHelper(int Idx, const detail::SwizzleOp, - T2, T3, T4, T5...> &arg) { - size_t NumElems = sizeof...(T5); - for (size_t I = 0; I < NumElems; ++I) { - setValue(Idx + I, arg.getValue(I)); - } - return Idx + NumElems; - } - - template class T4, int... T5> - constexpr int - vaargCtorHelper(int Idx, - const detail::SwizzleOp, T2, - T3, T4, T5...> &arg) { - size_t NumElems = sizeof...(T5); - for (size_t I = 0; I < NumElems; ++I) { - setValue(Idx + I, arg.getValue(I)); - } - return Idx + NumElems; - } - - template - constexpr void vaargCtorHelper(int Idx, const T1 &arg, const argTN &...args) { - int NewIdx = vaargCtorHelper(Idx, arg); - vaargCtorHelper(NewIdx, args...); - } - - template - constexpr void vaargCtorHelper(int Idx, const vec &arg, - const argTN &...args) { - int NewIdx = vaargCtorHelper(Idx, arg); - vaargCtorHelper(NewIdx, args...); - } - // fields // Used "__SYCL_ALIGNED_VAR" instead "alignas" to handle MSVC compiler. // For MSVC compiler max alignment is 64, e.g. vec required diff --git a/sycl/test/basic_tests/vectors/constexpr-constructor.cpp b/sycl/test/basic_tests/vectors/constexpr-constructor.cpp new file mode 100644 index 0000000000000..993a02e778c7a --- /dev/null +++ b/sycl/test/basic_tests/vectors/constexpr-constructor.cpp @@ -0,0 +1,65 @@ +// RUN: %clangxx -fsycl -fsyntax-only -Wno-deprecated-declarations %s +// RUN: %clangxx -fsycl -D__NO_EXT_VECTOR_TYPE_ON_HOST__ -fsyntax-only -Wno-deprecated-declarations %s + +#include + +#include + +#define DEFINE_CONSTEXPR_VECTOR(name, type, size) \ + constexpr sycl::vec name##_##size{0}; + +#define DEFINE_CONSTEXPR_VECTOR_INIT_NON_ZERO(name, type, size, init) \ + constexpr sycl::vec name##_##size{init}; + +#define DEFINE_CONSTEXPR_VECTOR_FOR_TYPE(type) \ + DEFINE_CONSTEXPR_VECTOR(type, type, 1) \ + DEFINE_CONSTEXPR_VECTOR(type, type, 2) \ + DEFINE_CONSTEXPR_VECTOR(type, type, 3) \ + DEFINE_CONSTEXPR_VECTOR(type, type, 4) \ + DEFINE_CONSTEXPR_VECTOR(type, type, 8) \ + DEFINE_CONSTEXPR_VECTOR(type, type, 16) + +#define DEFINE_CONSTEXPR_VECTOR_FOR_TYPE_NAMED(type, name) \ + DEFINE_CONSTEXPR_VECTOR(name, type, 1) \ + DEFINE_CONSTEXPR_VECTOR(name, type, 2) \ + DEFINE_CONSTEXPR_VECTOR(name, type, 3) \ + DEFINE_CONSTEXPR_VECTOR(name, type, 4) \ + DEFINE_CONSTEXPR_VECTOR(name, type, 8) \ + DEFINE_CONSTEXPR_VECTOR(name, type, 16) + +int main() { + + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE_NAMED(sycl::byte, syclbyte) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE_NAMED(sycl::half, half) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE(bool) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE(char) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE_NAMED(signed char, schar) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE_NAMED(unsigned char, uchar) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE_NAMED(short int, short) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE_NAMED(unsigned short int, ushort) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE(int) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE_NAMED(unsigned int, uint) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE_NAMED(long int, long) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE_NAMED(unsigned long int, ulong) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE_NAMED(long long int, longlong) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE_NAMED(unsigned long long int, ulonglong) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE(float) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE(double) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE_NAMED(std::int8_t, int8) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE_NAMED(std::uint8_t, uint8) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE_NAMED(std::int16_t, int16) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE_NAMED(std::uint16_t, uint16) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE_NAMED(std::int32_t, int32) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE_NAMED(std::uint32_t, uint32) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE_NAMED(std::int64_t, int64) + DEFINE_CONSTEXPR_VECTOR_FOR_TYPE_NAMED(std::uint64_t, uint64) + + DEFINE_CONSTEXPR_VECTOR_INIT_NON_ZERO(stdbyte, std::byte, 1, std::byte{1}); + DEFINE_CONSTEXPR_VECTOR_INIT_NON_ZERO(stdbyte, std::byte, 2, std::byte{1}); + DEFINE_CONSTEXPR_VECTOR_INIT_NON_ZERO(stdbyte, std::byte, 3, std::byte{1}); + DEFINE_CONSTEXPR_VECTOR_INIT_NON_ZERO(stdbyte, std::byte, 4, std::byte{1}); + DEFINE_CONSTEXPR_VECTOR_INIT_NON_ZERO(stdbyte, std::byte, 8, std::byte{1}); + DEFINE_CONSTEXPR_VECTOR_INIT_NON_ZERO(stdbyte, std::byte, 16, std::byte{1}); + + return 0; +} diff --git a/sycl/test/basic_tests/vectors/negative.cpp b/sycl/test/basic_tests/vectors/negative.cpp index 1bdb923ece81c..5a5fde4094b9a 100644 --- a/sycl/test/basic_tests/vectors/negative.cpp +++ b/sycl/test/basic_tests/vectors/negative.cpp @@ -2,6 +2,7 @@ // DataT or N produces a verbose error message. // // RUN: %clangxx %fsycl-host-only -fsyntax-only -Xclang -verify -Xclang -verify-ignore-unexpected=note,error %s +// RUN: %clangxx %fsycl-host-only -D__NO_EXT_VECTOR_TYPE_ON_HOST__ -fsyntax-only -Xclang -verify -Xclang -verify-ignore-unexpected=note,error %s // // Note: there is one more error being emitted: "requested alignemnt is not a // power of 2" It happens because in all cases above we weren't able to select diff --git a/sycl/test/basic_tests/vectors/vectors.cpp b/sycl/test/basic_tests/vectors/vectors.cpp index 929e77abbab13..4acc46d1b3547 100644 --- a/sycl/test/basic_tests/vectors/vectors.cpp +++ b/sycl/test/basic_tests/vectors/vectors.cpp @@ -1,5 +1,7 @@ -// RUN: %clangxx -fsycl %s -o %t.out -// RUN: %t.out +// RUN: %clangxx -fsycl %s -o %t_default.out +// RUN: %t_default.out +// RUN: %clangxx -fsycl -D__NO_EXT_VECTOR_TYPE_ON_HOST__ %s -o %t_noext.out +// RUN: %t_noext.out //==--------------- vectors.cpp - SYCL vectors test ------------------------==// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.