This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] PR target/65846: Optimize data access in PIE with copy reloc


Normally, with PIE, GCC accesses globals that are extern to the module
using GOT.  This is two instructions, one to get the address of the global
from GOT and the other to get the value.  Examples:

---
extern int a_glob;
int
main ()
{
  return a_glob;
}
---

With PIE, the generated code accesses global via GOT using two memory
loads:

	movq	a_glob@GOTPCREL(%rip), %rax
	movl	(%rax), %eax

for 64-bit or

	movl	a_glob@GOT(%ecx), %eax
	movl	(%eax), %eax

for 32-bit.

Some experiments on google and SPEC CPU benchmarks show that the extra
instruction affects performance by 1% to 5%.

Solution - Copy Relocations:

When the linker supports copy relocations, GCC can always assume that
the global will be defined in the executable.  For globals that are
truly extern (come from shared objects), the linker will create copy
relocations and have them defined in the executable.  Result is that
no global access needs to go through GOT and hence improves performance.
We can generate

	movl	a_glob(%rip), %eax

for 64-bit and

	movl	a_glob@GOTOFF(%eax), %eax

for 32-bit.  This optimization only applies to undefined non-weak
non-TLS global data.  Undefined weak global or TLS data access still
must go through GOT.

This patch reverts legitimate_pic_address_disp_p change made in revision
218397, which only applies to x86-64.  Instead, this patch updates
targetm.binds_local_p to indicate if undefined non-weak non-TLS global
data is defined locally in PIE.  It also introduces a new target hook,
binds_tls_local_p to distinguish TLS variable from non-TLS variable.  By
default, binds_tls_local_p is the same as binds_local_p.

This patch checks if 32-bit and 64-bit linkers support PIE with copy
reloc at configure time.  64-bit linker is enabled in binutils 2.25
and 32-bit linker is enabled in binutils 2.26.  This optimization
is enabled only if the linker support is available.

Tested on Linux/x86-64 with -m32 and -m64, using linkers with and without
support for copy relocation in PIE.  OK for trunk?

Thanks.

H.J.
---
gcc/

	PR target/65846
	* configure.ac (HAVE_LD_PIE_COPYRELOC): Renamed to ...
	(HAVE_LD_64BIT_PIE_COPYRELOC): This.
	(HAVE_LD_32BIT_PIE_COPYRELOC): New.   Defined to 1 if Linux/ia32
	linker supports PIE with copy reloc.
	* output.h (default_binds_tls_local_p): New.
	(default_binds_local_p_3): Add 2 bool arguments.
	* target.def (binds_tls_local_p): New target hook.
	* varasm.c (decl_default_tls_model): Replace targetm.binds_local_p
	with targetm.binds_tls_local_p.
	(default_binds_local_p_3): Add a bool argument to indicate TLS
	variable and a bool argument to indicate if an undefined non-TLS
	non-weak data is local.  Double check TLS variable.  If an
	undefined non-TLS non-weak data is local, treat it as defined
	locally.
	(default_binds_local_p): Pass false and false to
	default_binds_local_p_3.
	(default_binds_local_p_2): Likewise.
	(default_binds_local_p_1): Likewise.
	(default_binds_tls_local_p): New.
	* config.in: Regenerated.
	* configure: Likewise.
	* doc/tm.texi: Likewise.
	* config/i386/i386.c (legitimate_pic_address_disp_p): Don't
	check HAVE_LD_PIE_COPYRELOC here.
	(ix86_binds_local): New.
	(ix86_binds_tls_local_p): Likewise.
	(ix86_binds_local_p): Use it.
	(TARGET_BINDS_TLS_LOCAL_P): New.
	* doc/tm.texi.in (TARGET_BINDS_TLS_LOCAL_P): New hook.

