public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/101485] New: Calling std::equal with std::byte* does not use memcmp
@ 2021-07-17 11:56 dennis-hezel at gmx dot de
  2021-07-18 21:14 ` [Bug libstdc++/101485] " redi at gcc dot gnu.org
                   ` (15 more replies)
  0 siblings, 16 replies; 17+ messages in thread
From: dennis-hezel at gmx dot de @ 2021-07-17 11:56 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 101485
           Summary: Calling std::equal with std::byte* does not use memcmp
           Product: gcc
           Version: 12.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: dennis-hezel at gmx dot de
  Target Milestone: ---

See https://godbolt.org/z/fKbhqe1sz

```
#include <algorithm>

auto equal_with_bytes(std::byte* b1, std::byte* e1, std::byte* b2) {
  return std::equal(b1, e1, b2);
}

auto equal_with_chars(unsigned char* b1, unsigned char* e1, unsigned char* b2)
{
  return std::equal(b1, e1, b2);
}
```

In the above code `equal_with_chars` invokes `memcmp` while `equal_with_bytes`
does not, although it would be eligble.

The problematic code seems to be in `stl_algobase.h`

```
  template<typename _II1, typename _II2>
    _GLIBCXX20_CONSTEXPR
    inline bool
    __equal_aux1(_II1 __first1, _II1 __last1, _II2 __first2)
    {
      typedef typename iterator_traits<_II1>::value_type _ValueType1;
      const bool __simple = ((__is_integer<_ValueType1>::__value
                              || __is_pointer<_ValueType1>::__value)
                             && __memcmpable<_II1, _II2>::__value);
      return std::__equal<__simple>::equal(__first1, __last1, __first2);
    } 
```

since `std::byte` is neither an integer nor a pointer.

Suggested fix: Extend the condition with a check for `std::byte`

```
__is_integer<_ValueType1>::__value || __is_pointer<_ValueType1>::__value ||
__is_byte<_ValueType1>::__value
```

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug libstdc++/101485] Calling std::equal with std::byte* does not use memcmp
  2021-07-17 11:56 [Bug c++/101485] New: Calling std::equal with std::byte* does not use memcmp dennis-hezel at gmx dot de
