[libcxx-commits] [PATCH] D148067: [libcxx] Add mdspan/extents
Louis Dionne via Phabricator via libcxx-commits
libcxx-commits at lists.llvm.org
Mon May 15 09:35:04 PDT 2023
ldionne accepted this revision.
ldionne added a comment.
This revision is now accepted and ready to land.
LGTM w/ comments and CI. If some comments can't be applied, please LMK.
Thanks a lot for the contribution and for all the time you devoted during our live reviews!
================
Comment at: libcxx/include/__mdspan/extents.h:145
+ _LIBCPP_HIDE_FROM_ABI static constexpr _DynamicValues __zeros(std::index_sequence<Indices...>) noexcept {
+ return _DynamicValues{__zero(Indices)...};
+ }
----------------
crtrott wrote:
> crtrott wrote:
> > ldionne wrote:
> > > Then you can get rid of `__zero` above.
> > Turns out this warns:
> >
> > ```
> > llvm-project/build3/include/c++/v1/__mdspan/extents.h:143:28: error: left operand of comma operator has no effect [-Werror,-Wunused-value]
> > return _DynamicValues{(Indices, 0)...};
> > ```
> >
> n
```
return _DynamicValues{((void)Indices, 0)...};
```
This gets rid of the warning, it's a common trick.
================
Comment at: libcxx/include/__mdspan/extents.h:109
+struct __static_partial_sums {
+ static constexpr __possibly_empty_array<size_t, sizeof...(_Values)> __result{
+ __static_partial_sums_impl<_Values...>()};
----------------
Optional: If you want you could maybe use an immediately invoked lambda here to avoid giving a name to `__static_partial_sums_impl`, which is obviously just a one-shot helper for now:
```
static constexpr std::array<size_t, sizeof...(_Values)> __result = []{
// implementation here
}();
```
================
Comment at: libcxx/include/__mdspan/extents.h:175-190
+template <size_t _Idx, size_t _FirstVal>
+struct __index_sequence_scan_impl<_Idx, _FirstVal> {
+# if defined(__NVCC__) || defined(__NVCOMPILER)
+ // NVCC warns about pointless comparison with 0 for _Idx==0 and r being const
+ // evaluatable and also 0.
+ _LIBCPP_HIDE_FROM_ABI constexpr static size_t get(size_t __r) {
+ return static_cast<int64_t>(_Idx) > static_cast<int64_t>(__r) ? _FirstVal : 0;
----------------
crtrott wrote:
> ldionne wrote:
> > crtrott wrote:
> > > ldionne wrote:
> > > > I think we can simplify this one as well for a bit more compile-time win (https://godbolt.org/z/qjn471871):
> > > >
> > > > ```
> > > > template <std::size_t ..._Values>
> > > > _LIBCPP_HIDE_FROM_ABI constexpr array<size_t, sizeof...(_Values)> __partial_sums_impl() {
> > > > array<size_t, sizeof...(_Values)> __values = {_Values...};
> > > > array<size_t, sizeof...(_Values)> __partial_sums;
> > > > size_t __running_sum = 0;
> > > > for (int __i = 0; __i != __values.size(); ++__i) {
> > > > __partial_sums[__i] = __running_sum;
> > > > __running_sum += __values[__i];
> > > > }
> > > > return __partial_sums;
> > > > }
> > > >
> > > > template <size_t ..._Values>
> > > > struct __partial_sums {
> > > > static constexpr array<size_t, sizeof...(_Values)> __result = __partial_sums_impl<_Values...>();
> > > >
> > > > _LIBCPP_HIDE_FROM_ABI constexpr static size_t __get(size_t __index) {
> > > > return __result[__index];
> > > > }
> > > > };
> > > > ```
> > > >
> > > Turns out I run into issues for rank-0 extents. However, using __possibly_empty_array instead of std::array here makes it work. https://godbolt.org/z/1Tona7Mzz
> > I just investigated this a bit more. Here's the difference: https://godbolt.org/z/8zsMfzEd9.
> >
> > The problem is that you had
> >
> > ```
> > std::array<std::size_t, sizeof...(_Values)> __partial_sums;
> > ```
> >
> > Instead, if you switch to
> >
> > ```
> > std::array<std::size_t, sizeof...(_Values)> __partial_sums{};
> > ```
> >
> > then your array is value-initialized and it works.
> Ah, makes sense. That said, do you feel we should move back to array instead of possibly_empty_array? I am inclined to leave it as is. If nothing else __possibly_empty_array is a bit simpler than std::array, and thus at the margin it may ease compile time a bit. Thoughts?
I think I would go for `std::array` cause it's more idiomatic and you don't need the properties of `maybe_empty_array` here. Otherwise it seems like we require the `maybe_empty_array` when we don't, which is a bit confusing.
================
Comment at: libcxx/test/std/containers/views/mdspan/extents/ConvertibleToIntegral.h:22
+
+#endif
----------------
Nit for consistency: `// TEST_STD_CONTAINERS_CONVERTIBLE_TO_INTEGRAL_H`
================
Comment at: libcxx/test/std/containers/views/mdspan/extents/comparison.pass.cpp:10-32
+// <mdspan>
+
+// template<class OtherIndexType, size_t... OtherExtents>
+// friend constexpr bool operator==(const extents&,
+// const extents<OtherIndexType, OtherExtents...>&) noexcept;
+// `
+
----------------
There seems to be a copy-paste issue here.
================
Comment at: libcxx/test/std/containers/views/mdspan/extents/comparison.pass.cpp:38
+ assert((dest == src) == equal);
+ assert((dest != src) != equal);
+}
----------------
Equivalent, but semantically you want to check what the result of `!=` *is*, not what it *isn't*.
================
Comment at: libcxx/test/std/containers/views/mdspan/extents/ctor_default.pass.cpp:30-31
+ static constexpr void test_construction(AllExtents all_ext, Extents, std::index_sequence<Indices...>) {
+ // this function gets called twice: once with Extents being just dynamic ones, and once with all
+ // we only test during the all extent case, since then Indices is correct number
+ if constexpr (sizeof...(Indices) == E::rank()) {
----------------
================
Comment at: libcxx/test/std/containers/views/mdspan/extents/ctor_from_array.pass.cpp:79
+ // check that implicit construction doesn't work
+ LIBCPP_ASSERT((implicit_construction<std::extents<int, D, D, 5, D, D>>(a5).value == false));
+
----------------
I think you mean just a regular `assert` here, since this is not a libc++ extension.
================
Comment at: libcxx/test/std/containers/views/mdspan/extents/ctor_from_span.pass.cpp:60
+
+int main() {
+ test_index_type_combo<SpanCtorTest>();
----------------
Here's a really annoying one that we don't seem to have clang-tidy checks for. Please make sure you declare main as `int main(int, char**)` and make sure you `return 0;` at the end. This is needed for running tests in Freestanding, where `main()` is not a special function (so no implicit return and no implicit `extern "C"` mangling).
Please check throughout all your tests.
================
Comment at: libcxx/test/std/containers/views/mdspan/extents/ctor_from_span.pass.cpp:81
+ // check that implicit construction doesn't work
+ LIBCPP_ASSERT((implicit_construction<std::extents<int, D, D, 5, D, D>>(s5).value == false));
+
----------------
Same here, probably `assert`.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D148067/new/
https://reviews.llvm.org/D148067
More information about the libcxx-commits
mailing list