https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127510

--- Comment #6 from Raghesh Aloor <raghesh.aloor at amd dot com> ---
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.

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.

Reply via email to