diff mbox

PR rtl-optimization/32219: optimizer causees wrong code in pic/hidden/weak symbol checking

Message ID 54DC46BF.5060503@redhat.com
State New
Headers show

Commit Message

Richard Henderson Feb. 12, 2015, 6:22 a.m. UTC
On 02/10/2015 01:19 PM, Richard Henderson wrote:
> As an existing issue, I'm not sure why "specified" visibility is any different
> from unspecified visibility.  As far as I'm aware, the "specified" bit simply
> means that the decl doesn't inherit inherit visibility from the class, or from
> the command-line.  But once we're this far, the visibility actually applied to
> the symbol should be all that matters.

The test is there to differentiate explicit visibility from that implied from
the command-line.  Without it, we assume hidden visibility for external symbols
too early, making the command-line option useless.  This is visible even in
building libgcc.

I believe this set of patches does what we want, and cleans things up a bit in
the process.


r~

Comments

H.J. Lu Feb. 12, 2015, 6:16 p.m. UTC | #1
On Wed, Feb 11, 2015 at 10:22 PM, Richard Henderson <rth@redhat.com> wrote:
> On 02/10/2015 01:19 PM, Richard Henderson wrote:
>> As an existing issue, I'm not sure why "specified" visibility is any different
>> from unspecified visibility.  As far as I'm aware, the "specified" bit simply
>> means that the decl doesn't inherit inherit visibility from the class, or from
>> the command-line.  But once we're this far, the visibility actually applied to
>> the symbol should be all that matters.
>
> The test is there to differentiate explicit visibility from that implied from
> the command-line.  Without it, we assume hidden visibility for external symbols
> too early, making the command-line option useless.  This is visible even in
> building libgcc.
>
> I believe this set of patches does what we want, and cleans things up a bit in
> the process.
>
>

I tried them on Linux/x86-64.  They caused:

FAIL: g++.dg/gomp/tls-wrap4.C  -std=gnu++11  scan-assembler-not _ZTW1i@PLT
FAIL: g++.dg/gomp/tls-wrap4.C  -std=gnu++11  scan-assembler-not _ZTW1i@PLT
FAIL: g++.dg/gomp/tls-wrap4.C  -std=gnu++14  scan-assembler-not _ZTW1i@PLT
FAIL: g++.dg/gomp/tls-wrap4.C  -std=gnu++14  scan-assembler-not _ZTW1i@PLT
FAIL: g++.dg/tls/thread_local-wrap4.C  -std=gnu++11
scan-assembler-not _ZTW1i@PLT
FAIL: g++.dg/tls/thread_local-wrap4.C  -std=gnu++11
scan-assembler-not _ZTW1i@PLT
FAIL: g++.dg/tls/thread_local-wrap4.C  -std=gnu++14
scan-assembler-not _ZTW1i@PLT
FAIL: g++.dg/tls/thread_local-wrap4.C  -std=gnu++14
scan-assembler-not _ZTW1i@PLT
Jack Howarth Feb. 12, 2015, 7:16 p.m. UTC | #2
H.J.,
   Oddly I saw no regressions in the g++ test suite at -m32/-m64 on
x86_64-apple-darwin14.
           Jack