@ 2021-07-18 21:14 ` redi at gcc dot gnu.org
  2024-06-28 10:01 ` redi at gcc dot gnu.org
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: redi at gcc dot gnu.org @ 2021-07-18 21:14 UTC (permalink / raw)
  To: gcc-bugs

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

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |missed-optimization
           See Also|                            |https://gcc.gnu.org/bugzill
                   |                            |a/show_bug.cgi?id=93059
     Ever confirmed|0                           |1
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2021-07-18

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug libstdc++/101485] Calling std::equal with std::byte* does not use memcmp
  2021-07-17 11:56 [Bug c++/101485] New: Calling std::equal with std::byte* does not use memcmp dennis-hezel at gmx dot de
  2021-07-18 21:14 ` [Bug libstdc++/101485] " redi at gcc dot gnu.org
@ 2024-06-28 10:01 ` redi at gcc dot gnu.org
  2024-06-28 10:18 ` redi at gcc dot gnu.org
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: redi at gcc dot gnu.org @ 2024-06-28 10:01 UTC (permalink / raw)
  To: gcc-bugs

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

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |ASSIGNED
           Assignee|unassigned at gcc dot gnu.org      |redi at gcc dot gnu.org

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug libstdc++/101485] Calling std::equal with std::byte* does not use memcmp
  2021-07-17 11:56 [Bug c++/101485] New: Calling std::equal with std::byte* does not use memcmp dennis-hezel at gmx dot de
  2021-07-18 21:14 ` [Bug libstdc++/101485] " redi at gcc dot gnu.org
  2024-06-28 10:01 ` redi at gcc dot gnu.org
@ 2024-06-28 10:18 ` redi at gcc dot gnu.org
  2024-06-28 10:29 ` janschultke at googlemail dot com
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: redi at gcc dot gnu.org @ 2024-06-28 10:18 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
We can use is_same_v<_ValueType1, byte> instead, which is more efficient to
compile than instantiating __is_byte unconditionally.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug libstdc++/101485] Calling std::equal with std::byte* does not use memcmp
  2021-07-17 11:56 [Bug c++/101485] New: Calling std::equal with std::byte* does not use memcmp dennis-hezel at gmx dot de
                   ` (2 preceding siblings ...)
  2024-06-28 10:18 ` redi at gcc dot gnu.org
@ 2024-06-28 10:29 ` janschultke at googlemail dot com
  2024-06-28 10:32 ` redi at gcc dot gnu.org
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: janschultke at googlemail dot com @ 2024-06-28 10:29 UTC (permalink / raw)
  To: gcc-bugs

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

Jan Schultke <janschultke at googlemail dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |janschultke at googlemail dot com

--- Comment #2 from Jan Schultke <janschultke at googlemail dot com> ---
Would it be wrong to extend the definition to all enumeration types instead of
just std::byte? I don't see what could be wrong about memcmping enumerations,
given that this is correct for integers, and enumerations always have integer
underlying types.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug libstdc++/101485] Calling std::equal with std::byte* does not use memcmp
  2021-07-17 11:56 [Bug c++/101485] New: Calling std::equal with std::byte* does not use memcmp dennis-hezel at gmx dot de
                   ` (3 preceding siblings ...)
  2024-06-28 10:29 ` janschultke at googlemail dot com
@ 2024-06-28 10:32 ` redi at gcc dot gnu.org
  2024-06-28 10:41 ` redi at gcc dot gnu.org
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: redi at gcc dot gnu.org @ 2024-06-28 10:32 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #3 from Jonathan Wakely <redi at gcc dot gnu.org> ---
#include <algorithm>

enum E { e };
bool operator==(E, E) { return false; }

int main()
{
  E e[1];
  return std::equal(e, e+1, e);
}

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug libstdc++/101485] Calling std::equal with std::byte* does not use memcmp
  2021-07-17 11:56 [Bug c++/101485] New: Calling std::equal with std::byte* does not use memcmp dennis-hezel at gmx dot de
                   ` (4 preceding siblings ...)
  2024-06-28 10:32 ` redi at gcc dot gnu.org
@ 2024-06-28 10:41 ` redi at gcc dot gnu.org
  2024-06-28 10:53 ` janschultke at googlemail dot com
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: redi at gcc dot gnu.org @ 2024-06-28 10:41 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> ---
It's valid for std::byte because we know what equality means for std::byte.

You could maaaaaaybe do something like:

template<typename T>
concept is_sane_enum = is_enum_v<T> && (!requires { &operator==(E,E); });

but I'm not confident enough that it wouldn't miss some cases and allow
std::equal to do use memcmp when it shouldn't.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug libstdc++/101485] Calling std::equal with std::byte* does not use memcmp
  2021-07-17 11:56 [Bug c++/101485] New: Calling std::equal with std::byte* does not use memcmp dennis-hezel at gmx dot de
                   ` (5 preceding siblings ...)
  2024-06-28 10:41 ` redi at gcc dot gnu.org
@ 2024-06-28 10:53 ` janschultke at googlemail dot com
  2024-06-28 11:19 ` redi at gcc dot gnu.org
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: janschultke at googlemail dot com @ 2024-06-28 10:53 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #5 from Jan Schultke <janschultke at googlemail dot com> ---
&operator==(E,E); is not a valid expression, but I understand what you're
trying to do there. Perhaps you can test by converting to a function pointer
bool(*)(E,E).

It would surely miss cases like an operator== with an always-defaulted third
parameter, or one where the return type is contextually convertible to bool,
but not exactly bool, or:

template <std::same_as<E> T>
bool operator==(T, T) { return false; }

... or other cases. You would really need some way to detect whether an
expression (x == y) uses any overloaded operators, and I don't see how you
could do that (without additional intrinsics).

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug libstdc++/101485] Calling std::equal with std::byte* does not use memcmp
  2021-07-17 11:56 [Bug c++/101485] New: Calling std::equal with std::byte* does not use memcmp dennis-hezel at gmx dot de
                   ` (6 preceding siblings ...)
  2024-06-28 10:53 ` janschultke at googlemail dot com
@ 2024-06-28 11:19 ` redi at gcc dot gnu.org
  2024-06-28 11:25 ` redi at gcc dot gnu.org
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: redi at gcc dot gnu.org @ 2024-06-28 11:19 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #6 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Jan Schultke from comment #5)
> It would surely miss cases like an operator== with an always-defaulted third
> parameter,

That's not valid, operator== must have two parameters.

> or one where the return type is contextually convertible to bool,

Yes, int operator==(E, E) is valid.

> but not exactly bool, or:
> 
> template <std::same_as<E> T>
> bool operator==(T, T) { return false; }

That is valid to declare, but doesn't get called. I think the built-in
candidate is a better match.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug libstdc++/101485] Calling std::equal with std::byte* does not use memcmp
  2021-07-17 11:56 [Bug c++/101485] New: Calling std::equal with std::byte* does not use memcmp dennis-hezel at gmx dot de
                   ` (7 preceding siblings ...)
  2024-06-28 11:19 ` redi at gcc dot gnu.org
@ 2024-06-28 11:25 ` redi at gcc dot gnu.org
  2024-06-28 11:32 ` janschultke at googlemail dot com
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: redi at gcc dot gnu.org @ 2024-06-28 11:25 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #7 from Jonathan Wakely <redi at gcc dot gnu.org> ---
A better version of the concept sketched above:

template<typename T>
concept is_sane_enum = std::is_enum_v<T> && (!requires {
  []<std::convertible_to<bool> U>(U (*)(T, T)){}(&operator==);
});

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug libstdc++/101485] Calling std::equal with std::byte* does not use memcmp
  2021-07-17 11:56 [Bug c++/101485] New: Calling std::equal with std::byte* does not use memcmp dennis-hezel at gmx dot de
                   ` (8 preceding siblings ...)
  2024-06-28 11:25 ` redi at gcc dot gnu.org
@ 2024-06-28 11:32 ` janschultke at googlemail dot com
  2024-06-28 11:34 ` redi at gcc dot gnu.org
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: janschultke at googlemail dot com @ 2024-06-28 11:32 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #8 from Jan Schultke <janschultke at googlemail dot com> ---
It is a tiny bit pessimistic if it uses std::convertible_to instead of
std::__boolean_testable or what it was called.

I cannot come up with an example that produces a false positive though (which
is crucial for correctness), and if we cover 99% of enums, that's still much
better than just std::byte. Nice job.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug libstdc++/101485] Calling std::equal with std::byte* does not use memcmp
  2021-07-17 11:56 [Bug c++/101485] New: Calling std::equal with std::byte* does not use memcmp dennis-hezel at gmx dot de
                   ` (9 preceding siblings ...)
  2024-06-28 11:32 ` janschultke at googlemail dot com
@ 2024-06-28 11:34 ` redi at gcc dot gnu.org
  2024-06-28 19:23 ` cvs-commit at gcc dot gnu.org
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: redi at gcc dot gnu.org @ 2024-06-28 11:34 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #9 from Jonathan Wakely <redi at gcc dot gnu.org> ---
I'm still not willing to use that though.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug libstdc++/101485] Calling std::equal with std::byte* does not use memcmp
  2021-07-17 11:56 [Bug c++/101485] New: Calling std::equal with std::byte* does not use memcmp dennis-hezel at gmx dot de
                   ` (10 preceding siblings ...)
  2024-06-28 11:34 ` redi at gcc dot gnu.org
@ 2024-06-28 19:23 ` cvs-commit at gcc dot gnu.org
  2024-06-28 19:29 ` redi at gcc dot gnu.org
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2024-06-28 19:23 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #10 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>:

https://gcc.gnu.org/g:fab60eaa94b50b1eea84f0d001004c851d4c781b

commit r15-1715-gfab60eaa94b50b1eea84f0d001004c851d4c781b
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Fri Jun 28 11:14:39 2024 +0100

    libstdc++: Extend std::equal memcmp optimization to std::byte [PR101485]

    We optimize std::equal to memcmp for integers and pointers, which means
    that std::byte comparisons generate bigger code than char comparisons.

    We can't use memcmp for arbitrary enum types, because they could have an
    overloaded operator== that has custom semantics, but we know that
    std::byte doesn't do that.

    libstdc++-v3/ChangeLog:

            PR libstdc++/101485
            * include/bits/stl_algobase.h (__equal_aux1): Check for
            std::byte as well.
            * testsuite/25_algorithms/equal/101485.cc: New test.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug libstdc++/101485] Calling std::equal with std::byte* does not use memcmp
  2021-07-17 11:56 [Bug c++/101485] New: Calling std::equal with std::byte* does not use memcmp dennis-hezel at gmx dot de
                   ` (11 preceding siblings ...)
  2024-06-28 19:23 ` cvs-commit at gcc dot gnu.org
@ 2024-06-28 19:29 ` redi at gcc dot gnu.org
  2024-06-28 20:43 ` janschultke at googlemail dot com
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: redi at gcc dot gnu.org @ 2024-06-28 19:29 UTC (permalink / raw)
  To: gcc-bugs

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

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|ASSIGNED                    |RESOLVED
   Target Milestone|---                         |15.0
         Resolution|---                         |FIXED

--- Comment #11 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Fixed on trunk, thanks for the report.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug libstdc++/101485] Calling std::equal with std::byte* does not use memcmp
  2021-07-17 11:56 [Bug c++/101485] New: Calling std::equal with std::byte* does not use memcmp dennis-hezel at gmx dot de
                   ` (12 preceding siblings ...)
  2024-06-28 19:29 ` redi at gcc dot gnu.org
@ 2024-06-28 20:43 ` janschultke at googlemail dot com
  2024-06-29  7:39 ` redi at gcc dot gnu.org
  2024-06-29  9:20 ` redi at gcc dot gnu.org
  15 siblings, 0 replies; 17+ messages in thread
