Hello! Using following testcase: --cut here-- __thread int a; int foo (void) { return a; } --cut here-- Attached patch converts TLS location in the form of: (mem/c:SI (plus:DI (unspec:DI [ (const_int 0 [0]) ] UNSPEC_TP) (const:DI (unspec:DI [ (symbol_ref:DI ("a") [flags 0x2a] ) ] UNSPEC_NTPOFF))) [1 a+0 S4 A32])) "thread.c":5 82 {*movsi_internal} to: (mem/c:SI (const:DI (unspec:DI [ (symbol_ref:DI ("a") [flags 0x2a] ) ] UNSPEC_NTPOFF)) [1 a+0 S4 A32 AS1])) "thread.c":5 -1 avoiding the UNSPEC_TP tag and instead mark the location with AS. This way, address space becomes the property of the memory location, not of the address itself, so we don't need ugly hacks when the address is moved to a register (LEA ignores segment overrides, c.f. split_long_move function in i386.c). Please note that some instructions (e.g. prefetchX) operate on prefixed *address*, so we can't just rip out non-AS code from print_operand. The above amended example: --cut here-- __thread int a; int foo (void) { __builtin_prefetch (&a, 0); return a; } --cut here-- compiles to: prefetcht0 %fs:a@tpoff movl %fs:a@tpoff, %eax where prefetch operand remains: (insn 7 6 16 2 (prefetch (plus:DI (unspec:DI [ (const_int 0 [0]) ] UNSPEC_TP) (const:DI (unspec:DI [ (symbol_ref:DI ("a") [flags 0x2a] ) ] UNSPEC_NTPOFF))) (const_int 0 [0]) (const_int 3 [0x3])) "thread.c":5 1010 {*prefetch_sse} (nil)) 2017-08-31 Uros Bizjak * config/i386/i386-protos.h (ix86_tls_address_pattern_p) New prototype. (ix86_rewrite_tls_address): Ditto. * config/i386/i386.c (ix86_tls_address_pattern_p) New function. (ix86_rewrite_tls_address_1): Ditto. (ix86_rewrite_tls_address): Ditto. * config/i386/predicates.md (tls_address_pattern): New predicate. * config/i386/i386.md (TLS address splitter): New splitter. Patch was bootstrapped and regression tested on x86_64-linux-gnu {,-m32}, all default languages plus go. I plan to commit the patch to the mainline early next week. Uros