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.

Reply via email to