On Thu, Feb 12, 2015 at 1:16 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Wed, Feb 11, 2015 at 10:22 PM, Richard Henderson <rth@redhat.com> wrote:
>> On 02/10/2015 01:19 PM, Richard Henderson wrote:
>>> As an existing issue, I'm not sure why "specified" visibility is any different
>>> from unspecified visibility.  As far as I'm aware, the "specified" bit simply
>>> means that the decl doesn't inherit inherit visibility from the class, or from
>>> the command-line.  But once we're this far, the visibility actually applied to
>>> the symbol should be all that matters.
>>
>> The test is there to differentiate explicit visibility from that implied from
>> the command-line.  Without it, we assume hidden visibility for external symbols
>> too early, making the command-line option useless.  This is visible even in
>> building libgcc.
>>
>> I believe this set of patches does what we want, and cleans things up a bit in
>> the process.
>>
>>
>
> I tried them on Linux/x86-64.  They caused:
>
> FAIL: g++.dg/gomp/tls-wrap4.C  -std=gnu++11  scan-assembler-not _ZTW1i@PLT
> FAIL: g++.dg/gomp/tls-wrap4.C  -std=gnu++11  scan-assembler-not _ZTW1i@PLT
> FAIL: g++.dg/gomp/tls-wrap4.C  -std=gnu++14  scan-assembler-not _ZTW1i@PLT
> FAIL: g++.dg/gomp/tls-wrap4.C  -std=gnu++14  scan-assembler-not _ZTW1i@PLT
> FAIL: g++.dg/tls/thread_local-wrap4.C  -std=gnu++11
> scan-assembler-not _ZTW1i@PLT
> FAIL: g++.dg/tls/thread_local-wrap4.C  -std=gnu++11
> scan-assembler-not _ZTW1i@PLT
> FAIL: g++.dg/tls/thread_local-wrap4.C  -std=gnu++14
> scan-assembler-not _ZTW1i@PLT
> FAIL: g++.dg/tls/thread_local-wrap4.C  -std=gnu++14
> scan-assembler-not _ZTW1i@PLT
>
>
> --
> H.J.
H.J. Lu Feb. 12, 2015, 7:18 p.m. UTC | #3
On Thu, Feb 12, 2015 at 11:16 AM, Jack Howarth <howarth.at.gcc@gmail.com> wrote:
> H.J.,
>    Oddly I saw no regressions in the g++ test suite at -m32/-m64 on
> x86_64-apple-darwin14.
>            Jack

They have

// { dg-require-effective-target tls }

Does x86_64-apple-darwin14 support TLS?  If yes, what does the
generated assembly code look like?

> On Thu, Feb 12, 2015 at 1:16 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>> On Wed, Feb 11, 2015 at 10:22 PM, Richard Henderson <rth@redhat.com> wrote:
>>> On 02/10/2015 01:19 PM, Richard Henderson wrote:
>>>> As an existing issue, I'm not sure why "specified" visibility is any different
>>>> from unspecified visibility.  As far as I'm aware, the "specified" bit simply
>>>> means that the decl doesn't inherit inherit visibility from the class, or from
>>>> the command-line.  But once we're this far, the visibility actually applied to
>>>> the symbol should be all that matters.
>>>
>>> The test is there to differentiate explicit visibility from that implied from
>>> the command-line.  Without it, we assume hidden visibility for external symbols
>>> too early, making the command-line option useless.  This is visible even in
>>> building libgcc.
>>>
>>> I believe this set of patches does what we want, and cleans things up a bit in
>>> the process.
>>>
>>>
>>
>> I tried them on Linux/x86-64.  They caused:
>>
>> FAIL: g++.dg/gomp/tls-wrap4.C  -std=gnu++11  scan-assembler-not _ZTW1i@PLT
>> FAIL: g++.dg/gomp/tls-wrap4.C  -std=gnu++11  scan-assembler-not _ZTW1i@PLT
>> FAIL: g++.dg/gomp/tls-wrap4.C  -std=gnu++14  scan-assembler-not _ZTW1i@PLT
>> FAIL: g++.dg/gomp/tls-wrap4.C  -std=gnu++14  scan-assembler-not _ZTW1i@PLT
>> FAIL: g++.dg/tls/thread_local-wrap4.C  -std=gnu++11
>> scan-assembler-not _ZTW1i@PLT
>> FAIL: g++.dg/tls/thread_local-wrap4.C  -std=gnu++11
>> scan-assembler-not _ZTW1i@PLT
>> FAIL: g++.dg/tls/thread_local-wrap4.C  -std=gnu++14
>> scan-assembler-not _ZTW1i@PLT
>> FAIL: g++.dg/tls/thread_local-wrap4.C  -std=gnu++14
>> scan-assembler-not _ZTW1i@PLT
>>
>>
>> --
>> H.J.
Jack Howarth Feb. 12, 2015, 7:39 p.m. UTC | #4
On Thu, Feb 12, 2015 at 2:18 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Thu, Feb 12, 2015 at 11:16 AM, Jack Howarth <howarth.at.gcc@gmail.com> wrote:
>> H.J.,
>>    Oddly I saw no regressions in the g++ test suite at -m32/-m64 on
>> x86_64-apple-darwin14.
>>            Jack
>
> They have
>
> // { dg-require-effective-target tls }
>
> Does x86_64-apple-darwin14 support TLS?  If yes, what does the
> generated assembly code look like?

