]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Properly generate x32 TLS IE sequence
authorH.J. Lu <hongjiu.lu@intel.com>
Sat, 10 Mar 2012 18:47:52 +0000 (18:47 +0000)
committerH.J. Lu <hjl@gcc.gnu.org>
Sat, 10 Mar 2012 18:47:52 +0000 (10:47 -0800)
2012-03-10  H.J. Lu  <hongjiu.lu@intel.com>

* 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
gcc/config/i386/i386.c
gcc/config/i386/i386.md

index b5e3b36ce76a8a88948ac366ea4ede9e6ee76d8f..8e5b4a9c742b16382db81cd22ca5c19158ec8c28 100644 (file)
@@ -1,3 +1,13 @@
+2012-03-10  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * 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  <cltang@codesourcery.com>
 
        PR rtl-optimization/52528
index 567a41de70afee7ac182b4af634786e18a8920ca..bc144a90cd3b3566f74dc8ef867bff0475ae476b 100644 (file)
@@ -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;
index a4a7d3ab1b8d1cc270efa35f666278bb6ca6da75..dcbfab43eeead69a39bdb68c530f2271fd7a5aed 100644 (file)
@@ -96,6 +96,7 @@
   UNSPEC_TLS_LD_BASE
   UNSPEC_TLSDESC
   UNSPEC_TLS_IE_SUN
+  UNSPEC_TLS_IE_X32
 
   ;; Other random patterns
   UNSPEC_SCAS
 }
   [(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"