gcc/testsuite/

	PR target/65846
	* gcc.target/i386/pie-copyrelocs-1.c: Updated for ia32.
	* gcc.target/i386/pie-copyrelocs-2.c: Likewise.
	* gcc.target/i386/pie-copyrelocs-3.c: Likewise.
	* gcc.target/i386/pie-copyrelocs-4.c: Likewise.
	* gcc.target/i386/pr32219-9.c: Likewise.
	* gcc.target/i386/pr32219-10.c: New file.

	* lib/target-supports.exp (check_effective_target_pie_copyreloc):
	Check HAVE_LD_64BIT_PIE_COPYRELOC and HAVE_LD_32BIT_PIE_COPYRELOC
	instead of HAVE_LD_64BIT_PIE_COPYRELOC.
---
 gcc/config.in                                    | 18 ++++---
 gcc/config/i386/i386.c                           | 44 ++++++++++-----
 gcc/configure                                    | 68 +++++++++++++++++++++---
 gcc/configure.ac                                 | 64 +++++++++++++++++++---
 gcc/doc/tm.texi                                  | 10 ++++
 gcc/doc/tm.texi.in                               |  2 +
 gcc/output.h                                     |  4 +-
 gcc/target.def                                   | 14 +++++
 gcc/testsuite/gcc.target/i386/pie-copyrelocs-1.c |  4 +-
 gcc/testsuite/gcc.target/i386/pie-copyrelocs-2.c |  4 +-
 gcc/testsuite/gcc.target/i386/pie-copyrelocs-3.c |  2 +-
 gcc/testsuite/gcc.target/i386/pie-copyrelocs-4.c |  4 +-
 gcc/testsuite/gcc.target/i386/pr32219-10.c       | 16 ++++++
 gcc/testsuite/gcc.target/i386/pr32219-9.c        |  2 +
 gcc/testsuite/lib/target-supports.exp            | 10 +++-
 gcc/varasm.c                                     | 47 ++++++++++++----
 16 files changed, 261 insertions(+), 52 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-10.c

diff --git a/gcc/config.in b/gcc/config.in
index f2ed301..a8ea34d 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -1349,6 +1349,18 @@
 #endif
 
 
+/* Define 0/1 if your 32-bit linker supports -pie option with copy reloc. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_32BIT_PIE_COPYRELOC
+#endif
+
+
+/* Define 0/1 if your 64-bit linker supports -pie option with copy reloc. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_64BIT_PIE_COPYRELOC
+#endif
+
+
 /* Define if your linker supports --as-needed/--no-as-needed or equivalent
    options. */
 #ifndef USED_FOR_TARGET
@@ -1429,12 +1441,6 @@
 #endif
 
 
-/* Define 0/1 if your linker supports -pie option with copy reloc. */
-#ifndef USED_FOR_TARGET
-#undef HAVE_LD_PIE_COPYRELOC
-#endif
-
-
 /* Define if your linker links a mix of read-only and read-write sections into
    a read-write section. */
 #ifndef USED_FOR_TARGET
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index bdc3652..eb9b27f 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -13231,11 +13231,7 @@ legitimate_pic_address_disp_p (rtx disp)
 		return true;
 	    }
 	  else if (!SYMBOL_REF_FAR_ADDR_P (op0)
-		   && (SYMBOL_REF_LOCAL_P (op0)
-		       || (HAVE_LD_PIE_COPYRELOC
-			   && flag_pie
-			   && !SYMBOL_REF_WEAK (op0)
-			   && !SYMBOL_REF_FUNCTION_P (op0)))
+		   && SYMBOL_REF_LOCAL_P (op0)
 		   && ix86_cmodel != CM_LARGE_PIC)
 	    return true;
 	  break;
@@ -51712,17 +51708,39 @@ ix86_initialize_bounds (tree var, tree lb, tree ub, tree *stmts)
 }
 
 #if !TARGET_MACHO && !TARGET_DLLIMPORT_DECL_ATTRIBUTES
