On Thu, Jul 28, 2011 at 3:03 PM, Uros Bizjak <ubiz...@gmail.com> wrote: > On Thu, Jul 28, 2011 at 10:15 PM, H.J. Lu <hjl.to...@gmail.com> wrote: > >>>>>>>> TP is 32bit in x32 For load_tp_x32, we load SImode value and >>>>>>>> zero-extend to DImode. For add_tp_x32, we are adding SImode >>>>>>>> value. We can't pretend TP is 64bit. load_tp_x32 and add_tp_x32 >>>>>>>> must take SImode TP. > >> Here is the revised patch. The difference is I changed *add_tp_x32 to >> SImode. >> For >> >> --- >> extern __thread int __libc_errno __attribute__ ((tls_model >> ("initial-exec"))); >> >> int * >> __errno_location (void) >> { >> return &__libc_errno; >> } >> --- >> >> compiled with -mx32 -O2 -fPIC DImode *add_tp_x32 generates: >> >> movq __libc_errno@gottpoff(%rip), %rax >> addl %fs:0, %eax >> mov %eax, %eax >> ret >> >> SImode *add_tp_x32 generates: >> >> movl %fs:0, %eax >> addl __libc_errno@gottpoff(%rip), %eax >> ret > > This happens because combine can't combine DImode load and SImode plus > RTXes. These RTXes have to be in Pmode, see the intention in > legitimize_tls_address, also for TARGET_GNU2_TLS. > > Can you please debug what goes wrong with tp_add_x32 in DImode? >
We start with insn 5 2 6 2 (set (reg:DI 63) (unspec:DI [ (const_int 0 [0]) ] UNSPEC_TP)) err.i:6 716 {*load_tp_x32} (nil)) (insn 6 5 7 2 (set (reg:DI 64) (mem/u/c:DI (const:DI (unspec:DI [ (symbol_ref:SI ("__libc_errno") [flags 0x60] <var_decl 0x7ffff085b140 __libc_errno>) ] UNSPEC_GOTNTPOFF)) [0 S8 A8])) err.i:6 62 {*movdi_internal _rex64} (nil)) (insn 7 6 8 2 (parallel [ (set (reg:DI 65) (plus:DI (reg:DI 63) (reg:DI 64))) (clobber (reg:CC 17 flags)) ]) err.i:6 251 {*adddi_1} (expr_list:REG_DEAD (reg:DI 64) (expr_list:REG_DEAD (reg:DI 63) (expr_list:REG_UNUSED (reg:CC 17 flags) (nil))))) With DImode *add_tp_x32, combine matches (parallel [ (set (reg:DI 65) (plus:DI (unspec:DI [ (const_int 0 [0]) ] UNSPEC_TP) (reg:DI 64))) (clobber (reg:CC 17 flags)) ]) first. It turns out that it isn't a very good choice since it prevents combine to try (parallel [ (set (reg:DI 65) (plus:DI (reg:DI 63) (mem/u/c:DI (const:DI (unspec:DI [ (symbol_ref:SI ("__libc_errno") [flags 0x60] <var_decl 0x7 ffff085b140 __libc_errno>) ] UNSPEC_GOTNTPOFF)) [0 S8 A8]))) (clobber (reg:CC 17 flags)) ]) I am not sure how useful *add_tp_XXX pattern is. -- H.J.