We use emutls on darwin. Those failing test are run at -m32/-m64...

Executing on host:
/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/testsuite/g++/../../xg++
-B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/testsuite/g++/../../
/sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150212/gcc/testsuite/g++.dg/gomp/tls-wrap4.C
 -fno-diagnostics-show-caret -fdiagnostics-color=never  -nostdinc++
-I/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/x86_64-apple-darwin13.4.0/libstdc++-v3/include/x86_64-apple-darwin13.4.0
-I/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/x86_64-apple-darwin13.4.0/libstdc++-v3/include
-I/sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150212/libstdc++-v3/libsupc++
-I/sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150212/libstdc++-v3/include/backward
-I/sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150212/libstdc++-v3/testsuite/util
-fmessage-length=0  -std=gnu++11 -fPIC  -S  -m64  -o tls-wrap4.s
(timeout = 300)
spawn -ignore SIGHUP
/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/testsuite/g++/../../xg++
-B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/testsuite/g++/../../
/sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150212/gcc/testsuite/g++.dg/gomp/tls-wrap4.C
-fno-diagnostics-show-caret -fdiagnostics-color=never -nostdinc++
-I/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/x86_64-apple-darwin13.4.0/libstdc++-v3/include/x86_64-apple-darwin13.4.0
-I/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/x86_64-apple-darwin13.4.0/libstdc++-v3/include
-I/sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150212/libstdc++-v3/libsupc++
-I/sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150212/libstdc++-v3/include/backward
-I/sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150212/libstdc++-v3/testsuite/util
-fmessage-length=0 -std=gnu++11 -fPIC -S -m64 -o tls-wrap4.s^M
PASS: g++.dg/gomp/tls-wrap4.C  -std=gnu++11 (test for excess errors)
PASS: g++.dg/gomp/tls-wrap4.C  -std=gnu++11  scan-assembler-not _ZTW1i@PLT

and produce the attached assembly.
                Jack

>
>> On Thu, Feb 12, 2015 at 1:16 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>>> On Wed, Feb 11, 2015 at 10:22 PM, Richard Henderson <rth@redhat.com> wrote:
>>>> On 02/10/2015 01:19 PM, Richard Henderson wrote:
>>>>> As an existing issue, I'm not sure why "specified" visibility is any different
>>>>> from unspecified visibility.  As far as I'm aware, the "specified" bit simply
>>>>> means that the decl doesn't inherit inherit visibility from the class, or from
>>>>> the command-line.  But once we're this far, the visibility actually applied to
>>>>> the symbol should be all that matters.
>>>>
>>>> The test is there to differentiate explicit visibility from that implied from
>>>> the command-line.  Without it, we assume hidden visibility for external symbols
>>>> too early, making the command-line option useless.  This is visible even in
>>>> building libgcc.
>>>>
>>>> I believe this set of patches does what we want, and cleans things up a bit in
>>>> the process.
>>>>
>>>>
>>>
>>> I tried them on Linux/x86-64.  They caused:
>>>
>>> FAIL: g++.dg/gomp/tls-wrap4.C  -std=gnu++11  scan-assembler-not _ZTW1i@PLT
>>> FAIL: g++.dg/gomp/tls-wrap4.C  -std=gnu++11  scan-assembler-not _ZTW1i@PLT
>>> FAIL: g++.dg/gomp/tls-wrap4.C  -std=gnu++14  scan-assembler-not _ZTW1i@PLT
>>> FAIL: g++.dg/gomp/tls-wrap4.C  -std=gnu++14  scan-assembler-not _ZTW1i@PLT
>>> FAIL: g++.dg/tls/thread_local-wrap4.C  -std=gnu++11
>>> scan-assembler-not _ZTW1i@PLT
>>> FAIL: g++.dg/tls/thread_local-wrap4.C  -std=gnu++11
>>> scan-assembler-not _ZTW1i@PLT
>>> FAIL: g++.dg/tls/thread_local-wrap4.C  -std=gnu++14
>>> scan-assembler-not _ZTW1i@PLT
>>> FAIL: g++.dg/tls/thread_local-wrap4.C  -std=gnu++14
>>> scan-assembler-not _ZTW1i@PLT
>>>
>>>
>>> --
>>> H.J.
>
>
>
> --
> H.J.
diff mbox