-/* For i386, common symbol is local only for non-PIE binaries.  For
-   x86-64, common symbol is local only for non-PIE binaries or linker
-   supports copy reloc in PIE binaries.   */
+/* Common and undefined, non-TLS, non-weak data symbols are local
+   only for non-PIE binaries or linker supports copy reloc in PIE
+   binaries.  */
+
+static bool
+ix86_binds_local (const_tree exp, bool tls)
+{
+  bool local_p;
+  if (!flag_pic)
+    local_p = true;
+  else if (flag_pie)
+    {
+      if (TARGET_64BIT)
+	local_p = HAVE_LD_64BIT_PIE_COPYRELOC != 0;
+      else
+	local_p = HAVE_LD_32BIT_PIE_COPYRELOC != 0;
+    }
+  else
+    local_p = false;
+  return default_binds_local_p_3 (exp, tls, flag_shlib != 0, true,
+				  true, local_p, local_p);
+}
 
 static bool
 ix86_binds_local_p (const_tree exp)
 {
-  return default_binds_local_p_3 (exp, flag_shlib != 0, true, true,
-				  (!flag_pic
-				   || (TARGET_64BIT
-				       && HAVE_LD_PIE_COPYRELOC != 0)));
+  return ix86_binds_local (exp, false);
+}
+
+static bool
+ix86_binds_tls_local_p (const_tree exp)
+{
+  return ix86_binds_local (exp, true);
 }
 #endif
 
@@ -51861,6 +51879,8 @@ ix86_binds_local_p (const_tree exp)
 #else
 #undef TARGET_BINDS_LOCAL_P
 #define TARGET_BINDS_LOCAL_P ix86_binds_local_p
+#undef TARGET_BINDS_TLS_LOCAL_P
+#define TARGET_BINDS_TLS_LOCAL_P ix86_binds_tls_local_p
 #endif
 #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
 #undef TARGET_BINDS_LOCAL_P
diff --git a/gcc/configure b/gcc/configure
index 9523773..9566d71 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -27095,13 +27095,13 @@ fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_pie" >&5
 $as_echo "$gcc_cv_ld_pie" >&6; }
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker PIE support with copy reloc" >&5
-$as_echo_n "checking linker PIE support with copy reloc... " >&6; }
-gcc_cv_ld_pie_copyreloc=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking 64-bit linker PIE support with copy reloc" >&5
+$as_echo_n "checking 64-bit linker PIE support with copy reloc... " >&6; }
+gcc_cv_ld_64bit_pie_copyreloc=no
 if test $gcc_cv_ld_pie = yes ; then
   if test $in_tree_ld = yes ; then
     if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 25 -o "$gcc_cv_gld_major_version" -gt 2; then
-      gcc_cv_ld_pie_copyreloc=yes
+      gcc_cv_ld_64bit_pie_copyreloc=yes
     fi
   elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then
     # Check if linker supports -pie option with copy reloc
@@ -27132,7 +27132,7 @@ EOF
          && $gcc_cv_ld -shared -melf_x86_64 -o conftest1.so conftest1.o > /dev/null 2>&1 \
          && $gcc_cv_as --64 -o conftest2.o conftest2.s > /dev/null 2>&1 \
          && $gcc_cv_ld -pie -melf_x86_64 -o conftest conftest2.o conftest1.so > /dev/null 2>&1; then
-        gcc_cv_ld_pie_copyreloc=yes
+        gcc_cv_ld_64bit_pie_copyreloc=yes
       fi
       rm -f conftest conftest1.so conftest1.o conftest2.o conftest1.s conftest2.s
       ;;
@@ -27141,11 +27141,63 @@ EOF
 fi
 
 cat >>confdefs.h <<_ACEOF
