Patchwork PATCH: Properly generate X32 IE sequence

login
register
mail settings
Submitter Uros Bizjak
Date March 12, 2012, 7:39 p.m.
Message ID <CAFULd4bYk9N-4WZFnq7qM=mgDWziKj2+c-_zV0PgYPP9yB9ryQ@mail.gmail.com>
Download mbox | patch
Permalink /patch/146226/
State New
Headers show

Comments

Uros Bizjak - March 12, 2012, 7:39 p.m.
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.
H.J. Lu - March 12, 2012, 10:35 p.m.
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.
H.J. Lu - March 13, 2012, 1:20 a.m.
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
Uros Bizjak - March 13, 2012, 7:11 a.m.
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.

Patch

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;