Details
- Reviewers
philnik - Group Reviewers
Restricted Project - Commits
- rGce5652c78ac0: [libcxx] <experimental/simd> Added simd width functions, simd_size traits and…
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
The implementation itself looks good, but the tests need some work.
libcxx/docs/Status/ParallelismProjects.csv | ||
---|---|---|
11 ↗ | (On Diff #531628) | This looks wrong. Should there have been two lines? |
17 ↗ | (On Diff #531628) | I'm a bit confused by this entry and the one below. What exactly are you trying to mark as completed? |
libcxx/include/experimental/__simd/traits.h | ||
55 | This needs a SFINAE test. I'm also not sure this works on the _v version. | |
libcxx/include/experimental/__simd/utility.h | ||
10–11 | utility doesn't really seem like that nice of a name for a header. Do you have plans to add more functions? If yes, which ones? | |
13 | Please includes the granularized headers instead. | |
20–22 | Why isn't this simply a variable template? | |
libcxx/test/std/experimental/simd/simd.class/simd_width.pass.cpp | ||
24–25 | This way we make sure the functions is static and constexpr. | |
32 | Why aren't you calling CheckSimdWidth directly? | |
libcxx/test/std/experimental/simd/simd.traits/simd_size.pass.cpp | ||
63 | The 16 here and _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES are implementation-defined, so this should either be moved into a new test in test/libcxx or be a LIBCPP_STATIC_ASSERT. | |
86–121 | This looks like a really complicated way to do this. For scalar, compatible and native it doesn't look like you make any use of the instantiation facility. They could instead just be in the main(). |
libcxx/docs/Status/ParallelismProjects.csv | ||
---|---|---|
11 ↗ | (On Diff #531628) |
This line corresponds to traits simd_size and simd_size_v. And traits is_abi_tag_v is the dependency because the implementation of simd_size_v used it for SFINAE check. Am I right? |
17 ↗ | (On Diff #531628) |
This line and the one below correspond to the function size() in class simd and class simd_mask. And the function size() in class simd is dependent on traits simd_size_v. The function size() in class simd_mask is dependent on the function size() in class simd. |
libcxx/include/experimental/__simd/utility.h | ||
10–11 | Yes, this file is mainly used to implement some internal functions that are not easy to classify. You can see them here: https://reviews.llvm.org/D139421#change-93rWXSd8B8Z9 |
libcxx/include/experimental/__simd/utility.h | ||
---|---|---|
20–22 | This is mainly used to give a flag for SFINAE check. I think it's better to use it as a function. WDYT? |
This looks pretty good now. I have a few comments, but nothing major.
libcxx/docs/Status/ParallelismProjects.csv | ||
---|---|---|
11 ↗ | (On Diff #531628) | Ahh, I missed that is_abi_tag is a dependency. Never mind then. |
17 ↗ | (On Diff #531628) | Ok. I think it would be clearer to use simd<>::size() and simd_mask<>::size()instead. |
libcxx/include/experimental/__simd/simd.h | ||
27 | These aliases need tests too. Just check for a few instantiations that they exist and have the expected types. | |
libcxx/include/experimental/__simd/utility.h | ||
10–11 | Hmm, I can't come up with a good name for them right now. No action required right now. | |
20–22 | Since this is a type trait, a variable template is the more canonical way to write it. It also avoids evaluating the same trait multiple times. | |
libcxx/test/libcxx/transitive_includes/cxx03.csv | ||
265 | These shouldn't be required anymore. |
@philnik Hi, we have added the SFINAE false test for simd_size. But the error messages seem not easy to read. Do you have any suggestions?
I think you did something wrong. You shouldn't need a .verify.cpp for SFINAE testing, and looking at the error message the types don't SFINAE away.
Something like
template <class T, class U, class = void> struct check_sfinae : false_type {}; template <class T, class U> struct check_sfinae<void_t<ex::simd_size<T, U>>> : true_type {}; static_assert(!check_sfinae<int , ex::native_simd<int>>::value);
should work just fine in a normal .pass.cpp. If you get an error, either I did something wrong in the SFINAE test, or the implementation of ex::simd_size is wrong (because it doesn't SFINAE away).
I'm pretty sure that variable templates can't SFINAE away.
@philnik Hi, we rewrite the SFINAE test as you given style. It seems no errors come out. Does it mean our implementations right?
Looks correct to me. TIL that variable templates can SFINAE away. I think we are missing some test coverage elsewhere...
LGTM % comment. Thanks! I'm really looking forward to having a great <experimental/simd> implementation.
libcxx/test/std/experimental/simd/simd.traits/simd_size.pass.cpp | ||
---|---|---|
59–63 | Please also add tests for simd_size, and not just for simd_size_v. |
Errors come out with SFINAE tests for simd_size. Same tests pass with simd_size_v.
You can see the situation in following URL and try the other parameters:
https://godbolt.org/z/EjWxz6P37
Do you have any solutions?
libcxx/include/experimental/__simd/traits.h | ||
---|---|---|
61 | As discussed in D153319#inline-1502156, this needs to be updated. |
@philnik Hi! We found that the current implementation might have an unexpected behavior. Because we do not check the template parameter of simd_size_v, it gives value with invalid first parameter.
https://godbolt.org/z/o8o4fWe7n
In the document, simd_size is implemented first and using simd_size_v as value of simd_size. Therefore, the template parameters of simd_size_v are checked by simd_size. Here is the behavior with GCC implementation: https://godbolt.org/z/1vYTsnbsd
I implement in the current form because you told me earlier that implementing variable first can avoid instantiating a class every time. But it seems to have some minor issues at the moment.
By the way, memory_alignment_v will also have the same issue. Do you have any suggestions for solving this?
Good catch! I'm actually learning some really interesting things about template variables and how they interact with things. I think the easiest solution for now is to use the class to implement the _v version. It's probably not worth the effort to try to avoid the instantiation. That's more of a nice to have than an absolute need to have. Please also add a test for this. Something like
static_assert(!std::experimental::simd_size_v<...>); // expected-error {{no member named 'value'}}
should be good enough.
It seems CI not happy with
simd_size_v.verify.cppstatic_assert(!std::experimental::simd_size_v<...>); // expected-error {{no member named 'value'}}
Can I use
simd_size_v.verify.cppstd::experimental::simd_size_v<...>; // expected-error {{no member named 'value'}}
instead? Or do you have any solutions?
I'm not sure, but these CI errors with macOS don't seem like the issue with this patch, do they?
I'm seeing a bunch of test failures with this (and the subsequent) changes on 32-bit x86. They all seem to be related to size assertions, e.g.:
$ ":" "COMPILED WITH" $ "/usr/lib/ccache/bin/i686-pc-linux-gnu-clang++" "/var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/std/experimental/simd/simd.class/simd_alias.pass.cpp" "-pthread" "--target=i686-pc-linux-g nu" "-nostdinc++" "-I" "/var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x86_32.x86/include/c++/v1" "-I" "/var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x 86_32.x86/include/c++/v1" "-I" "/var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/support" "-std=c++26" "-Werror" "-Wall" "-Wctad-maybe-unsupported" "-Wextra" "-Wshadow" "-Wundef" "-Wunused-t emplate" "-Wno-unused-command-line-argument" "-Wno-attributes" "-Wno-pessimizing-move" "-Wno-noexcept-type" "-Wno-atomic-alignment" "-Wno-reserved-module-identifier" "-Wno-user-defined-literals" "-Wno-tautologi cal-compare" "-Wsign-compare" "-Wunused-variable" "-Wunused-parameter" "-Wunreachable-code" "-Wno-unused-local-typedef" "-Wno-local-type-template-args" "-Wno-c++11-extensions" "-Wno-unknown-pragmas" "-Wno-pass- failed" "-Wno-mismatched-new-delete" "-Wno-redundant-move" "-Wno-self-move" "-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER" "-D_LIBCPP_ENABLE_EXPERIMENTAL" "-Werror=thread-safety" "-Wuser-defined-warnings" "-lc++experi mental" "-nostdlib++" "-L" "/var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x86_32.x86/lib" "-Wl,-rpath,/var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x8 6_32.x86/lib" "-lc++" "-o" "/var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x86_32.x86/test/std/experimental/simd/simd.class/Output/simd_alias.pass.cpp.dir/t.tmp.exe" # command stderr: In file included from /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/std/experimental/simd/simd.class/simd_alias.pass.cpp:19: In file included from /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/std/experimental/simd/simd.class/../test_utils.h:17: In file included from /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x86_32.x86/include/c++/v1/experimental/simd:81: In file included from /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x86_32.x86/include/c++/v1/experimental/__simd/abi_tag.h:14: /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x86_32.x86/include/c++/v1/experimental/__simd/vec_ext.h:31:29: error: vector size not an integral multiple of component size 31 | _Tp __data __attribute__((__vector_size__(std::__bit_ceil((sizeof(_Tp) * _Np))))); | ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x86_32.x86/include/c++/v1/experimental/__simd/simd.h:33:12: note: in instantiation of template class 'std::experimental::__simd_storag e<long double, std::experimental::simd_abi::__vec_ext<1>>' requested here 33 | _Storage __s_; | ^ /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/std/experimental/simd/simd.class/simd_alias.pass.cpp:28:47: note: in instantiation of template class 'std::experimental::simd<long double, st d::experimental::simd_abi::__vec_ext<1>>' requested here 28 | static_assert(std::is_same_v<typename ex::simd<T, SimdAbi>::value_type, T>); | ^ /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/support/type_algorithms.h:52:23: note: in instantiation of function template specialization 'CheckSimdAlias<long double, 1>::operator()<std:: experimental::simd_abi::__vec_ext<1>>' requested here 52 | swallow((f.template operator()<Types>(), 0)...); | ^ /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/support/type_algorithms.h:52:23: note: in instantiation of function template specialization 'TestAllSimdAbiFunctor<CheckSimdAlias>::operator( )<long double>' requested here /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/std/experimental/simd/simd.class/simd_alias.pass.cpp:35:3: note: in instantiation of function template specialization 'test_all_simd_abi<CheckSimdAlias>' requested here 35 | test_all_simd_abi<CheckSimdAlias>(); | ^ In file included from /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/std/experimental/simd/simd.class/simd_alias.pass.cpp:19: In file included from /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/std/experimental/simd/simd.class/../test_utils.h:18: /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/support/type_algorithms.h:52:23: error: no matching member function for call to 'operator()' 52 | swallow((f.template operator()<Types>(), 0)...); | ~~~~~~~~~~~^~~~~~~~~~~~~~~~~ /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/std/experimental/simd/simd.class/../test_utils.h:31:13: note: in instantiation of function template specialization 'types::for_each<std::expe rimental::simd_abi::__vec_ext<1>, std::experimental::simd_abi::__vec_ext<1>, CheckSimdAlias<long double, 1>>' requested here 31 | (types::for_each(sized_abis<T, Ns + 1>{}, F<T, Ns + 1>{}), ...); | ^ /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/std/experimental/simd/simd.class/../test_utils.h:39:5: note: in instantiation of function template specialization 'TestAllSimdAbiFunctor<Chec kSimdAlias>::instantiate_with_n<long double, 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 16U, 17U, 18U, 19U, 20U, 21U, 22U, 23U, 24U, 25U, 26U, 27U, 28U, 29U, 30U>' requested here 39 | instantiate_with_n<T>(std::make_index_sequence<max_simd_size - 1>{}); | ^ /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/support/type_algorithms.h:52:23: note: in instantiation of function template specialization 'TestAllSimdAbiFunctor<CheckSimdAlias>::operator()<long double>' requested here 52 | swallow((f.template operator()<Types>(), 0)...); | ^ /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/std/experimental/simd/simd.class/simd_alias.pass.cpp:35:3: note: in instantiation of function template specialization 'test_all_simd_abi<Chec kSimdAlias>' requested here 35 | test_all_simd_abi<CheckSimdAlias>(); | ^ /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/std/experimental/simd/simd.class/simd_alias.pass.cpp:27:8: note: candidate template ignored: substitution failure [with SimdAbi = std::experi mental::simd_abi::__vec_ext<1>] 27 | void operator()() { | ^ ---- $ ":" "COMPILED WITH" $ "/usr/lib/ccache/bin/i686-pc-linux-gnu-clang++" "/var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/std/experimental/simd/simd.mask.class/simd_mask_alias.pass.cpp" "-pthread" "--target=i686-pc-linux-gnu" "-nostdinc++" "-I" "/var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x86_32.x86/include/c++/v1" "-I" "/var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x86_32.x86/include/c++/v1" "-I" "/var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/support" "-std=c++26" "-Werror" "-Wall" "-Wctad-maybe-unsupported" "-Wextra" "-Wshadow" "-Wundef" "-Wunused-template" "-Wno-unused-command-line-argument" "-Wno-attributes" "-Wno-pessimizing-move" "-Wno-noexcept-type" "-Wno-atomic-alignment" "-Wno-reserved-module-identifier" "-Wno-user-defined-literals" "-Wno-tautological-compare" "-Wsign-compare" "-Wunused-variable" "-Wunused-parameter" "-Wunreachable-code" "-Wno-unused-local-typedef" "-Wno-local-type-template-args" "-Wno-c++11-extensions" "-Wno-unknown-pragmas" "-Wno-pass-failed" "-Wno-mismatched-new-delete" "-Wno-redundant-move" "-Wno-self-move" "-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER" "-D_LIBCPP_ENABLE_EXPERIMENTAL" "-Werror=thread-safety" "-Wuser-defined-warnings" "-lc++experimental" "-nostdlib++" "-L" "/var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x86_32.x86/lib" "-Wl,-rpath,/var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x86_32.x86/lib" "-lc++" "-o" "/var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x86_32.x86/test/std/experimental/simd/simd.mask.class/Output/simd_mask_alias.pass.cpp.dir/t.tmp.exe" # command stderr: In file included from /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/std/experimental/simd/simd.mask.class/simd_mask_alias.pass.cpp:19: In file included from /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/std/experimental/simd/simd.mask.class/../test_utils.h:17: In file included from /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x86_32.x86/include/c++/v1/experimental/simd:81: In file included from /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x86_32.x86/include/c++/v1/experimental/__simd/abi_tag.h:14: In file included from /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x86_32.x86/include/c++/v1/experimental/__simd/vec_ext.h:16: /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x86_32.x86/include/c++/v1/experimental/__simd/utility.h:53:19: error: static assertion failed due to requirement 'sizeof(long double) == 0': Unexpected size 53 | static_assert(sizeof(_Tp) == 0, "Unexpected size"); | ^~~~~~~~~~~~~~~~ /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x86_32.x86/include/c++/v1/experimental/__simd/vec_ext.h:45:45: note: in instantiation of function template specialization 'std::experimental::__choose_mask_type<long double>' requested here 45 | : __simd_storage<decltype(experimental::__choose_mask_type<_Tp>()), simd_abi::__vec_ext<_Np>> {}; | ^ /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x86_32.x86/include/c++/v1/experimental/__simd/simd_mask.h:31:12: note: in instantiation of template class 'std::experimental::__mask_storage<long double, std::experimental::simd_abi::__vec_ext<1>>' requested here 31 | _Storage __s_; | ^ /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/std/experimental/simd/simd.mask.class/simd_mask_alias.pass.cpp:28:47: note: in instantiation of template class 'std::experimental::simd_mask<long double, std::experimental::simd_abi::__vec_ext<1>>' requested here 28 | static_assert(std::is_same_v<typename ex::simd_mask<T, SimdAbi>::value_type, bool>); | ^ /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/support/type_algorithms.h:52:23: note: in instantiation of function template specialization 'CheckSimdMaskAlias<long double, 1>::operator()<std::experimental::simd_abi::__vec_ext<1>>' requested here 52 | swallow((f.template operator()<Types>(), 0)...); | ^ /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/support/type_algorithms.h:52:23: note: in instantiation of function template specialization 'TestAllSimdAbiFunctor<CheckSimdMaskAlias>::operator()<long double>' requested here /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/libcxx/test/std/experimental/simd/simd.mask.class/simd_mask_alias.pass.cpp:35:3: note: in instantiation of function template specialization 'test_all_simd_abi<CheckSimdMaskAlias>' requested here 35 | test_all_simd_abi<CheckSimdMaskAlias>(); | ^ /var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x86_32.x86/include/c++/v1/experimental/__simd/utility.h:53:31: note: expression evaluates to '12 == 0' 53 | static_assert(sizeof(_Tp) == 0, "Unexpected size"); | ~~~~~~~~~~~~^~~~
Full log (.xz, 2.8M uncompressed):
Thank you very much for your reminder. I tried to fix this issue in revision https://reviews.llvm.org/D159509 and land this patch after CI passed.
I'm getting the same errors after this change (tested on 2f005df066e07d93e3d6aa04748c158f883197b7).
Note the specific errors are:
/var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x86_32.x86/include/c++/v1/experimental/__simd/vec_ext.h:31:29: error: vector size not an integral multiple of component size 31 | _Tp __data __attribute__((__vector_size__(std::__bit_ceil((sizeof(_Tp) * _Np))))); | ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
and:
/var/tmp/portage/sys-libs/libcxx-18.0.0_pre20230912/work/runtimes_build-abi_x86_32.x86/include/c++/v1/experimental/__simd/utility.h:53:19: error: static assertion failed due to requirement 'sizeof(long double) == 0': Unexpected size 53 | static_assert(sizeof(_Tp) == 0, "Unexpected size"); | ^~~~~~~~~~~~~~~~
Sorry. Because this issue did not appear in the CI of above revision, I presumed that it is related to another issue that appeared in the CI. But it does not seem like this. I am trying to reproduce and resolve it by https://reviews.llvm.org/D159514. This time, I will ensure that the modifications can pass the test on 2f005df066e07d93e3d6aa04748c158f883197b7
These aliases need tests too. Just check for a few instantiations that they exist and have the expected types.