-#define HAVE_LD_PIE_COPYRELOC `if test x"$gcc_cv_ld_pie_copyreloc" = xyes; then echo 1; else echo 0; fi`
+#define HAVE_LD_64BIT_PIE_COPYRELOC `if test x"$gcc_cv_ld_64bit_pie_copyreloc" = xyes; then echo 1; else echo 0; fi`
 _ACEOF
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_pie_copyreloc" >&5
-$as_echo "$gcc_cv_ld_pie_copyreloc" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_64bit_pie_copyreloc" >&5
+$as_echo "$gcc_cv_ld_64bit_pie_copyreloc" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking 32-bit linker PIE support with copy reloc" >&5
+$as_echo_n "checking 32-bit linker PIE support with copy reloc... " >&6; }
+gcc_cv_ld_32bit_pie_copyreloc=no
+if test $gcc_cv_ld_pie = yes ; then
+  if test $in_tree_ld = yes ; then
+    if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 26 -o "$gcc_cv_gld_major_version" -gt 2; then
+      gcc_cv_ld_32bit_pie_copyreloc=yes
+    fi
+  elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then
+    # Check if linker supports -pie option with copy reloc
+    case "$target" in
+    i?86-*-linux* | x86_64-*-linux*)
+      cat > conftest1.s <<EOF
+	.globl	a_glob
+	.data
+	.type	a_glob, @object
+	.size	a_glob, 4
+a_glob:
+	.long	2
+EOF
+      cat > conftest2.s <<EOF
+	.text
+	.globl	main
+	.type	main, @function
+main:
+	movl	a_glob@GOTOFF(%ebx), %eax
+	.size	main, .-main
+	.globl	ptr
+	.section	.data.rel,"aw",@progbits
+	.type	ptr, @object
+ptr:
+	.long	a_glob
+EOF
+      if $gcc_cv_as --32 -o conftest1.o conftest1.s > /dev/null 2>&1 \
+         && $gcc_cv_ld -shared -melf_i386 -o conftest1.so conftest1.o > /dev/null 2>&1 \
+         && $gcc_cv_as --32 -o conftest2.o conftest2.s > /dev/null 2>&1 \
+         && $gcc_cv_ld -pie -melf_i386 -o conftest conftest2.o conftest1.so > /dev/null 2>&1; then
+        gcc_cv_ld_32bit_pie_copyreloc=yes
+      fi
+      rm -f conftest conftest1.so conftest1.o conftest2.o conftest1.s conftest2.s
+      ;;
+    esac
+  fi
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LD_32BIT_PIE_COPYRELOC `if test x"$gcc_cv_ld_32bit_pie_copyreloc" = xyes; then echo 1; else echo 0; fi`
+_ACEOF
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_32bit_pie_copyreloc" >&5
+$as_echo "$gcc_cv_ld_32bit_pie_copyreloc" >&6; }
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker EH-compatible garbage collection of sections" >&5
 $as_echo_n "checking linker EH-compatible garbage collection of sections... " >&6; }
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 68b0ee8..53adc4b 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -4705,12 +4705,12 @@ if test x"$gcc_cv_ld_pie" = xyes; then
 fi
 AC_MSG_RESULT($gcc_cv_ld_pie)
 
-AC_MSG_CHECKING(linker PIE support with copy reloc)
-gcc_cv_ld_pie_copyreloc=no
+AC_MSG_CHECKING(64-bit linker PIE support with copy reloc)
+gcc_cv_ld_64bit_pie_copyreloc=no
 if test $gcc_cv_ld_pie = yes ; then
   if test $in_tree_ld = yes ; then
     if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 25 -o "$gcc_cv_gld_major_version" -gt 2; then
-      gcc_cv_ld_pie_copyreloc=yes
+      gcc_cv_ld_64bit_pie_copyreloc=yes
     fi
   elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then
     # Check if linker supports -pie option with copy reloc
@@ -4741,17 +4741,65 @@ EOF
          && $gcc_cv_ld -shared -melf_x86_64 -o conftest1.so conftest1.o > /dev/null 2>&1 \
          && $gcc_cv_as --64 -o conftest2.o conftest2.s > /dev/null 2>&1 \
          && $gcc_cv_ld -pie -melf_x86_64 -o conftest conftest2.o conftest1.so > /dev/null 2>&1; then
