https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110052
Bug ID: 110052 Summary: useless local variable not optimized away Product: gcc Version: 14.0 Status: UNCONFIRMED Keywords: missed-optimization Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: aldot at gcc dot gnu.org Target Milestone: --- Created attachment 55221 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55221&action=edit reduced test, v1 A superfluous local variable is not optimized away. Consider: $ cat localvar.c ; echo EOF #include <stddef.h> // original flags: gcc-12 -std=gnu99 -malign-data=abi -finline-limit=0 -fno-builtin-strlen -fomit-frame-pointer -ffunction-sections -fdata-sections -fno-guess-branch-probability -funsigned-char -falign-functions=1 -falign-jumps=1 -falign-labels=1 -falign-loops=1 -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-builtin-printf -Oz extern void *realloc(void *ptr, size_t size); static char * __attribute__((noipa)) myrealloc(void *ptr, int n, int *size) { if (!ptr || n >= *size) { *size = n + (n >> 1) + 80; ptr = realloc (ptr, *size); if (ptr == NULL) /* mimic xrealloc */ __builtin_abort(); } return ptr; } typedef struct foo_s { int fd; char *buffer; int adv; int size; int pos; signed char boo; } foo_t; void bloat(foo_t *); void bloat(foo_t *foo) { char *m = foo->buffer; /* This is the original code, the local variable is superfluous */ int size = foo->size; if (!m) m = myrealloc(m, 256, &size); foo->size = size; } void ok(foo_t *); void ok(foo_t *foo) { char *m = foo->buffer; if (!m) m = myrealloc(m, 256, &foo->size); } EOF $ readelf -s localvar.o | grep "FUNC *GLOBAL" 13: 0000000000000000 52 FUNC GLOBAL DEFAULT 6 bloat 14: 0000000000000000 24 FUNC GLOBAL DEFAULT 8 ok $ strip -R .comment localvar.o $ objdump -D localvar.o localvar.o: file format elf64-x86-64 Disassembly of section .text.myrealloc: 0000000000000000 <.text.myrealloc>: 0: 48 89 f8 mov %rdi,%rax 3: 48 85 ff test %rdi,%rdi 6: 74 04 je 0xc 8: 39 32 cmp %esi,(%rdx) a: 7f 21 jg 0x2d c: 51 push %rcx d: 89 f1 mov %esi,%ecx f: 48 97 xchg %rax,%rdi 11: d1 f9 sar %ecx 13: 8d 74 0e 50 lea 0x50(%rsi,%rcx,1),%esi 17: 89 32 mov %esi,(%rdx) 19: 48 63 f6 movslq %esi,%rsi 1c: e8 00 00 00 00 callq 0x21 21: 48 85 c0 test %rax,%rax 24: 75 05 jne 0x2b 26: e8 00 00 00 00 callq 0x2b 2b: 5a pop %rdx 2c: c3 retq 2d: c3 retq Disassembly of section .text.bloat: 0000000000000000 <.text.bloat>: 0: 53 push %rbx 1: 48 89 fb mov %rdi,%rbx 4: 48 83 ec 10 sub $0x10,%rsp 8: 8b 47 14 mov 0x14(%rdi),%eax b: 48 83 7f 08 00 cmpq $0x0,0x8(%rdi) 10: 89 44 24 0c mov %eax,0xc(%rsp) 14: 75 11 jne 0x27 16: 48 8d 54 24 0c lea 0xc(%rsp),%rdx 1b: be 00 01 00 00 mov $0x100,%esi 20: 31 ff xor %edi,%edi 22: e8 00 00 00 00 callq 0x27 27: 8b 44 24 0c mov 0xc(%rsp),%eax 2b: 89 43 14 mov %eax,0x14(%rbx) 2e: 48 83 c4 10 add $0x10,%rsp 32: 5b pop %rbx 33: c3 retq Disassembly of section .text.ok: 0000000000000000 <.text.ok>: 0: 48 83 7f 08 00 cmpq $0x0,0x8(%rdi) 5: 75 10 jne 0x17 7: 48 8d 57 14 lea 0x14(%rdi),%rdx b: be 00 01 00 00 mov $0x100,%esi 10: 31 ff xor %edi,%edi 12: e9 00 00 00 00 jmpq 0x17 17: c3 retq object size with each myrealloc and either bloat or ok: $ size localvar-*.o text data bss dec hex filename 70 0 0 70 46 localvar-ok.o 98 0 0 98 62 localvar-bloat.o