diff mbox

PATCH: Properly generate X32 IE sequence

Message ID CAMe9rOqUiNgXhsRc0abM0COB5Ck5zy8tsivu8zQ2386DfN7ZWw@mail.gmail.com
State New
Headers show

Commit Message

H.J. Lu March 17, 2012, 9:50 p.m. UTC
On Sat, Mar 17, 2012 at 11:20 AM, Uros Bizjak <ubizjak@gmail.com> wrote:
> On Sat, Mar 17, 2012 at 7:18 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>
>>>> 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?
>>>>
>>>> Thanks.
>>>>
>>>> --
>>>> H.J.
>>>> ---
>>>> 2012-03-11  H.J. Lu  <hongjiu.lu@intel.com>
>>>>
>>>>        * config/i386/i386.md (*tls_initial_exec_x32_load): New.
>>>>        (*tls_initial_exec_x32_store): Likewise.
>>>
>>> Can you implement this with define_insn_and_split, like i.e.
>>> *tls_dynamic_gnu2_combine_32 ?
>>>
>>
>> I will give it a try again.  Last time when I tried it, GCC didn't
>> like memory operand in DImode when Pmode == SImode.
>
> You should remove mode for tls_symbolic_operand predicate.
>

I am testing this patch.  OK for trunk if it passes all tests?

Thanks.

Comments

Uros Bizjak March 18, 2012, 4:01 p.m. UTC | #1
On Sat, Mar 17, 2012 at 10:50 PM, H.J. Lu <hjl.tools@gmail.com> wrote:

>>>>> 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?
>>>>
>>>> Can you implement this with define_insn_and_split, like i.e.
>>>> *tls_dynamic_gnu2_combine_32 ?
>>>>
>>>
>>> I will give it a try again.  Last time when I tried it, GCC didn't
>>> like memory operand in DImode when Pmode == SImode.
>>
>> You should remove mode for tls_symbolic_operand predicate.
>>
>
> I am testing this patch.  OK for trunk if it passes all tests?

No, force_reg will generate a pseudo, so this conversion is valid only
for !can_create_pseudo ().

At least for *tls_initial_exec_x32_store, you will need a temporary to
split the pattern after reload.

Uros.
diff mbox

Patch

diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 630112f..2c4f1ed 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -213,6 +213,7 @@  extern unsigned int ix86_get_callcvt (const_tree);
 #endif
 
 extern rtx ix86_tls_module_base (void);
+extern void ix86_split_tls_initial_exec_x32 (rtx [], enum machine_mode, bool);
 
 extern void ix86_expand_vector_init (bool, rtx, rtx);
 extern void ix86_expand_vector_set (bool, rtx, rtx, int);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 78a366e..5a9c673 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -12754,6 +12754,28 @@  legitimize_tls_address (rtx x, enum tls_model model, bool for_mov)
   return dest;
 }
 
+/* Split x32 TLS IE access in MODE.  Split load if LOAD is TRUE,
+   otherwise split store.  */
+
+void
+ix86_split_tls_initial_exec_x32 (rtx operands[],
+				 enum machine_mode mode, bool load)
+{
+  rtx base, mem;
+  rtx off = load ? operands[1] : operands[0];
+  off = gen_rtx_UNSPEC (DImode, gen_rtvec (1, off), UNSPEC_GOTNTPOFF);
+  off = gen_rtx_CONST (DImode, off);
+  off = gen_const_mem (DImode, off);
+  set_mem_alias_set (off, ix86_GOT_alias_set ());
+  base = gen_rtx_UNSPEC (DImode, gen_rtvec (1, const0_rtx), UNSPEC_TP);
+  off = gen_rtx_PLUS (DImode, base, force_reg (DImode, off));
+  mem = gen_rtx_MEM (mode, off);
+  if (load)
+    emit_move_insn (operands[0], mem);
+  else
+    emit_move_insn (mem, operands[1]);
+}
+
 /* Create or return the unique __imp_DECL dllimport symbol corresponding
    to symbol DECL.  */
 
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index eae26ae..78faeec 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -12858,6 +12858,32 @@ 
 }
   [(set_attr "type" "multi")])
 
+(define_insn_and_split "*tls_initial_exec_x32_load"
+  [(set (match_operand:SWI1248x 0 "register_operand" "=r")
+        (mem:SWI1248x
+	  (unspec:SI
+	   [(match_operand 1 "tls_symbolic_operand" "")]
+	   UNSPEC_TLS_IE_X32)))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_X32"
+  "#"
+  ""
+  [(const_int 0)]
+  "ix86_split_tls_initial_exec_x32 (operands, <MODE>mode, TRUE); DONE;")
+
+(define_insn_and_split "*tls_initial_exec_x32_store"
+  [(set (mem:SWI1248x
+	  (unspec:SI
+	   [(match_operand 0 "tls_symbolic_operand" "")]
+	   UNSPEC_TLS_IE_X32))
+  	(match_operand:SWI1248x 1 "register_operand" "r"))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_X32"
+  "#"
+  ""
+  [(const_int 0)]
+  "ix86_split_tls_initial_exec_x32 (operands, <MODE>mode, FALSE); DONE;")
+
 ;; GNU2 TLS patterns can be split.
 
 (define_expand "tls_dynamic_gnu2_32"