-        gcc_cv_ld_pie_copyreloc=yes
+        gcc_cv_ld_64bit_pie_copyreloc=yes
       fi
       rm -f conftest conftest1.so conftest1.o conftest2.o conftest1.s conftest2.s
       ;;
     esac
   fi
 fi
-AC_DEFINE_UNQUOTED(HAVE_LD_PIE_COPYRELOC,
-  [`if test x"$gcc_cv_ld_pie_copyreloc" = xyes; then echo 1; else echo 0; fi`],
-  [Define 0/1 if your linker supports -pie option with copy reloc.])
-AC_MSG_RESULT($gcc_cv_ld_pie_copyreloc)
+AC_DEFINE_UNQUOTED(HAVE_LD_64BIT_PIE_COPYRELOC,
+  [`if test x"$gcc_cv_ld_64bit_pie_copyreloc" = xyes; then echo 1; else echo 0; fi`],
+  [Define 0/1 if your 64-bit linker supports -pie option with copy reloc.])
+AC_MSG_RESULT($gcc_cv_ld_64bit_pie_copyreloc)
+
+AC_MSG_CHECKING(32-bit linker PIE support with copy reloc)
+gcc_cv_ld_32bit_pie_copyreloc=no
+if test $gcc_cv_ld_pie = yes ; then
+  if test $in_tree_ld = yes ; then
+    if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 26 -o "$gcc_cv_gld_major_version" -gt 2; then
+      gcc_cv_ld_32bit_pie_copyreloc=yes
+    fi
+  elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then
+    # Check if linker supports -pie option with copy reloc
+    case "$target" in
+    i?86-*-linux* | x86_64-*-linux*)
+      cat > conftest1.s <<EOF
+	.globl	a_glob
+	.data
+	.type	a_glob, @object
+	.size	a_glob, 4
+a_glob:
+	.long	2
+EOF
+      cat > conftest2.s <<EOF
+	.text
+	.globl	main
+	.type	main, @function
+main:
+	movl	a_glob@GOTOFF(%ebx), %eax
+	.size	main, .-main
+	.globl	ptr
+	.section	.data.rel,"aw",@progbits
+	.type	ptr, @object
+ptr:
+	.long	a_glob
+EOF
+      if $gcc_cv_as --32 -o conftest1.o conftest1.s > /dev/null 2>&1 \
+         && $gcc_cv_ld -shared -melf_i386 -o conftest1.so conftest1.o > /dev/null 2>&1 \
+         && $gcc_cv_as --32 -o conftest2.o conftest2.s > /dev/null 2>&1 \
+         && $gcc_cv_ld -pie -melf_i386 -o conftest conftest2.o conftest1.so > /dev/null 2>&1; then
+        gcc_cv_ld_32bit_pie_copyreloc=yes
+      fi
+      rm -f conftest conftest1.so conftest1.o conftest2.o conftest1.s conftest2.s
+      ;;
+    esac
+  fi
+fi
+AC_DEFINE_UNQUOTED(HAVE_LD_32BIT_PIE_COPYRELOC,
+  [`if test x"$gcc_cv_ld_32bit_pie_copyreloc" = xyes; then echo 1; else echo 0; fi`],
+  [Define 0/1 if your 32-bit linker supports -pie option with copy reloc.])
+AC_MSG_RESULT($gcc_cv_ld_32bit_pie_copyreloc)
 
 AC_MSG_CHECKING(linker EH-compatible garbage collection of sections)
 gcc_cv_ld_eh_gc_sections=no
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 6c5bfab..5a73c8a 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -7219,6 +7219,16 @@ for ELF, which has a looser model of global name binding than other
 currently supported object file formats.
 @end deftypefn
 
+@deftypefn {Target Hook} bool TARGET_BINDS_TLS_LOCAL_P (const_tree @var{exp})
+Returns true if TLS variable @var{exp} names an object for which name
+resolution rules must resolve to the current ``module'' (dynamic shared
+library or executable image).
+
+The default version of this hook implements the name resolution rules
+for ELF, which has a looser model of global name binding than other
+currently supported object file formats.
+@end deftypefn
+
 @deftypevr {Target Hook} bool TARGET_HAVE_TLS
 Contains the value true if the target supports thread-local storage.
 The default value is false.
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 8d6dfbc..c0316be 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -5034,6 +5034,8 @@ it is unlikely to be called.
 
 @hook TARGET_BINDS_LOCAL_P
 