Patch

From 81db9e951ac27c9a7f94f88546d90c852a927d54 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@redhat.com>
Date: Wed, 11 Feb 2015 22:16:38 -0800
Subject: [PATCH 5/5] Rest of HJL patch

---
 gcc/cgraphunit.c                          |  4 +++-
 gcc/testsuite/gcc.dg/visibility-22.c      | 17 +++++++++++++++++
 gcc/testsuite/gcc.dg/visibility-23.c      | 15 +++++++++++++++
 gcc/testsuite/gcc.target/i386/pr32219-1.c | 16 ++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr32219-2.c | 16 ++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr32219-3.c | 17 +++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr32219-4.c | 17 +++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr32219-5.c | 16 ++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr32219-6.c | 16 ++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr32219-7.c | 17 +++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr32219-8.c | 17 +++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr64317.c   |  2 +-
 gcc/varasm.c                              |  5 +++--
 13 files changed, 171 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/visibility-22.c
 create mode 100644 gcc/testsuite/gcc.dg/visibility-23.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-3.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-4.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-5.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-6.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-7.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-8.c

diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index f2c40d4..057eedb 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -803,8 +803,10 @@  varpool_node::finalize_decl (tree decl)
 
   if (node->definition)
     return;
-  notice_global_symbol (decl);
+  /* Set definition first before calling notice_global_symbol so that
+     it is available to notice_global_symbol.  */
   node->definition = true;
+  notice_global_symbol (decl);
   if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl)
       /* Traditionally we do not eliminate static variables when not
 	 optimizing and when not doing toplevel reoder.  */
