[PATCH] PR target/65846: Optimize data access in PIE with copy reloc
Ramana Radhakrishnan
ramana.gcc@googlemail.com
Wed Apr 22 22:16:00 GMT 2015
On Wed, Apr 22, 2015 at 5:34 PM, H.J. Lu <hongjiu.lu@intel.com> wrote:
> 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.
Looking at this my first reaction was that surely most (if not all ? )
targets that use ELF and had copy relocs would benefit from this ?
Couldn't we find a simpler way for targets to have this support ? I
don't have a more constructive suggestion to make at the minute but
getting this to work just from the targetm.binds_local_p (decl)
interface would probably be better ?
It's late in the evening and I probably won't have time to look at
this in more detail till Friday afternoon given other personal
commitments.
regards,
Ramana
>
> 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
>
More information about the Gcc-patches
mailing list