+@hook TARGET_BINDS_TLS_LOCAL_P
+
 @hook TARGET_HAVE_TLS
 
 
diff --git a/gcc/output.h b/gcc/output.h
index 81d2ad2..52e094c 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -585,9 +585,11 @@ extern const char *default_strip_name_encoding (const char *);
 extern void default_asm_output_anchor (rtx);
 extern bool default_use_anchors_for_symbol_p (const_rtx);
 extern bool default_binds_local_p (const_tree);
+extern bool default_binds_tls_local_p (const_tree);
 extern bool default_binds_local_p_1 (const_tree, int);
 extern bool default_binds_local_p_2 (const_tree);
-extern bool default_binds_local_p_3 (const_tree, bool, bool, bool, bool);
+extern bool default_binds_local_p_3 (const_tree, bool, bool, bool, bool,
+				     bool, bool);
 extern void default_globalize_label (FILE *, const char *);
 extern void default_globalize_decl_name (FILE *, tree);
 extern void default_emit_unwind_label (FILE *, tree, int, int);
diff --git a/gcc/target.def b/gcc/target.def
index a00181a..4a3e0d9 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -2891,6 +2891,20 @@ currently supported object file formats.",
  bool, (const_tree exp),
  default_binds_local_p)
 
+/* True if TLS variable EXP names an object for which name resolution must
+   resolve to the current executable or shared library.  */
+DEFHOOK
+(binds_tls_local_p,
+ "Returns true if TLS variable @var{exp} names an object for which name\n\
+resolution rules must resolve to the current ``module'' (dynamic shared\n\
+library or executable image).\n\
+\n\
+The default version of this hook implements the name resolution rules\n\
+for ELF, which has a looser model of global name binding than other\n\
+currently supported object file formats.",
+ bool, (const_tree exp),
+ default_binds_tls_local_p)
+
 /* Check if profiling code is before or after prologue.  */
 DEFHOOK
 (profile_before_prologue,
diff --git a/gcc/testsuite/gcc.target/i386/pie-copyrelocs-1.c b/gcc/testsuite/gcc.target/i386/pie-copyrelocs-1.c
index 7af851b..69e3f6e 100644
--- a/gcc/testsuite/gcc.target/i386/pie-copyrelocs-1.c
+++ b/gcc/testsuite/gcc.target/i386/pie-copyrelocs-1.c
@@ -1,4 +1,4 @@
-/* Check that GOTPCREL isn't used to access glob_a.  */
+/* Check that GOTPCREL/GOT isn't used to access glob_a.  */
 /* { dg-do compile { target *-*-linux* } } */
 /* { dg-require-effective-target pie_copyreloc } */
 /* { dg-options "-O2 -fpie" } */
@@ -12,3 +12,5 @@ int foo ()
 
 /* glob_a should never be accessed with a GOTPCREL.  */
 /* { dg-final { scan-assembler-not "glob_a@GOTPCREL" { target { ! ia32 } } } } */
+/* glob_a should never be accessed with a GOT.  */
+/* { dg-final { scan-assembler-not "glob_a@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pie-copyrelocs-2.c b/gcc/testsuite/gcc.target/i386/pie-copyrelocs-2.c
index 19cb97e..eb0724b 100644
--- a/gcc/testsuite/gcc.target/i386/pie-copyrelocs-2.c
+++ b/gcc/testsuite/gcc.target/i386/pie-copyrelocs-2.c
@@ -1,4 +1,4 @@
-/* Check that GOTPCREL isn't used to access glob_a.  */
+/* Check that GOTPCREL/GOT isn't used to access glob_a.  */
 /* { dg-do compile { target *-*-linux* } } */
 /* { dg-require-effective-target pie_copyreloc } */
 /* { dg-options "-O2 -fpie" } */
@@ -12,3 +12,5 @@ int foo ()
 
 /* glob_a should never be accessed with a GOTPCREL.  */
 /* { dg-final { scan-assembler-not "glob_a@GOTPCREL" { target { ! ia32 } } } } */
+/* glob_a should never be accessed with a GOT.  */
+/* { dg-final { scan-assembler-not "glob_a@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pie-copyrelocs-3.c b/gcc/testsuite/gcc.target/i386/pie-copyrelocs-3.c
index c2fa896..1123bd8 100644
--- a/gcc/testsuite/gcc.target/i386/pie-copyrelocs-3.c
+++ b/gcc/testsuite/gcc.target/i386/pie-copyrelocs-3.c
@@ -11,4 +11,4 @@ int foo ()
 }
 
 /* glob_a should be accessed with a PLT.  */
-/* { dg-final { scan-assembler "glob_a@PLT" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "glob_a@PLT" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pie-copyrelocs-4.c b/gcc/testsuite/gcc.target/i386/pie-copyrelocs-4.c
index 413cdf3..4724ede 100644
--- a/gcc/testsuite/gcc.target/i386/pie-copyrelocs-4.c
+++ b/gcc/testsuite/gcc.target/i386/pie-copyrelocs-4.c
@@ -1,4 +1,4 @@
-/* Check that GOTPCREL is used to access glob_a.  */
+/* Check that GOTPCREL/GOT is used to access glob_a.  */
 /* { dg-do compile { target *-*-linux* } } */
 /* { dg-require-effective-target pie_copyreloc } */
 /* { dg-options "-O2 -fpie" } */
@@ -15,3 +15,5 @@ int foo ()
 
 /* weak glob_a should be accessed with a GOTPCREL.  */
 /* { dg-final { scan-assembler "glob_a@GOTPCREL" { target { ! ia32 } } } } */
+/* weak glob_a should be accessed with a GOT.  */
+/* { dg-final { scan-assembler "glob_a@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-10.c b/gcc/testsuite/gcc.target/i386/pr32219-10.c
new file mode 100644
index 0000000..3cd95f0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr32219-10.c
@@ -0,0 +1,16 @@
+/* Check that tpoff/ntpoff isn't used to access glob_a.  */
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-require-effective-target pie } */
+/* { dg-options "-O2 -fpie" } */
+
+extern __thread int glob_a;
+
+int foo ()
+{
+  return glob_a;
+}
+
+/* glob_a should never be accessed with a tpoff.  */
+/* { dg-final { scan-assembler-not "glob_a@tpoff" { target { ! ia32 } } } } */
+/* glob_a should never be accessed with a ntpoff.  */
+/* { dg-final { scan-assembler-not "glob_a@ntpoff" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-9.c b/gcc/testsuite/gcc.target/i386/pr32219-9.c
index 8c21826..77330be 100644
--- a/gcc/testsuite/gcc.target/i386/pr32219-9.c
+++ b/gcc/testsuite/gcc.target/i386/pr32219-9.c
@@ -13,3 +13,5 @@ foo ()
 
 /* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
 /* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "xxx@GOTOFF" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "xxx@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index f632d00..153024d 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -6220,8 +6220,14 @@ proc check_effective_target_pie_copyreloc { } {
 
 	set f [open $src "w"]
 	puts $f "#include \"../../auto-host.h\""
-	puts $f "#if HAVE_LD_PIE_COPYRELOC == 0"
-	puts $f "# error Linker does not support PIE with copy reloc."
+	puts $f "#ifdef __x86_64__"
+	puts $f "# if HAVE_LD_64BIT_PIE_COPYRELOC == 0"
+	puts $f "#  error 64-bit linker does not support PIE with copy reloc."
+	puts $f "# endif"
+	puts $f "#else"
+	puts $f "# if HAVE_LD_32BIT_PIE_COPYRELOC == 0"
+	puts $f "#  error 32-bit linker does not support PIE with copy reloc."
+	puts $f "# endif"
 	puts $f "#endif"
 	close $f
 
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 1597de1..ef78995 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -6115,7 +6115,7 @@ decl_default_tls_model (const_tree decl)
   enum tls_model kind;
   bool is_local;
 
-  is_local = targetm.binds_local_p (decl);
+  is_local = targetm.binds_tls_local_p (decl);
   if (!flag_shlib)
     {
       if (is_local)
@@ -6809,11 +6809,15 @@ resolution_local_p (enum ld_plugin_symbol_resolution resolution)
 
 /* COMMON_LOCAL_P is true means that the linker can guarantee that an
    uninitialized common symbol in the executable will still be defined
-   (through COPY relocation) in the executable.  */
+   (through COPY relocation) in the executable.  DATA_LOCAL_P is true
+   means that the linker can guarantee that undefined, non-TLS, non-weak
+   data in the executable will still be defined (through COPY relocation)
+   in the executable.  */
 
 bool
