public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/94082] __builtin_memcpy in constexpr context should compile
       [not found] <bug-94082-4@http.gcc.gnu.org/bugzilla/>
@ 2020-03-07 19:37 ` fche at redhat dot com
  2020-03-08 13:25 ` D.Bahadir at GMX dot de
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 8+ messages in thread
From: fche at redhat dot com @ 2020-03-07 19:37 UTC (permalink / raw)
  To: gcc-bugs

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

Frank Ch. Eigler <fche at redhat dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |fche at redhat dot com

test

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

* [Bug c++/94082] __builtin_memcpy in constexpr context should compile
       [not found] <bug-94082-4@http.gcc.gnu.org/bugzilla/>
  2020-03-07 19:37 ` [Bug c++/94082] __builtin_memcpy in constexpr context should compile fche at redhat dot com
@ 2020-03-08 13:25 ` D.Bahadir at GMX dot de
  2020-03-08 13:27 ` D.Bahadir at GMX dot de
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 8+ messages in thread
From: D.Bahadir at GMX dot de @ 2020-03-08 13:25 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #1 from Deniz Bahadir <D.Bahadir at GMX dot de> ---
Not: As due to the sourceware/gcc move it seems my original bug-report comment
got lost, I am here re-posting it.


Reading P0202 (wg21.link/p0202) (which made it into C++20) it sounds as if
`__builtin_memcpy` should be usable from a `constexpr` context. However, it is
not, as the following code demonstrates:

```
#include <array>
#include <cstdint>

constexpr std::uint32_t extract(const std::uint8_t* data) noexcept
{
    std::uint32_t num;
    __builtin_memcpy(&num, data, sizeof(std::uint32_t));
    return num;
}

