On Sun, Mar 11, 2012 at 11:21 AM, Uros Bizjak <ubiz...@gmail.com> wrote: > On Sun, Mar 11, 2012 at 7:16 PM, H.J. Lu <hjl.to...@gmail.com> wrote: > >>>>>>> * config/i386/i386.c (ix86_decompose_address): Disallow fs:(reg) >>>>>>> if Pmode != word_mode. >>>>>>> (legitimize_tls_address): Call gen_tls_initial_exec_x32 if >>>>>>> Pmode == SImode for x32. >>>>>>> >>>>>>> * config/i386/i386.md (UNSPEC_TLS_IE_X32): New. >>>>>>> (tls_initial_exec_x32): Likewise. >>>>>> >>>>>> Nice solution! >>>>>> >>>>>> OK for mainline. >>>>> >>>>> Done. >>>>> >>>>>> BTW: Did you investigate the issue with memory aliasing? >>>>>> >>>>> >>>>> It isn't a problem since it is wrapped in UNSPEC_TLS_IE_X32 >>>>> which loads address of the TLS symbol. >>>>> >>>>> Thanks. >>>>> >>>> >>>> Since we must use reg64 in %fs:(%reg) memory operand like >>>> >>>> movq x@gottpoff(%rip),%reg64; >>>> mov %fs:(%reg64),%reg >>>> >>>> this patch optimizes x32 TLS IE load and store by wrapping >>>> %reg64 inside of UNSPEC when Pmode == SImode. OK for >>>> trunk? >>> >>> I think we should just scrap all these complications and go with the >>> idea of clearing MASK_TLS_DIRECT_SEG_REFS. >>> >> >> I will give it a try. > > You can also revert: > >>>>>>> * config/i386/i386.c (ix86_decompose_address): Disallow fs:(reg) >>>>>>> if Pmode != word_mode. > > then, since this part is handled later in the function. >
Here is the patch which is equivalent to clearing MASK_TLS_DIRECT_SEG_REFS when Pmode != word_mode. We need to keep else if (Pmode == SImode) { /* Always generate movl %fs:0, %reg32 addl xgottpoff(%rip), %reg32 to support linker IE->LE optimization and avoid fs:(%reg32) as memory operand. */ dest = gen_reg_rtx (Pmode); emit_insn (gen_tls_initial_exec_x32 (dest, x)); return dest; } to support linker IE->LE optimization. TARGET_TLS_DIRECT_SEG_REFS only affects TLS LE access and fs:(%reg) is only generated by combine. So the main impact of disabling TARGET_TLS_DIRECT_SEG_REFS is to disable fs:immediate memory operand for TLS LE access, which doesn't have any problems to begin with. I would prefer to keep TARGET_TLS_DIRECT_SEG_REFS and disable only fs:(%reg), which is generated by combine. -- H.J. -- diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index b101922..1ffcc85 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -11478,6 +11478,7 @@ ix86_decompose_address (rtx addr, struct ix86_address *out) case UNSPEC: if (XINT (op, 1) == UNSPEC_TP + && Pmode == word_mode && TARGET_TLS_DIRECT_SEG_REFS && seg == SEG_DEFAULT) seg = TARGET_64BIT ? SEG_FS : SEG_GS; @@ -11534,11 +11535,6 @@ ix86_decompose_address (rtx addr, struct ix86_address *out) else disp = addr; /* displacement */ - /* Since address override works only on the (reg32) part in fs:(reg32), - we can't use it as memory operand. */ - if (Pmode != word_mode && seg == SEG_FS && (base || index)) - return 0; - if (index) { if (REG_P (index)) @@ -12706,7 +12702,9 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov) if (TARGET_64BIT || TARGET_ANY_GNU_TLS) { - base = get_thread_pointer (for_mov || !TARGET_TLS_DIRECT_SEG_REFS); + base = get_thread_pointer (for_mov + || Pmode != word_mode + || !TARGET_TLS_DIRECT_SEG_REFS); return gen_rtx_PLUS (Pmode, base, off); } else @@ -13239,7 +13237,7 @@ ix86_delegitimize_tls_address (rtx orig_x) rtx x = orig_x, unspec; struct ix86_address addr; - if (!TARGET_TLS_DIRECT_SEG_REFS) + if (Pmode != word_mode || !TARGET_TLS_DIRECT_SEG_REFS) return orig_x; if (MEM_P (x)) x = XEXP (x, 0);