This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/80265] __builtin_{memcmp,memchr,strlen} are not usable in constexpr functions
- From: "redi at gcc dot gnu.org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Fri, 23 Mar 2018 13:23:19 +0000
- Subject: [Bug c++/80265] __builtin_{memcmp,memchr,strlen} are not usable in constexpr functions
- Auto-submitted: auto-generated
- References: <bug-80265-4@http.gcc.gnu.org/bugzilla/>
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).