int main()
{
    constexpr std::array<std::uint8_t, 4> a1 {{ 0xff, 0xff, 0xff, 0xff }};
    constexpr auto val = extract(a1.data());  // <--- Error!
    return val;
}
```

Compilation fails with:

```
<source>: In function 'int main()':
<source>:14:33:   in 'constexpr' expansion of 'extract(a1.std::array<unsigned
char, 4>::data())'
<source>:7:21: error: '__builtin_memcpy(((void*)(& num)), ((const void*)(&
a1.std::array<unsigned char, 4>::_M_elems)), 4)' is not a constant expression

    7 |     __builtin_memcpy(&num, data, sizeof(std::uint32_t));
      |     ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```

I would have expected this to compile and `__builtin_memcpy` being optimized
away.

Interestingly, removing the `constexpr` in front of the call to the function
and thereby not calling it from a `constexpr` context compiles just fine and
the optimizer is even able to optimize the call away and replace it by the
returned value (`-1`).

The `constexpr` keyword in front of the function definition seems then to just
be an indicator for inlining, similar to the `inline` keyword. But for this
simple example, the compiler is even able to optimize it without `inline` or
`constexpr` in front of the function definition.


I think a `constexpr` context should not prevent compilation and optimization,
as the optimizer seems to be able to do that.

BTW: Using e.g. `__builtin_bswap32` from a `constexpr` context is compiling and
optimizing just fine.

See Compiler Explorer for a demonstration of the described behavior:
https://godbolt.org/z/HaBt__

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

* [Bug c++/94082] __builtin_memcpy in constexpr context should compile
       [not found] <bug-94082-4@http.gcc.gnu.org/bugzilla/>
  2020-03-07 19:37 ` [Bug c++/94082] __builtin_memcpy in constexpr context should compile fche at redhat dot com
  2020-03-08 13:25 ` D.Bahadir at GMX dot de
@ 2020-03-08 13:27 ` D.Bahadir at GMX dot de
  2020-03-09  9:45 ` redi at gcc dot gnu.org
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 8+ messages in thread
From: D.Bahadir at GMX dot de @ 2020-03-08 13:27 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #2 from Deniz Bahadir <D.Bahadir at GMX dot de> ---
Here is a link to Stack Overflow where I originally asked a question about this
behavior: https://stackoverflow.com/q/60572199/3115457

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

* [Bug c++/94082] __builtin_memcpy in constexpr context should compile
       [not found] <bug-94082-4@http.gcc.gnu.org/bugzilla/>
                   ` (2 preceding siblings ...)
  2020-03-08 13:27 ` D.Bahadir at GMX dot de
@ 2020-03-09  9:45 ` redi at gcc dot gnu.org
  2020-03-09 11:04 ` D.Bahadir at GMX dot de
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 8+ messages in thread
From: redi at gcc dot gnu.org @ 2020-03-09  9:45 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #3 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Deniz Bahadir from comment #1)
> Reading P0202 (wg21.link/p0202) (which made it into C++20) it sounds as if
> `__builtin_memcpy` should be usable from a `constexpr` context.

Why? std::memcpy isn't usable in constant expressions.

It might be useful if it could be used, but the fact it can't currently isn't a
bug.

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

* [Bug c++/94082] __builtin_memcpy in constexpr context should compile
       [not found] <bug-94082-4@http.gcc.gnu.org/bugzilla/>
                   ` (3 preceding siblings ...)
  2020-03-09  9:45 ` redi at gcc dot gnu.org
@ 2020-03-09 11:04 ` D.Bahadir at GMX dot de
  2020-03-09 11:28 ` redi at gcc dot gnu.org
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 8+ messages in thread
From: D.Bahadir at GMX dot de @ 2020-03-09 11:04 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #4 from Deniz Bahadir <D.Bahadir at GMX dot de> ---
(In reply to Jonathan Wakely from comment #3)
> (In reply to Deniz Bahadir from comment #1)
> > Reading P0202 (wg21.link/p0202) (which made it into C++20) it sounds as if
> > `__builtin_memcpy` should be usable from a `constexpr` context.
> 
> Why? std::memcpy isn't usable in constant expressions.


Revision 0 of P0202 (https://wg21.link/p0202r0) originally had the following
text in section III.B:

    "B. std::memmove and std::memcpy must have constexpr additions

    std::memmove and std::memcpy accept void* and const void* parameters.
    This makes them impossible to implement in pure C++ as constexpr, because
    constant expressions can not evaluate a conversion from type cv void * to
    a pointer-to-object type according to [expr.const].

    However those functions are not only popular, but also are widely used
    across Standard Library to gain better performance. Not making them
    constexpr will force standard Library developer to have compiler
    intrinsics for them anyway. This is a hard step that must be done."

That was rejected at the committee meeting in Jacksonville in early 2018 and
the section was replaced by the following:

    "During the Jacksonville meeting it was decided not to modify the <cstring>
    headers, leading to a decision to use compiler specific intrinsics instead
    of functions from <cstring> header."

To me that sounds as if compiler-intrinsics like `__builtin_memcpy` should
instead be usable in `constexpr` contexts.


> It might be useful if it could be used, but the fact it can't currently
> isn't a bug.

OK, then consider this issue a feature-request and a question.

As the link to Compiler Explorer shows the compiler is already able to
calculate the result of the entire function call at compile-time when called
from a non-`constexpr` context.
Shouldn't it then be able to still do so in a `constexpr` context, too?
(As I mentioned, e.g. for `__builtin_bswap32` that is possible.)

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

* [Bug c++/94082] __builtin_memcpy in constexpr context should compile
       [not found] <bug-94082-4@http.gcc.gnu.org/bugzilla/>
                   ` (4 preceding siblings ...)
  2020-03-09 11:04 ` D.Bahadir at GMX dot de
@ 2020-03-09 11:28 ` redi at gcc dot gnu.org
  2020-03-09 12:04 ` D.Bahadir at GMX dot de
  2021-08-28 21:57 ` pinskia at gcc dot gnu.org
  7 siblings, 0 replies; 8+ messages in thread
