public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c/114923] New: gcc ignores escaping pointer and applies invalid optimization
@ 2024-05-02 12:51 nfxjfg at googlemail dot com
  2024-05-02 12:52 ` [Bug c/114923] " nfxjfg at googlemail dot com
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: nfxjfg at googlemail dot com @ 2024-05-02 12:51 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 114923
           Summary: gcc ignores escaping pointer and applies invalid
                    optimization
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: nfxjfg at googlemail dot com
  Target Milestone: ---

Created attachment 58088
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=58088&action=edit
Test case

In this test case, the pointer to a stack-allocated variable is passed to a
volatile variable. That means the pointer definitely escapes. But the compiler
seems to assume that the memory can't change, and returns the initialization
value of the buf variable.

I tried multiple variations of this. Sometimes it generates the correct code,
even though the situation is exactly the same. A call to an external function
often fixes it, but sometimes not (could not produce a reduced test case of the
latter).

This is reduced from some real-word code. The first register access passes the
memory pointer to the hardware, the second access starts the DMA. In the
real-world code there was some more stuff such as waiting for the DMA to
finish, but it doesn't matter for code generation. The code started to fail
after a DMA buffer was moved from a global variable to the stack.

Originally experienced on 12.2.0 / riscv32-unknown-elf, but on godlbolt I can
reproduce it with trunk and some other architectures.

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

* [Bug c/114923] gcc ignores escaping pointer and applies invalid optimization
  2024-05-02 12:51 [Bug c/114923] New: gcc ignores escaping pointer and applies invalid optimization nfxjfg at googlemail dot com
@ 2024-05-02 12:52 ` nfxjfg at googlemail dot com
  2024-05-02 13:24 ` amonakov at gcc dot gnu.org
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: nfxjfg at googlemail dot com @ 2024-05-02 12:52 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #1 from nfxjfg at googlemail dot com ---
To make this explicitly clear: I expect that gcc reads back the buf value from
memory and returns that.

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

* [Bug c/114923] gcc ignores escaping pointer and applies invalid optimization
  2024-05-02 12:51 [Bug c/114923] New: gcc ignores escaping pointer and applies invalid optimization nfxjfg at googlemail dot com
  2024-05-02 12:52 ` [Bug c/114923] " nfxjfg at googlemail dot com
@ 2024-05-02 13:24 ` amonakov at gcc dot gnu.org
  2024-05-02 13:44 ` nfxjfg at googlemail dot com
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: amonakov at gcc dot gnu.org @ 2024-05-02 13:24 UTC (permalink / raw)
  To: gcc-bugs

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

Alexander Monakov <amonakov at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |amonakov at gcc dot gnu.org

--- Comment #2 from Alexander Monakov <amonakov at gcc dot gnu.org> ---
'volatile' is not viral like that. If 'buf' can be accessed outside of the
abstract machine, it needs to be volatile itself. Alternatively, an empty asm
with a memory clobber, asm("":::"memory"), will imply a possible access to
'buf' via its escaped address.

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

* [Bug c/114923] gcc ignores escaping pointer and applies invalid optimization
  2024-05-02 12:51 [Bug c/114923] New: gcc ignores escaping pointer and applies invalid optimization nfxjfg at googlemail dot com
  2024-05-02 12:52 ` [Bug c/114923] " nfxjfg at googlemail dot com
  2024-05-02 13:24 ` amonakov at gcc dot gnu.org
@ 2024-05-02 13:44 ` nfxjfg at googlemail dot com
  2024-05-02 13:56 ` amonakov at gcc dot gnu.org
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: nfxjfg at googlemail dot com @ 2024-05-02 13:44 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #3 from nfxjfg at googlemail dot com ---
I'm expecting gcc to realize that the pointer escaped into the unknown, and
that it can't assume that the memory won't change. This is just causality, not
any vague made up viralyness.

