[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