[Bug lto/120559] local variable stack store eliminated while its stack location is kept as passed argument (only with LTO, rv64gc)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120559 --- Comment #7 from Andrew Pinski --- >1. Does it affect the caller due to LTO being used? LTO just exposes the issue as now the compiler has aliasing info from the functions of all Translational units. GCC 12 (or was it 13) added IPA based aliasing to functions (modref) which allows more optimizations to happen and expose your bad code. Also the aliasing and undefined behavior is documented in many places and there are many papers about it which you should read up on. This is not the correct place of asking questions about it though since this is not related to GCC bug as it is about the C/C++ language rather than GCC implementation. If you have questions about GCC implementation on why it gets exposed in some cases; even bugzilla is not the right place either.
[Bug lto/120559] local variable stack store eliminated while its stack location is kept as passed argument (only with LTO, rv64gc)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120559 --- Comment #6 from Lucian Raul Silistru --- (In reply to Andrew Pinski from comment #5) > struct tx_buffer_entry *entry; > > uint32_t * ptr = (void *)(&entry); > > uint32_t value = (*ptr | (channel & 3)); > // alias violation here, reading a `struct tx_buffer_entry *` value via > uint32_t. > > Use -fno-strict-aliasing or fix your code differently. > > https://gist.github.com/shafik/848ae25ee209f698763cffee272a58f8 is a good > place to start reading up about strict aliasing. But there are many more > pages about it. Thanks for confirming. Barely looked at that function with the symptom in the caller. 2 final questions: 1. Does it affect the caller due to LTO being used? 2. So it is tx_buffer_entry ** -> uint32_t * + deref that just adds an aliasing violation to just do the same as tx_buffer_entry * -> uint32_t, correct?
[Bug lto/120559] local variable stack store eliminated while its stack location is kept as passed argument (only with LTO, rv64gc)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120559 Andrew Pinski changed: What|Removed |Added Status|UNCONFIRMED |RESOLVED Resolution|--- |INVALID --- Comment #5 from Andrew Pinski --- struct tx_buffer_entry *entry; uint32_t * ptr = (void *)(&entry); uint32_t value = (*ptr | (channel & 3)); // alias violation here, reading a `struct tx_buffer_entry *` value via uint32_t. Use -fno-strict-aliasing or fix your code differently. https://gist.github.com/shafik/848ae25ee209f698763cffee272a58f8 is a good place to start reading up about strict aliasing. But there are many more pages about it.
[Bug lto/120559] local variable stack store eliminated while its stack location is kept as passed argument (only with LTO, rv64gc)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120559
--- Comment #4 from Lucian Raul Silistru ---
(In reply to Sam James from comment #3)
> __attribute__((noinline)) void write_to_hw(uint32_t channel, uint32_t * ptr)
>
> __attribute__((noinline)) void send_buffer(uint32_t channel, void *ptr,
> uint32_t size) {
>
> and ...
> __attribute__((noinline)) void hw_low_level_write(uint32_t channel, uint32_t
> value)
>
> uint32_t* vs tx_buffer_entry*
Yes, have to push 32 LSB but it's not required to be a half of
tx_buffer_entry*. Other send_* push other pointers through other instances of
the same hardware. That must have been the intent of the separation, but
confirmation is long gone, code is half a decade old.
Current workarounds we have are just use a (uint32_t)entry, don't do the silly
pass the address and dereference the pointer.
Or dumb stuff like add - "%p", (void*)&entry - to the printf - which still
forces keeping the save of &entry to stack.
[Bug lto/120559] local variable stack store eliminated while its stack location is kept as passed argument (only with LTO, rv64gc)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120559
--- Comment #3 from Sam James ---
__attribute__((noinline)) void write_to_hw(uint32_t channel, uint32_t * ptr) {
while (1) {
hw_low_level_write(channel, (*ptr | (channel & 3)));
if (!hw_low_level_overflow(channel, 7)) {
break; // Exit loop if the hardware is ready
}
}
}
__attribute__((noinline)) void send_buffer(uint32_t channel, void *ptr,
uint32_t size) {
struct tx_buffer_entry *entry;
/* ... */
entry = get_buffer();
entry->data = ptr;
entry->size = size;
entry->state = 1; // Mark as used
/* ... */
write_to_hw(channel, (void *)(&entry));
}
and ...
#ifndef SET_REG_WORD
#define SET_REG_WORD(a, x) ((void)(*(volatile uint32_t *)(((uintptr_t)(a))) =
(uint32_t)(x)))
#endif
__attribute__((noinline)) void hw_low_level_write(uint32_t channel, uint32_t
value) {
SET_REG_WORD(REG_LOC, value);
// Write the value to the specified hardware channel
// This is a placeholder implementation
// Actual implementation would depend on the specific hardware
// and might involve memory-mapped I/O or other mechanisms.
}
uint32_t* vs tx_buffer_entry*
[Bug lto/120559] local variable stack store eliminated while its stack location is kept as passed argument (only with LTO, rv64gc)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120559 --- Comment #2 from Lucian Raul Silistru --- hw_sender.o dasm (end of send_buffer() - see offset 7c); -O2 -flto -ffat-lto-objects: 0068 <.LVL17>: 68: 01163423sd a7,8(a2) 6c: 01062823sw a6,16(a2) 70: 00f60023sb a5,0(a2) 74: 0517auipc a0,0x0 74: R_RISCV_PCREL_HI20 .LC0 74: R_RISCV_RELAX *ABS* 78: 00050513mv a0,a0 78: R_RISCV_PCREL_LO12_I.L0 78: R_RISCV_RELAX *ABS* 007c <.LVL18>: 7c: e432sd a2,8(sp) 007e <.LBB27>: 7e: 00c33423sd a2,8(t1) 0082 <.LBE27>: 82: 0097auipc ra,0x0 82: R_RISCV_CALL_PLTprintf 82: R_RISCV_RELAX *ABS* 86: 80e7jalrra # 82 <.LBE27> 008a <.LVL20>: 8a: 002caddia1,sp,8 8c: 8522mv a0,s0 8e: 0097auipc ra,0x0 8e: R_RISCV_CALL_PLTwrite_to_hw 8e: R_RISCV_RELAX *ABS* 92: 80e7jalrra # 8e <.LVL20+0x4>
[Bug lto/120559] local variable stack store eliminated while its stack location is kept as passed argument (only with LTO, rv64gc)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120559 --- Comment #1 from Andrew Pinski --- This smells like an alias violation.
