https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78821
Uroš Bizjak <ubizjak at gmail dot com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |ubizjak at gmail dot com --- Comment #2 from Uroš Bizjak <ubizjak at gmail dot com> --- Some more examples: --cut here-- struct S1 { char val1; char val2; short pad2; }; extern struct S1 s; void test (struct S1 a) { s.val1 = a.val1; s.val2 = a.val2; } --cut here-- results in (x86_64, -O2): test: movl %edi, %eax movb %dil, s(%rip) movb %ah, s+1(%rip) ret the code above is equivalent to: movw %di, s(%rip) ret --cut here-- struct S1 { short val1; short val2; }; extern struct S1 s; void test (struct S1 a) { s.val1 = a.val1; s.val2 = a.val2; } --cut here-- results in (x86_64, -O2): test: movw %di, s(%rip) sarl $16, %edi movw %di, s+2(%rip) ret the code above is equivalent to: movl %edi, s(%rip) The first example happens many times in libstdc++. Looking at src/c++11/cxx11-shim_facets.o for x86_64, there are several examples of: 19d: 88 43 5c mov %al,0x5c(%rbx) 1a0: 88 63 5d mov %ah,0x5d(%rbx) and in the cc1 itself even gems like: 13ee3c6: 48 8b 53 10 mov 0x10(%rbx),%rdx 13ee3ca: 48 8b 43 28 mov 0x28(%rbx),%rax 13ee3ce: 44 89 f9 mov %r15d,%ecx 13ee3d1: 44 88 7c 02 fc mov %r15b,0xfffffffffffffffc(%rdx,%rax,1) 13ee3d6: 48 8b 53 10 mov 0x10(%rbx),%rdx 13ee3da: 48 8b 43 28 mov 0x28(%rbx),%rax 13ee3de: 88 6c 02 fd mov %ch,0xfffffffffffffffd(%rdx,%rax,1) The additional problem represents the fact that move from highpart (%ch) can't use registers other than %ah, %bh, %ch and %dh, and the address can't use REX-prefixed registers in this case, while the move from 16bit register avoids both limitations. So, merging would benefit x86 targets considerably.