https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80265
--- Comment #31 from Jonathan Wakely <redi at gcc dot gnu.org> --- (In reply to Pedro Alves from comment #28) > So back to the constexpr __builtin_memcmp, or __constexpr_memcmp ideas. > > Though I still don't see how __constexpr_memcmp would make a difference wrt > to number of __equal::equal implementations, but now I'm thinking that > that's not what you meant. It's not what I meant :-) What I mean is that when you call std::equal today, it either dispatches to a for-loop, or __builtin_memcmp. That's two. If we replaced __builtin_memcmp with __constexpr_memcmp which either uses a for-loop or memcmp, then we have three. The foor-loop in __equal<false>::equal, or a for-loop in __constexpr_memcmp, or a call to __builtin_memcmp. There are still only two versions of __equal<bool>::equal but we do have more code, and two for-loops that are effectively identical (one in __equal<false>::equal and one in __constexpr_memcmp). If the one in __constexpr_memcmp is guaranteed to always be optimized out that's great, but I don't know if it's guaranteed. Intuitively, adding more code doesn't seem like it's going to _help_ guarantee we optimize everything out :-) > From my view, __constexpr_memcmp implemented in > a helper constexpr function or directly in the frontend (as > __builtin_memcmp), is just an implementation detail of the function. > Ultimately, __constexpr_memcmp or constexpr __builtin_memcmp ends up > interpreted in a similar way internally, I expect. I would hope so, but I'd like to be certain, not hopeful. It would be nice if we could just add _GLIBCXX17_CONSTEXPR in a few places and then do: --- a/libstdc++-v3/include/bits/stl_algobase.h +++ b/libstdc++-v3/include/bits/stl_algobase.h @@ -807,11 +807,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __equal<true> { template<typename _Tp> - static bool + static _GLIBCXX14_CONSTEXPR bool equal(const _Tp* __first1, const _Tp* __last1, const _Tp* __first2) { if (const size_t __len = (__last1 - __first1)) + { + if (__builtin_constant_p( something something )) + return __equal<false>::equal(__first1, __last1, __first2); return !__builtin_memcmp(__first1, __first2, sizeof(_Tp) * __len); + } return true; } }; (For some value of "something something", as you did for char_traits). This is somewhere that https://wg21.link/p0595r0 would help again (and if the arguments aren't constants, we just get an error in __equal<false>::equal).