From: redi at gcc dot gnu.org @ 2020-03-09 11:28 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #5 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Deniz Bahadir from comment #4)
> (In reply to Jonathan Wakely from comment #3)
> > (In reply to Deniz Bahadir from comment #1)
> > > Reading P0202 (wg21.link/p0202) (which made it into C++20) it sounds as if
> > > `__builtin_memcpy` should be usable from a `constexpr` context.
> > 
> > Why? std::memcpy isn't usable in constant expressions.
> 
> 
> Revision 0 of P0202 (https://wg21.link/p0202r0) originally had the following
> text in section III.B:
> 
>     "B. std::memmove and std::memcpy must have constexpr additions
>     
>     std::memmove and std::memcpy accept void* and const void* parameters.
>     This makes them impossible to implement in pure C++ as constexpr, because
>     constant expressions can not evaluate a conversion from type cv void * to
>     a pointer-to-object type according to [expr.const].
>     
>     However those functions are not only popular, but also are widely used
>     across Standard Library to gain better performance. Not making them
>     constexpr will force standard Library developer to have compiler
>     intrinsics for them anyway. This is a hard step that must be done."
> 
> That was rejected at the committee meeting in Jacksonville in early 2018 and
> the section was replaced by the following:
> 
>     "During the Jacksonville meeting it was decided not to modify the
> <cstring>
>     headers, leading to a decision to use compiler specific intrinsics
> instead
>     of functions from <cstring> header."
> 
> To me that sounds as if compiler-intrinsics like `__builtin_memcpy` should
> instead be usable in `constexpr` contexts.

It definitely doesn't mean __builtin_memcpy has to be used. It means "we don't
want to change std::memcpy, implementations must use some other method to make
it work". 

That could mean using some new intrinsic like __builtin_constant_memcpy, or
anything else that makes the algorithms work in constant expressions. The
solution in libstdc++ is based on std::is_constant_evaluted() and ensures that
memcpy and __builtin_memcpy are never needed in constant expressions because we
implement those copies by hand when needed during constant evaluation.


> > It might be useful if it could be used, but the fact it can't currently
> > isn't a bug.
> 
> OK, then consider this issue a feature-request and a question.
> 
> As the link to Compiler Explorer shows the compiler is already able to
> calculate the result of the entire function call at compile-time when called
> from a non-`constexpr` context.

For some cases. I don't think it's true for all inputs.

> Shouldn't it then be able to still do so in a `constexpr` context, too?
> (As I mentioned, e.g. for `__builtin_bswap32` that is possible.)

bswap32 is much simpler than mempcy and can always be expanded by the compiler,
for all inputs.

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

* [Bug c++/94082] __builtin_memcpy in constexpr context should compile
       [not found] <bug-94082-4@http.gcc.gnu.org/bugzilla/>
                   ` (5 preceding siblings ...)
  2020-03-09 11:28 ` redi at gcc dot gnu.org
@ 2020-03-09 12:04 ` D.Bahadir at GMX dot de
  2021-08-28 21:57 ` pinskia at gcc dot gnu.org
  7 siblings, 0 replies; 8+ messages in thread
From: D.Bahadir at GMX dot de @ 2020-03-09 12:04 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #6 from Deniz Bahadir <D.Bahadir at GMX dot de> ---
(In reply to Jonathan Wakely from comment #5)
> 
> It definitely doesn't mean __builtin_memcpy has to be used. It means "we
> don't want to change std::memcpy, implementations must use some other method
> to make it work". 
> 
> That could mean using some new intrinsic like __builtin_constant_memcpy, or
> anything else that makes the algorithms work in constant expressions. The
> solution in libstdc++ is based on std::is_constant_evaluted() and ensures
> that memcpy and __builtin_memcpy are never needed in constant expressions
> because we implement those copies by hand when needed during constant
> evaluation.

OK, I see.
Would you then suggest GCC should provide such an intrinsic or would you expect
developers to do copies by hand, too, in `constexpr` context.

> > > It might be useful if it could be used, but the fact it can't currently
> > > isn't a bug.
> > 
> > OK, then consider this issue a feature-request and a question.
> > 
> > As the link to Compiler Explorer shows the compiler is already able to
> > calculate the result of the entire function call at compile-time when called
> > from a non-`constexpr` context.
> 
> For some cases. I don't think it's true for all inputs.

Well, that is unfortunate.

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

* [Bug c++/94082] __builtin_memcpy in constexpr context should compile
       [not found] <bug-94082-4@http.gcc.gnu.org/bugzilla/>
                   ` (6 preceding siblings ...)
  2020-03-09 12:04 ` D.Bahadir at GMX dot de
@ 2021-08-28 21:57 ` pinskia at gcc dot gnu.org
  7 siblings, 0 replies; 8+ messages in thread
From: pinskia at gcc dot gnu.org @ 2021-08-28 21:57 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #7 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
clang produces:
<source>:8:5: note: cannot constant evaluate 'memcpy' from object of type
'unsigned char' to object of type 'std::uint32_t' (aka 'unsigned int')
    __builtin_memcpy(&num, data, sizeof(std::uint32_t));
    ^

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

end of thread, other threads:[~2021-08-28 21:57 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <bug-94082-4@http.gcc.gnu.org/bugzilla/>
2020-03-07 19:37 ` [Bug c++/94082] __builtin_memcpy in constexpr context should compile fche at redhat dot com
2020-03-08 13:25 ` D.Bahadir at GMX dot de
2020-03-08 13:27 ` D.Bahadir at GMX dot de
2020-03-09  9:45 ` redi at gcc dot gnu.org
2020-03-09 11:04 ` D.Bahadir at GMX dot de
2020-03-09 11:28 ` redi at gcc dot gnu.org
2020-03-09 12:04 ` D.Bahadir at GMX dot de
2021-08-28 21:57 ` pinskia 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).