http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54445
Bug #: 54445 Summary: TLS array lookup with negative constant is not combined into a single instruction Classification: Unclassified Product: gcc Version: 4.7.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target AssignedTo: unassig...@gcc.gnu.org ReportedBy: a...@consulting.net.nz I have encountered a weird Thread Local Storage issue where negative constants in an array lookup statement are not combined into a single memory load instruction. Non-negative constant are handled OK. $ cat tls_array_lookup_with_negative_constant_not_combined_into_a_single_instruction.c #include <stdint.h> uint8_t array[64]; __thread uint8_t tls_array[64]; uint8_t array_lookup_with_positive_constant(int64_t position) { return array[position + 1]; } uint8_t array_lookup_with_negative_constant(int64_t position) { return array[position - 1]; } uint8_t tls_array_lookup_with_positive_constant(int64_t position) { return tls_array[position + 1]; } uint8_t tls_array_lookup_with_negative_constant(int64_t position) { return tls_array[position - 1]; } int main(void) { return 0; } $ gcc -O3 -std=gnu11 -pthread tls_array_lookup_with_negative_constant_not_combined_into_a_single_instruction.c && objdump -d -m i386:x86-64:intel a.out |less 0000000000400540 <array_lookup_with_positive_constant>: 400540: 0f b6 87 e1 09 60 00 movzx eax,BYTE PTR [rdi+0x6009e1] 400547: c3 ret 400548: 0f 1f 84 00 00 00 00 nop DWORD PTR [rax+rax*1+0x0] 40054f: 00 0000000000400550 <array_lookup_with_negative_constant>: 400550: 0f b6 87 df 09 60 00 movzx eax,BYTE PTR [rdi+0x6009df] 400557: c3 ret 400558: 0f 1f 84 00 00 00 00 nop DWORD PTR [rax+rax*1+0x0] 40055f: 00 0000000000400560 <tls_array_lookup_with_positive_constant>: 400560: 64 0f b6 87 c1 ff ff movzx eax,BYTE PTR fs:[rdi-0x3f] 400567: ff 400568: c3 ret 400569: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0] 0000000000400570 <tls_array_lookup_with_negative_constant>: 400570: 48 c7 c0 c0 ff ff ff mov rax,0xffffffffffffffc0 400577: 64 0f b6 44 07 ff movzx eax,BYTE PTR fs:[rdi+rax*1-0x1] 40057d: c3 ret 40057e: 90 nop 40057f: 90 nop I believe tls_array_lookup_with_negative_constant should generate the instruction movzx eax,BYTE PTR fs:[rdi-0x41] Note: I initially observed the issue with the cmp instruction (e.g. mov rax,0xfffffffffffffdc0; cmp BYTE PTR fs:[rax+rcx*1-0x80],r8b) so the issue is likely to apply to all x86-64 instructions that perform a TLS memory load with a negative constant.