Anyway, a 'asm volatile("":::"memory")' is too radical and increased code size
too much in my case (but it's a good suggestion). Making the buffer volatile
will inhibit optimizations before or after the DMA.

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

* [Bug c/114923] gcc ignores escaping pointer and applies invalid optimization
  2024-05-02 12:51 [Bug c/114923] New: gcc ignores escaping pointer and applies invalid optimization nfxjfg at googlemail dot com
                   ` (2 preceding siblings ...)
  2024-05-02 13:44 ` nfxjfg at googlemail dot com
@ 2024-05-02 13:56 ` amonakov at gcc dot gnu.org
  2024-05-02 19:07 ` [Bug middle-end/114923] " pinskia at gcc dot gnu.org
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: amonakov at gcc dot gnu.org @ 2024-05-02 13:56 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #4 from Alexander Monakov <amonakov at gcc dot gnu.org> ---
You can place points of possible access outside of abstract machine in a
fine-grained manner with volatile asms:

  asm volatile("" : "=m"(buf));

This cannot be reordered against accesses to volatile variables and doesn't
imply modification of anything except 'buf'.

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

* [Bug middle-end/114923] gcc ignores escaping pointer and applies invalid optimization
  2024-05-02 12:51 [Bug c/114923] New: gcc ignores escaping pointer and applies invalid optimization nfxjfg at googlemail dot com
                   ` (3 preceding siblings ...)
  2024-05-02 13:56 ` amonakov at gcc dot gnu.org
@ 2024-05-02 19:07 ` pinskia at gcc dot gnu.org
  2024-05-02 19:15 ` pinskia at gcc dot gnu.org
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: pinskia at gcc dot gnu.org @ 2024-05-02 19:07 UTC (permalink / raw)
  To: gcc-bugs

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

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|---                         |INVALID

--- Comment #5 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Escape means something different from memory being written.

In C (and C++), memory writes to some variable is modeled such that it is not
known to write to another location
So you need to add a compiler barrier here.
Note `atomic_signal_fence (memory_order_relaxed)` might be enough. Note also
the order of the writes to reg1 and reg2 might happen in a different order in
HW so you need to have a full (HW) write barrier between them to make sure the
write is done in the correct order.

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

* [Bug middle-end/114923] gcc ignores escaping pointer and applies invalid optimization
  2024-05-02 12:51 [Bug c/114923] New: gcc ignores escaping pointer and applies invalid optimization nfxjfg at googlemail dot com
                   ` (4 preceding siblings ...)
  2024-05-02 19:07 ` [Bug middle-end/114923] " pinskia at gcc dot gnu.org
@ 2024-05-02 19:15 ` pinskia at gcc dot gnu.org
  2024-05-02 23:03 ` nfxjfg at googlemail dot com
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: pinskia at gcc dot gnu.org @ 2024-05-02 19:15 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #6 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Some resources about memory barriers and why they are needed here (for both HW
and SW):
https://en.wikipedia.org/wiki/Memory_barrier

https://www.kernel.org/doc/Documentation/memory-barriers.txt
https://www.oreilly.com/library/view/linux-device-drivers/0596005903/ch09.html

And many more.

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

* [Bug middle-end/114923] gcc ignores escaping pointer and applies invalid optimization
  2024-05-02 12:51 [Bug c/114923] New: gcc ignores escaping pointer and applies invalid optimization nfxjfg at googlemail dot com
                   ` (5 preceding siblings ...)
  2024-05-02 19:15 ` pinskia at gcc dot gnu.org
