[Bug inline-asm/85185] New: Wider-than-expected load for struct member used as operand of inline-asm with memory clobber at -Og
zev+gccbug at bewilderbeest dot net
gcc-bugzilla@gcc.gnu.org
Wed Apr 4 02:49:00 GMT 2018
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).
More information about the Gcc-bugs
mailing list