On Sun, Mar 11, 2012 at 10:24 PM, H.J. Lu <hjl.to...@gmail.com> wrote:
> 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. Please try attached patch. It introduces TARGET_TLS_INDIRECT_SEG_REFS to block only indirect seg references. Uros.
Index: i386.c =================================================================== --- i386.c (revision 185250) +++ i386.c (working copy) @@ -11552,11 +11552,6 @@ ix86_decompose_address (rtx addr, struct ix86_addr 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)) @@ -11568,6 +11563,10 @@ ix86_decompose_address (rtx addr, struct ix86_addr return 0; } + if (seg != SEG_DEFAULT && (base || index) + && !TARGET_TLS_INDIRECT_SEG_REFS) + return 0; + /* Extract the integral value of scale. */ if (scale_rtx) { @@ -12696,7 +12695,9 @@ legitimize_tls_address (rtx x, enum tls_model mode if (TARGET_64BIT || TARGET_ANY_GNU_TLS) { - base = get_thread_pointer (for_mov || !TARGET_TLS_DIRECT_SEG_REFS); + base = get_thread_pointer (for_mov + || !(TARGET_TLS_DIRECT_SEG_REFS + && TARGET_TLS_INDIRECT_SEG_REFS)); off = force_reg (Pmode, off); return gen_rtx_PLUS (Pmode, base, off); } @@ -12716,7 +12717,9 @@ legitimize_tls_address (rtx x, enum tls_model mode if (TARGET_64BIT || TARGET_ANY_GNU_TLS) { - base = get_thread_pointer (for_mov || !TARGET_TLS_DIRECT_SEG_REFS); + base = get_thread_pointer (for_mov + || !(TARGET_TLS_DIRECT_SEG_REFS + && TARGET_TLS_INDIRECT_SEG_REFS)); return gen_rtx_PLUS (Pmode, base, off); } else @@ -13249,7 +13252,8 @@ ix86_delegitimize_tls_address (rtx orig_x) rtx x = orig_x, unspec; struct ix86_address addr; - if (!TARGET_TLS_DIRECT_SEG_REFS) + if (!(TARGET_TLS_DIRECT_SEG_REFS + && TARGET_TLS_INDIRECT_SEG_REFS)) return orig_x; if (MEM_P (x)) x = XEXP (x, 0); Index: i386.h =================================================================== --- i386.h (revision 185250) +++ i386.h (working copy) @@ -467,6 +467,9 @@ extern int x86_prefetch_sse; #define TARGET_TLS_DIRECT_SEG_REFS_DEFAULT 0 #endif +/* Address override works only on the (%reg) part in %fs:(%reg). */ +#define TARGET_TLS_INDIRECT_SEG_REFS (Pmode == word_mode) + /* Fence to use after loop using storent. */ extern tree x86_mfence;