From: janschultke at googlemail dot com @ 2024-06-28 20:43 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #12 from Jan Schultke <janschultke at googlemail dot com> ---
On a language evolution note, https://wg21.link/P2825 would let you detect
whether an equality comparison for enumerations is overloaded by checking
whether

> declcall(E{} == E{})

... is well-formed. If this makes it into C++26, the solution could be
broadened to all enumerations robustly.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug libstdc++/101485] Calling std::equal with std::byte* does not use memcmp
  2021-07-17 11:56 [Bug c++/101485] New: Calling std::equal with std::byte* does not use memcmp dennis-hezel at gmx dot de
                   ` (13 preceding siblings ...)
  2024-06-28 20:43 ` janschultke at googlemail dot com
@ 2024-06-29  7:39 ` redi at gcc dot gnu.org
  2024-06-29  9:20 ` redi at gcc dot gnu.org
  15 siblings, 0 replies; 17+ messages in thread
From: redi at gcc dot gnu.org @ 2024-06-29  7:39 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #13 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Yes I've read it but it's not clear to me that it's SFINAE-friendly when the
expression resolves to a built-in like that.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug libstdc++/101485] Calling std::equal with std::byte* does not use memcmp
  2021-07-17 11:56 [Bug c++/101485] New: Calling std::equal with std::byte* does not use memcmp dennis-hezel at gmx dot de
                   ` (14 preceding siblings ...)
  2024-06-29  7:39 ` redi at gcc dot gnu.org
