https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85185
Bug ID: 85185 Summary: Wider-than-expected load for struct member used as operand of inline-asm with memory clobber at -Og Product: gcc Version: 7.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: inline-asm Assignee: unassigned at gcc dot gnu.org Reporter: zev+gccbug at bewilderbeest dot net Target Milestone: --- Created attachment 43832 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=43832&action=edit Minimized reproducer In the attached test case, compiling with -Og generates a wider memory access than expected (4 bytes instead of 2, on the LP64 targets I'm dealing with) to load sub.a on line 12. -- $ nl -ba min.c 1 struct sub { 2 short a, b; 3 }; 4 5 struct { 6 int i; 7 struct sub P; 8 } S; 9 10 static inline void inner(struct sub sub) 11 { 12 asm("magic %0" :: "r" (sub.a) : "memory"); 13 } 14 15 void outer(void) 16 { 17 inner(S.P); 18 } $ gcc -S -o - -Og min.c .file "min.c" .text .globl outer .type outer, @function outer: .LFB1: .cfi_startproc movl 4+S(%rip), %eax #APP # 12 "min.c" 1 magic %ax # 0 "" 2 #NO_APP ret .cfi_endproc .LFE1: .size outer, .-outer .comm S,8,8 .ident "GCC: (GNU) 7.3.0" .section .note.GNU-stack,"",@progbits -- On x86-64 it ends up being relatively harmless because it uses a 16-bit register (%ax) as the actual operand used in the instruction, but on targets that only have full-width registers (riscv64 being the one at hand for me) this results in the instruction receiving a very different operand than desired (containing additional bytes from the neighboring struct member): -- $ riscv64-unknown-elf-gcc -S -o - -Og min.c .file "min.c" .option nopic .text .align 2 .globl outer .type outer, @function outer: addi sp,sp,-16 lui a5,%hi(S) addi a5,a5,%lo(S) lw a5,4(a5) sw a5,8(sp) #APP # 17 "min.c" 1 magic a5 # 0 "" 2 #NO_APP addi sp,sp,16 jr ra .size outer, .-outer .comm S,8,8 .ident "GCC: (GNU) 7.2.0" -- This only occurs when compiling with -Og; -O0, -O1, -O2, and -O3 all generate the expected two-byte load (movzwl instead of movl on x86-64, lh or lhu instead of lw on riscv64). I've also found via a bit of haphazard guess-based experimentation that adding -ftree-sra to -Og produces a two-byte load as well. I've observed these same patterns (4-byte load at -Og, 2-byte load at all other -O levels or with -ftree-sra) on a number of different GCCs: - x86-64: 4.8.2 (Red Hat), 5.1.0 (source), 5.4.0 (Ubuntu), 7.2.0 (source), 7.3.0 (Void) - riscv64: 6.1.0 and 7.2.0 (both from source; I realize the former predates official upstream riscv support but is perhaps illustrative nonetheless) I've filed this on release 7.2.0 because that's the version where this is actually biting me -- and as mentioned above, is only actually causing problems on riscv, but the very similar code generation on x86 makes me suspect the underlying problem is target-independent (and has apparently existed for a while).