https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120559
Bug ID: 120559
Summary: local variable stack store eliminated while its stack
location is kept as passed argument (only with LTO,
rv64gc)
Product: gcc
Version: 13.3.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: lto
Assignee: unassigned at gcc dot gnu.org
Reporter: lucian.silistru at gmail dot com
Target Milestone: ---
Created attachment 61588
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=61588&action=edit
source code to repro, build.sh to build, riscv-none-elf-gcc-13.3.0 used
__attribute__((noinline)) void send_buffer(uint32_t channel, void *ptr,
uint32_t size) {
struct tx_buffer_entry *entry;
channel_init();
entry = get_buffer();
if (entry == NULL) {
printf("Error finding buffer\n");
return;
}
entry->data = ptr;
entry->size = size;
entry->state = 1;
printf("Sending data on channel %u, from loc %p\n", channel, (void*)entry);
write_to_hw(channel, (void *)(&entry));
}
In a function like the above, sometimes when linking with LTO, entry is used as
a register throughout the function body but the end store that copies it to the
stack will vanish. write_to_hw() is always called with the value sp+offset
written to a1. But "sd entry_reg, offset(sp)" is sometimes deleted.
"sd entry_reg, offset(sp)" always shows up in current object disassembly,
always shows up in non-LTO linking (no matter how it was compiled), sometimes
shows up in LTO-linked versions, at least never seen in gcc 9.3 for years and
now on gcc 13.3.0 showed up after that "printf" like function got updated.
In the following dasm, a2 ends up being entry, it is never saved to sp+8 but
sp+8 is passed to a1 for write_to_hw():
00000000000101ec <send_buffer.constprop.0>:
...
1023a: e61c sd a5,8(a2)
1023c: 4785 li a5,1
1023e: 85a2 mv a1,s0
10240: 00062823 sw zero,16(a2)
10244: 00f60023 sb a5,0(a2)
10248: 00009517 auipc a0,0x9
1024c: 79050513 addi a0,a0,1936 # 199d8 <__trunctfdf2+0x2ee>
10250: 00c83423 sd a2,8(a6)
10254: 64e010ef jal 118a2 <printf>
10258: 002c addi a1,sp,8
1025a: 8522 mv a0,s0
1025c: f6bff0ef jal 101c6 <write_to_hw>
10260: 60e2 ld ra,24(sp)
10262: 6442 ld s0,16(sp)
10264: 6105 addi sp,sp,32
10266: 8082 ret
Attaching small (not functional but should compile just fine) reproduction
code.
Used xpack-riscv-none-elf-gcc-13.3.0-1 to compiler but initial repro was on a
riscv-rtems6-13.3.0.
In the attached hw_work.ltrans0.ltrans.254t.optimized, in send_buffer, the
register use of entry is idx_20, &entry is passed and never initialized.
Main suspicion right now is that this is some UB but I can't figure out/I don't
know what exactly.