Hello,

the ppc64 linker performs an optimization to avoid multi-instruction
TOC accesses in some cases:

      /* Multi-instruction sequences that access the TOC can be
         optimized, eg. addis ra,r2,0; addi rb,ra,x;
         to             nop;           addi rb,r2,x;  */

For this optimization to be valid, the TOC register r2 has to be live
at the point of the second instruction (addi rb,ra,x), even though
this instruction -on its face- does not use r2.  It is apparently
the responsibility of the compiler to keep r2 live at this point
on any such instruction (identified by using some low-part TOC 
relocation).

There is code in rs6000.md that does this for "normal" accesses to
variables in the TOC.  However, code that accesses TLS-related
information in the TOC (GOT_TLSGD and friends) does *not* ensure
r2 is live.

This usually doesn't matter because r2 tends to live across the
whole function anyway.  However, in the context of some out-of-tree
patches I ran into a situation where this caused a bug.  Since it
would probably be theoretically possible to run into this issue
even with mainline GCC (and in any case fixing the problem doesn't
have any drawbacks), I'd suggest to fix this on mainline.

This patch adds an extra operand to the UNSPEC operands of the
TLS-related lo_sum patterns, used to enforce keeping the TOC
register live.

Tested with no regressions on powerpc64-linux.

OK for mainline?

Bye,
Ulrich


ChangeLog:

        * config/rs6000/rs6000.md (""*tls_gd_low<TLSmode:tls_abi_suffix>"):
        Require GOT register as additional operand in UNSPEC.
        ("*tls_ld_low<TLSmode:tls_abi_suffix>"): Likewise.
        ("*tls_got_dtprel_low<TLSmode:tls_abi_suffix>"): Likewise.
        ("*tls_got_tprel_low<TLSmode:tls_abi_suffix>"): Likewise.
        ("*tls_gd<TLSmode:tls_abi_suffix>"): Update splitter.
        ("*tls_ld<TLSmode:tls_abi_suffix>"): Likewise.
        ("tls_got_dtprel_<TLSmode:tls_abi_suffix>"): Likewise.
        ("tls_got_tprel_<TLSmode:tls_abi_suffix>"): Likewise.

Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md (revision 200784)
+++ gcc/config/rs6000/rs6000.md (working copy)
@@ -10989,7 +10989,7 @@
            (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGD)))
    (set (match_dup 0)
        (lo_sum:TLSmode (match_dup 3)
-           (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGD)))]
+           (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGD)))]
   "
 {
   operands[3] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode);
@@ -11012,7 +11012,8 @@
 (define_insn "*tls_gd_low<TLSmode:tls_abi_suffix>"
   [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
      (lo_sum:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
-       (unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
+       (unspec:TLSmode [(match_operand:TLSmode 3 "gpc_reg_operand" "b")
+                       (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
                       UNSPEC_TLSGD)))]
   "HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
   "addi %0,%1,%2@got@tlsgd@l"
@@ -11124,7 +11125,7 @@
            (unspec:TLSmode [(const_int 0) (match_dup 1)] UNSPEC_TLSLD)))
    (set (match_dup 0)
        (lo_sum:TLSmode (match_dup 2)
-           (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)))]
+           (unspec:TLSmode [(const_int 0) (match_dup 1)] UNSPEC_TLSLD)))]
   "
 {
   operands[2] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode);
@@ -11147,7 +11148,9 @@
 (define_insn "*tls_ld_low<TLSmode:tls_abi_suffix>"
   [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
      (lo_sum:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
-       (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)))]
+       (unspec:TLSmode [(const_int 0)
+                        (match_operand:TLSmode 2 "gpc_reg_operand" "b")]
+                       UNSPEC_TLSLD)))]
   "HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
   "addi %0,%1,%&@got@tlsld@l"
   [(set_attr "length" "4")])
@@ -11219,7 +11222,7 @@
            (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGOTDTPREL)))
    (set (match_dup 0)
        (lo_sum:TLSmode (match_dup 3)
-           (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTDTPREL)))]
+           (unspec:TLSmode [(match_dup 1) (match_dup 2)] 
UNSPEC_TLSGOTDTPREL)))]
   "
 {
   operands[3] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode);
@@ -11242,7 +11245,8 @@
 (define_insn "*tls_got_dtprel_low<TLSmode:tls_abi_suffix>"
   [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
      (lo_sum:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
-        (unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
+        (unspec:TLSmode [(match_operand:TLSmode 3 "gpc_reg_operand" "b")
+                         (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
                         UNSPEC_TLSGOTDTPREL)))]
   "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
   "l<TLSmode:tls_insn_suffix> %0,%2@got@dtprel@l(%1)"
@@ -11288,7 +11292,7 @@
            (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGOTTPREL)))
    (set (match_dup 0)
        (lo_sum:TLSmode (match_dup 3)
-           (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTTPREL)))]
+           (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGOTTPREL)))]
   "
 {
   operands[3] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode);
@@ -11311,7 +11315,8 @@
 (define_insn "*tls_got_tprel_low<TLSmode:tls_abi_suffix>"
   [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
      (lo_sum:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
-        (unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
+        (unspec:TLSmode [(match_operand:TLSmode 3 "gpc_reg_operand" "b")
+                         (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
                         UNSPEC_TLSGOTTPREL)))]
   "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
   "l<TLSmode:tls_insn_suffix> %0,%2@got@tprel@l(%1)"
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  ulrich.weig...@de.ibm.com

Reply via email to