diff --git a/gcc/testsuite/gcc.dg/visibility-22.c b/gcc/testsuite/gcc.dg/visibility-22.c
new file mode 100644
index 0000000..52f59be
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/visibility-22.c
@@ -0,0 +1,17 @@ 
+/* PR target/32219 */
+/* { dg-do run } */
+/* { dg-require-visibility "" } */
+/* { dg-options "-O2 -fPIC" { target fpic } } */
+/* This test requires support for undefined weak symbols.  This support
+   is not available on hppa*-*-hpux*.  The test is skipped rather than
+   xfailed to suppress the warning that would otherwise arise.  */
+/* { dg-skip-if "" { "hppa*-*-hpux*" "*-*-aix*" "*-*-darwin*" } "*" { "" } }  */
+
+extern void foo () __attribute__((weak,visibility("hidden")));
+int
+main()
+{
+  if (foo)
+    foo ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/visibility-23.c b/gcc/testsuite/gcc.dg/visibility-23.c
new file mode 100644
index 0000000..0fa9ef4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/visibility-23.c
@@ -0,0 +1,15 @@ 
+/* PR target/32219 */
+/* { dg-do compile } */
+/* { dg-require-visibility "" } */
+/* { dg-final { scan-hidden "foo" } } */
+/* { dg-options "-O2 -fPIC" { target fpic } } */
+/* { dg-skip-if "" { "hppa*-*-hpux*" "*-*-aix*" "*-*-darwin*" } "*" { "" } }  */
+
+extern void foo () __attribute__((weak,visibility("hidden")));
+int
+main()
+{
+  if (foo)
+    foo ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-1.c b/gcc/testsuite/gcc.target/i386/pr32219-1.c
new file mode 100644
index 0000000..5bd80a0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr32219-1.c
@@ -0,0 +1,16 @@ 
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpie" } */
+
+/* Common symbol with -fpie.  */
+int xxx;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-2.c b/gcc/testsuite/gcc.target/i386/pr32219-2.c
new file mode 100644
index 0000000..0cf2eb5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr32219-2.c
@@ -0,0 +1,16 @@ 
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic" } */
+
+/* Common symbol with -fpic.  */
+int xxx;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-3.c b/gcc/testsuite/gcc.target/i386/pr32219-3.c
new file mode 100644
index 0000000..911f2a5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr32219-3.c
@@ -0,0 +1,17 @@ 
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpie" } */
+
+/* Weak common symbol with -fpie.  */
+__attribute__((weak))
+int xxx;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-4.c b/gcc/testsuite/gcc.target/i386/pr32219-4.c
new file mode 100644
index 0000000..3d43439
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr32219-4.c
@@ -0,0 +1,17 @@ 
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic" } */
+
+/* Weak common symbol with -fpic.  */
+__attribute__((weak))
+int xxx;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-5.c b/gcc/testsuite/gcc.target/i386/pr32219-5.c
new file mode 100644
index 0000000..ee7442e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr32219-5.c
@@ -0,0 +1,16 @@ 
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpie" } */
+
+/* Initialized symbol with -fpie.  */
+int xxx = -1;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-6.c b/gcc/testsuite/gcc.target/i386/pr32219-6.c
new file mode 100644
index 0000000..f261433
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr32219-6.c
@@ -0,0 +1,16 @@ 
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic" } */
+
+/* Initialized symbol with -fpic.  */
+int xxx = -1;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-7.c b/gcc/testsuite/gcc.target/i386/pr32219-7.c
new file mode 100644
index 0000000..12aaf72
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr32219-7.c
@@ -0,0 +1,17 @@ 
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpie" } */
+
+/* Weak initialized symbol with -fpie.  */
+__attribute__((weak))
+int xxx = -1;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-8.c b/gcc/testsuite/gcc.target/i386/pr32219-8.c
new file mode 100644
index 0000000..2e4fba0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr32219-8.c
@@ -0,0 +1,17 @@ 
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic" } */
+
+/* Weak initialized symbol with -fpic.  */
+__attribute__((weak))
+int xxx = -1;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr64317.c b/gcc/testsuite/gcc.target/i386/pr64317.c
index 33f5b5d..32969fc 100644
--- a/gcc/testsuite/gcc.target/i386/pr64317.c
+++ b/gcc/testsuite/gcc.target/i386/pr64317.c
@@ -1,7 +1,7 @@ 
 /* { dg-do compile { target { *-*-linux* && ia32 } } } */
 /* { dg-options "-O2 -fpie" } */
 /* { dg-final { scan-assembler "addl\[ \\t\]+\[$\]_GLOBAL_OFFSET_TABLE_, %ebx" } } */
-/* { dg-final { scan-assembler "movl\[ \\t\]+c@GOT\[(\]%ebx\[)\]" } } */
+/* { dg-final { scan-assembler "movl\[ \\t\]+c@GOTOFF\[(\]%ebx\[)\]" } } */
 /* { dg-final { scan-assembler-not "movl\[ \\t\]+\[0-9]+\[(\]%esp\[)\], %ebx" } } */
 long c;
 
diff --git a/gcc/varasm.c b/gcc/varasm.c
index dea9b36..9f79416 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -7435,9 +7435,10 @@  default_elf_asm_output_external (FILE *file ATTRIBUTE_UNUSED,
 {
   /* We output the name if and only if TREE_SYMBOL_REFERENCED is
      set in order to avoid putting out names that are never really
-     used. */
+     used.  Always output visibility specified in the source.  */
   if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
-      && targetm.binds_local_p (decl))
+      && (DECL_VISIBILITY_SPECIFIED (decl)
+	  || targetm.binds_local_p (decl)))
     maybe_assemble_visibility (decl);
 }
 
-- 
2.1.0