https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127510
--- Comment #7 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Raghesh Aloor from comment #6)
> Thanks Richard. From your comments, here is our understanding; please
> correct us
> if we are wrong.
>
> To your question in comment on libstdc++, the multi-pointer == comes
> from the user's iterator (Zip<3> in the testcase), but the "loop until
> last" comes from the random-access branch of std::for_each_n in
> libstdc++-v3/include/bits/stl_algo.h:
>
> template<typename _InputIterator, typename _Size, typename _Function>
> _GLIBCXX20_CONSTEXPR
> _InputIterator
> for_each_n(_InputIterator __first, _Size __n, _Function __f)
> {
> auto __n2 = std::__size_to_integer(__n);
> using _Cat =
> decltype(std::__iter_concept_or_category<_InputIterator>());
> if constexpr (is_base_of_v<random_access_iterator_tag, _Cat>)
> {
> if (__n2 <= 0)
> return __first;
> typename iterator_traits<_InputIterator>::difference_type __d = __n2;
> auto __last = __first + __d;
> std::for_each(__first, __last, std::move(__f));
> return __last;
> }
> else
> {
> while (__n2-->0)
> {
> __f(*__first);
> ++__first;
> }
> return __first;
> }
>
> Are you suggesting a libstdc++ fix that makes the random-access branch a
> decremented counted loop, as in the non-random-access case? Something like:
>
> if constexpr (is_base_of_v<random_access_iterator_tag, _Cat>)
> {
> if (__n2 <= 0)
> return __first;
> typename iterator_traits<_InputIterator>::difference_type __d = __n2;
> for (; __d > 0; --__d, ++__first)
> __f(*__first);
> return __first;
> }
>
> We are not sure the libstdc++ maintainers would accept this, though, as
> forwarding to std::for_each may be intentional.
No idea - which is why I asked to investigate if libstdc++ does something
stupid here.
> For the compiler side tasks, we understand the following.
>
> As a first step, we need to get the same output as with -fno-vect-cost-model,
> by teaching niter analysis to handle the &-combined EQ/NE exit condition.
>
> As a follow-up optimization, we would then do what you suggested in your
> final
> comment: rewrite the IVs with the same step in terms of a single IV bound by
> _14
> (with versioning where termination cannot be proven), so the redundant
> compares
> and extra IVs go away.
Note that when niter analysis handles the exit condition this should
effectively do the 2nd part automatically. If we do the followup the
niter part wouldn't be needed.