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.

Reply via email to