On Sat, Mar 17, 2012 at 11:20 AM, Uros Bizjak <ubiz...@gmail.com> wrote: > On Sat, Mar 17, 2012 at 7:18 PM, H.J. Lu <hjl.to...@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...@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. -- H.J.
2012-03-17 H.J. Lu <hongjiu...@intel.com> * config/i386/i386-protos.h (ix86_split_tls_initial_exec_x32): New. * config/i386/i386.c (ix86_split_tls_initial_exec_x32): Likewise. * config/i386/i386.md (*tls_initial_exec_x32_load): New. (*tls_initial_exec_x32_store): Likewise. 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"