@ 2024-06-29  9:20 ` redi at gcc dot gnu.org
  15 siblings, 0 replies; 17+ messages in thread
From: redi at gcc dot gnu.org @ 2024-06-29  9:20 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #14 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Gašper has confirmed that the intention is for it to be SFINAE-friendly, so
declcall would work here (and for [comparisons.general],
[comparisons.three.way], and [range.cmp], although P2434 might make it
unnecessary for those).

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2024-06-29  9:20 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-17 11:56 [Bug c++/101485] New: Calling std::equal with std::byte* does not use memcmp dennis-hezel at gmx dot de
2021-07-18 21:14 ` [Bug libstdc++/101485] " redi at gcc dot gnu.org
2024-06-28 10:01 ` redi at gcc dot gnu.org
2024-06-28 10:18 ` redi at gcc dot gnu.org
2024-06-28 10:29 ` janschultke at googlemail dot com
2024-06-28 10:32 ` redi at gcc dot gnu.org
2024-06-28 10:41 ` redi at gcc dot gnu.org
2024-06-28 10:53 ` janschultke at googlemail dot com
2024-06-28 11:19 ` redi at gcc dot gnu.org
2024-06-28 11:25 ` redi at gcc dot gnu.org
2024-06-28 11:32 ` janschultke at googlemail dot com
2024-06-28 11:34 ` redi at gcc dot gnu.org
2024-06-28 19:23 ` cvs-commit at gcc dot gnu.org
2024-06-28 19:29 ` redi at gcc dot gnu.org
2024-06-28 20:43 ` janschultke at googlemail dot com
2024-06-29  7:39 ` redi at gcc dot gnu.org
2024-06-29  9:20 ` redi at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).