@ 2024-05-02 23:03 ` nfxjfg at googlemail dot com
  2024-05-02 23:42 ` pinskia at gcc dot gnu.org
  2024-05-03  0:30 ` nfxjfg at googlemail dot com
  8 siblings, 0 replies; 10+ messages in thread
From: nfxjfg at googlemail dot com @ 2024-05-02 23:03 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #7 from nfxjfg at googlemail dot com ---
> Note also the order of the writes to reg1 and reg2 might happen in a different order in HW so you need to have a full (HW) write barrier between them to make sure the write is done in the correct order.

Seriously? That breaks literally all code that uses volatile for register
access (which, in our firmwares, is ALL code). This just fuels my belief that
gcc and C compiler developers in general turned C into a useless, fragile
language that can't do anything correctly.

Is there a way to prevent reordering of volatile accesses?

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

* [Bug middle-end/114923] gcc ignores escaping pointer and applies invalid optimization
  2024-05-02 12:51 [Bug c/114923] New: gcc ignores escaping pointer and applies invalid optimization nfxjfg at googlemail dot com
                   ` (6 preceding siblings ...)
  2024-05-02 23:03 ` nfxjfg at googlemail dot com
@ 2024-05-02 23:42 ` pinskia at gcc dot gnu.org
  2024-05-03  0:30 ` nfxjfg at googlemail dot com
  8 siblings, 0 replies; 10+ messages in thread
From: pinskia at gcc dot gnu.org @ 2024-05-02 23:42 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #8 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
(In reply to nfxjfg from comment #7)
> > Note also the order of the writes to reg1 and reg2 might happen in a different order in HW so you need to have a full (HW) write barrier between them to make sure the write is done in the correct order.
> 
> Seriously? That breaks literally all code that uses volatile for register
> access (which, in our firmwares, is ALL code). This just fuels my belief
> that gcc and C compiler developers in general turned C into a useless,
> fragile language that can't do anything correctly.
> 
> Is there a way to prevent reordering of volatile accesses?

Yes you need to use inline-asm to get a hw write barrier.
This has been this way for the last 20+ years even when it comes to out of
order processors. 

https://www.puppetmastertrading.com/images/hwViewForSwHackers.pdf should be
very useful. Basically volatile means the compiler not to remove the store/load
from it but it does not mean the HW will reorder the stores/loads. 

Oh and GCC even documents part of this:
https://gcc.gnu.org/onlinedocs/gcc/Volatiles.html

"Accesses to non-volatile objects are not ordered with respect to volatile
accesses. You cannot use a volatile object as a memory barrier to order a
sequence of writes to non-volatile memory. "

The documentation does not mention hw memory barriers since that is outside of
the compiler view really. This has been standard behavior with GCC and hardware
with weak memory systems for over 20 years.

That is even if GCC outputs the writes in order in the assembly the hardware
(or future hardware depending on the definition of the hardware) might reorder
the writes. RISCV IIRC has both a weak and strong memory consistency models.
https://riscv.org/wp-content/uploads/2018/05/14.25-15.00-RISCVMemoryModelTutorial.pdf
for more details on it. GCC will never output the needed instructions directly.

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

* [Bug middle-end/114923] gcc ignores escaping pointer and applies invalid optimization
  2024-05-02 12:51 [Bug c/114923] New: gcc ignores escaping pointer and applies invalid optimization nfxjfg at googlemail dot com
                   ` (7 preceding siblings ...)
  2024-05-02 23:42 ` pinskia at gcc dot gnu.org
@ 2024-05-03  0:30 ` nfxjfg at googlemail dot com
  8 siblings, 0 replies; 10+ messages in thread
From: nfxjfg at googlemail dot com @ 2024-05-03  0:30 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #9 from nfxjfg at googlemail dot com ---
Oh, I completely missed that your statement was restricted to "in HW". Normally
there are mechanisms in place that make all CPU-level memory accesses to
registers strictly ordered. (In our hardware that is also the case.) I panicked
because you seemed to imply that even the compiler can reorder accesses to reg1
and reg2, but this isn't the case according to you, the gcc docs, and maybe the
standard. Sorry about that.

I suppose it's regrettable that C and gcc do not consider the possibility that
passing an address to a register (which volatile is pretty much the only useful
thing for) does not imply that the memory at that address may change. But that
seems to be the conclusion here.

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

end of thread, other threads:[~2024-05-03  0:30 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-05-02 12:51 [Bug c/114923] New: gcc ignores escaping pointer and applies invalid optimization nfxjfg at googlemail dot com
2024-05-02 12:52 ` [Bug c/114923] " nfxjfg at googlemail dot com
2024-05-02 13:24 ` amonakov at gcc dot gnu.org
2024-05-02 13:44 ` nfxjfg at googlemail dot com
2024-05-02 13:56 ` amonakov at gcc dot gnu.org
2024-05-02 19:07 ` [Bug middle-end/114923] " pinskia at gcc dot gnu.org
2024-05-02 19:15 ` pinskia at gcc dot gnu.org
2024-05-02 23:03 ` nfxjfg at googlemail dot com
2024-05-02 23:42 ` pinskia at gcc dot gnu.org
2024-05-03  0:30 ` nfxjfg at googlemail dot com

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).