From 0925565205292f2d8ad5589805480af6cd8f35c6 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Sat, 10 Mar 2012 18:47:52 +0000 Subject: [PATCH] Properly generate x32 TLS IE sequence 2012-03-10 H.J. Lu * config/i386/i386.c (ix86_decompose_address): Disallow fs:(reg) if Pmode != word_mode. (legitimize_tls_address): Call gen_tls_initial_exec_x32 if Pmode == SImode for x32. * config/i386/i386.md (UNSPEC_TLS_IE_X32): New. (tls_initial_exec_x32): Likewise. From-SVN: r185179 --- gcc/ChangeLog | 10 ++++++++++ gcc/config/i386/i386.c | 16 ++++++++++++++++ gcc/config/i386/i386.md | 23 +++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b5e3b36ce76..8e5b4a9c742 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2012-03-10 H.J. Lu + + * config/i386/i386.c (ix86_decompose_address): Disallow fs:(reg) + if Pmode != word_mode. + (legitimize_tls_address): Call gen_tls_initial_exec_x32 if + Pmode == SImode for x32. + + * config/i386/i386.md (UNSPEC_TLS_IE_X32): New. + (tls_initial_exec_x32): Likewise. + 2012-03-10 Chung-Lin Tang PR rtl-optimization/52528 diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 567a41de70a..bc144a90cd3 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -11524,6 +11524,11 @@ ix86_decompose_address (rtx addr, struct ix86_address *out) 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)) @@ -12618,6 +12623,17 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov) emit_insn (gen_tls_initial_exec_64_sun (dest, x)); return dest; } + 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; + } pic = NULL; type = UNSPEC_GOTNTPOFF; diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index a4a7d3ab1b8..dcbfab43eee 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -96,6 +96,7 @@ UNSPEC_TLS_LD_BASE UNSPEC_TLSDESC UNSPEC_TLS_IE_SUN + UNSPEC_TLS_IE_X32 ;; Other random patterns UNSPEC_SCAS @@ -12777,6 +12778,28 @@ } [(set_attr "type" "multi")]) +;; When Pmode == SImode, there may be no REX prefix for ADD. Avoid +;; any instructions between MOV and ADD, which may interfere linker +;; IE->LE optimization, since the last byte of the previous instruction +;; before ADD may look like a REX prefix. This also avoids +;; movl x@gottpoff(%rip), %reg32 +;; movl $fs:(%reg32), %reg32 +;; Since address override works only on the (reg32) part in fs:(reg32), +;; we can't use it as memory operand. +(define_insn "tls_initial_exec_x32" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI + [(match_operand:SI 1 "tls_symbolic_operand" "")] + UNSPEC_TLS_IE_X32)) + (clobber (reg:CC FLAGS_REG))] + "TARGET_X32" +{ + output_asm_insn + ("mov{l}\t{%%fs:0, %0|%0, DWORD PTR fs:0}", operands); + return "add{l}\t{%a1@gottpoff(%%rip), %0|%0, %a1@gottpoff[rip]}"; +} + [(set_attr "type" "multi")]) + ;; GNU2 TLS patterns can be split. (define_expand "tls_dynamic_gnu2_32" -- 2.30.2