Message ID | CAFULd4bYk9N-4WZFnq7qM=mgDWziKj2+c-_zV0PgYPP9yB9ryQ@mail.gmail.com |
---|---|
State | New |
Headers | show |
On Mon, Mar 12, 2012 at 12:39 PM, Uros Bizjak <ubizjak@gmail.com> wrote: > On Sun, Mar 11, 2012 at 10:24 PM, H.J. Lu <hjl.tools@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. I am testing it.
On Mon, Mar 12, 2012 at 3:35 PM, H.J. Lu <hjl.tools@gmail.com> wrote: > On Mon, Mar 12, 2012 at 12:39 PM, Uros Bizjak <ubizjak@gmail.com> wrote: >> On Sun, Mar 11, 2012 at 10:24 PM, H.J. Lu <hjl.tools@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. > > I am testing it. > There is no regression. BTW, this x32 TLS IE optimization: http://gcc.gnu.org/ml/gcc-patches/2012-03/msg00714.html is still useful. For [hjl@gnu-6 tls]$ cat ie2.i extern __thread long long int x; extern long long int y; void ie2 (void) { x = y; } [hjl@gnu-6 tls]$ my patch turns ie2: .LFB0: .cfi_startproc movq y(%rip), %rdx # 6 *movdi_internal_rex64/2 [length = 7] movl %fs:0, %eax # 5 tls_initial_exec_x32 [length = 16] addl x@gottpoff(%rip), %eax movq %rdx, (%eax) # 7 *movdi_internal_rex64/4 [length = 3] ret # 14 simple_return_internal [length = 1] .cfi_endproc into ie2: .LFB0: .cfi_startproc movq y(%rip), %rax # 6 *movdi_internal_rex64/2 [length = 7] movq x@gottpoff(%rip), %rdx # 7 *tls_initial_exec_x32_store [length = 16] movq %rax, %fs:(%rdx) ret # 14 simple_return_internal [length = 1] .cfi_endproc
On Tue, Mar 13, 2012 at 2:20 AM, H.J. Lu <hjl.tools@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. > > There is no regression. Thanks, committed to mainline SVN with following ChangeLog: 2012-03-13 Uros Bizjak <ubizjak@gmail.com> * config/i386/i386.h (TARGET_TLS_INDIRECT_SEG_REFS): New. * config/i386/i386.c (ix86_decompose_address): Use TARGET_TLS_INDIRECT_SEG_REFS to prevent %fs:(%reg) addresses. (legitimize_tls_address): Use TARGET_TLS_INDIRECT_SEG_REFS to load thread pointer to a register. Tested on x86_64-pc-linux-gnu {,-m32}. > BTW, this x32 TLS IE optimization: > movq %rax, %fs:(%rdx) This is just looking for troubles. If we said these addresses are invalid, then we shouldn't generate them. 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;