[Bug libstdc++/95702] New: ranges::transform missing vectorization opportunity
pilarlatiesa at gmail dot com
gcc-bugzilla@gcc.gnu.org
Tue Jun 16 17:03:46 GMT 2020
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95702
Bug ID: 95702
Summary: ranges::transform missing vectorization opportunity
Product: gcc
Version: 10.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: pilarlatiesa at gmail dot com
Target Milestone: ---
GCC 10 is able to vectorize this code (https://godbolt.org/z/tsbfQw):
#include <algorithm>
#include <vector>
void foo(std::vector<double> &u, std::vector<double> const &v)
{
std::transform(std::begin(u), std::end(u),
std::begin(v),
std::begin(u),
std::plus());
}
However, it fails to vectorize the ranges equivalent
(https://godbolt.org/z/D49hJa):
#include <algorithm>
#include <vector>
void foo(std::vector<double> &u, std::vector<double> const &v)
{
std::ranges::transform(u, v, std::begin(u), std::plus());
}
The option -fopt-info-vec-missed reveals why:
bits/ranges_algo.h:986:29: missed: not vectorized: number of iterations cannot
be computed.
Would an optimization like the following one make sense?
template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
weakly_incrementable _Out, copy_constructible _Fp,
typename _Proj1 = identity, typename _Proj2 = identity>
requires indirectly_writable<_Out,
indirect_result_t<_Fp&,
projected<_Iter1, _Proj1>,
projected<_Iter2, _Proj2>>>
constexpr binary_transform_result<_Iter1, _Iter2, _Out>
operator()(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2,
_Out __result, _Fp __binary_op,
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
{
+ if constexpr (random_access_iterator<_Iter1>
+ && random_access_iterator<_Iter2>)
+ {
+ auto __d1 = ranges::distance(__first1, __last1);
+ auto __d2 = ranges::distance(__first2, __last2);
+ auto __n = std::min(__d1, __d2);
+ for (decltype(__n) __i = 0; __i < __n;
+ (void)++__i, (void)++__first1, (void)++__first2,
++__result)
+ }
+ else
for (; __first1 != __last1 && __first2 != __last2;
++__first1, (void)++__first2, ++__result)
*__result = std::__invoke(__binary_op,
std::__invoke(__proj1,
*__first1),
std::__invoke(__proj2,
*__first2));
return {std::move(__first1), std::move(__first2),
std::move(__result)};
}
More information about the Gcc-bugs
mailing list