-default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate,
-			 bool extern_protected_data, bool common_local_p)
+default_binds_local_p_3 (const_tree exp, bool tls, bool shlib,
+			 bool weak_dominate, bool extern_protected_data,
+			 bool common_local_p, bool data_local_p)
 {
   /* A non-decl is an entry in the constant pool.  */
   if (!DECL_P (exp))
@@ -6844,10 +6848,21 @@ default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate,
 			      || (!in_lto_p
 				  && DECL_INITIAL (exp) == error_mark_node)));
 
+  /* If TLS is false, double check if EXP is a TLS variable.  */
+  if (!tls)
+    tls = TREE_CODE (exp) == VAR_DECL && DECL_THREAD_LOCAL_P (exp);
+
   /* A non-external variable is defined locally only if it isn't
-     uninitialized COMMON variable or common_local_p is true.  */
-  bool defined_locally = (!DECL_EXTERNAL (exp)
-			  && (!uninited_common || common_local_p));
+     uninitialized COMMON variable or common_local_p is true.  A
+     undefined data variable is defined locally only if it isn't
+     weak nor a TLS variable and linker can guarantee it will be
+     defined locally.  */
+  bool defined_locally = ((!tls
+			   && TREE_CODE (exp) != FUNCTION_DECL
+			   && !DECL_WEAK (exp)
+			   && data_local_p)
+			  || (!DECL_EXTERNAL (exp)
+			      && (!uninited_common || common_local_p)));
   if (symtab_node *node = symtab_node::get (exp))
     {
       if (node->in_other_partition)
@@ -6903,7 +6918,16 @@ default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate,
 bool
 default_binds_local_p (const_tree exp)
 {
-  return default_binds_local_p_3 (exp, flag_shlib != 0, true, false, false);
+  return default_binds_local_p_3 (exp, false, flag_shlib != 0, true,
+				  false, false, false);
+}
+
+/* Similar to default_binds_local_p, but for TLS variable.  */
+
+bool
+default_binds_tls_local_p (const_tree exp)
+{
+  return targetm.binds_local_p (exp);
 }
 
 /* Similar to default_binds_local_p, but common symbol may be local.  */
@@ -6911,14 +6935,15 @@ default_binds_local_p (const_tree exp)
 bool
 default_binds_local_p_2 (const_tree exp)
 {
-  return default_binds_local_p_3 (exp, flag_shlib != 0, true, false,
-				  !flag_pic);
+  return default_binds_local_p_3 (exp, false, flag_shlib != 0, true,
+				  false, !flag_pic, false);
 }
 
 bool
 default_binds_local_p_1 (const_tree exp, int shlib)
 {
-  return default_binds_local_p_3 (exp, shlib != 0, false, false, false);
+  return default_binds_local_p_3 (exp, false, shlib != 0, false, false,
+				  false, false);
 }
 
 /* Return true when references to DECL must bind to current definition in
-- 
1.9.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]