Bug 2038839 - linking failure when OpenMP is used in static inline function (on ppc64le)
Summary: linking failure when OpenMP is used in static inline function (on ppc64le)
Keywords:
Status: CLOSED WONTFIX
Alias: None
Product: Red Hat Enterprise Linux 8
Classification: Red Hat
Component: gcc
Version: 8.5
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: rc
: ---
Assignee: Marek Polacek
QA Contact: qe-baseos-tools-bugs
URL:
Whiteboard:
Depends On:
Blocks: 2038842
TreeView+ depends on / blocked
 
Reported: 2022-01-10 09:40 UTC by Germano Massullo
Modified: 2023-07-18 14:19 UTC (History)
4 users (show)

Fixed In Version:
Doc Type: No Doc Update
Doc Text:
If this bug requires documentation, please select an appropriate Doc Type value.
Clone Of:
Environment:
Last Closed: 2022-01-13 17:58:17 UTC
Type: Bug
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)
view.i (3.11 MB, text/plain)
2022-01-10 22:52 UTC, Marek Polacek
no flags Details


Links
System ID Private Priority Status Summary Last Updated
GNU Compiler Collection 93274 0 P3 RESOLVED target_clones produces symbols with random digits with -fPIC 2022-01-11 18:05:15 UTC
Red Hat Issue Tracker RHELPLAN-107262 0 None None None 2022-01-10 09:42:30 UTC

Description Germano Massullo 2022-01-10 09:40:11 UTC
Good day, darktable EPEL maintainer here.
I am filling this bugreport upon suggestion of upstream developers.
There is a bug in GCC (gcc-c++-8.5.0-4.el8_5.ppc64le) that causes build to fail only on ppc64le

You can find full logs at
https://koji.fedoraproject.org/koji/taskinfo?taskID=81021576

Short extract

CMakeFiles/lib_darktable.dir/views/view.c.o: In function `variance_analyse._omp_fn.8.resolver.45':
/builddir/build/BUILD/darktable-3.8.0/src/views/view.c:1798: multiple definition of `variance_analyse._omp_fn.8'
CMakeFiles/lib_darktable.dir/dtgtk/thumbnail.c.o:/builddir/build/BUILD/darktable-3.8.0/src/dtgtk/thumbnail.c:2011: first defined here
CMakeFiles/lib_darktable.dir/views/view.c.o: In function `quantize._omp_fn.6.resolver.49':
/builddir/build/BUILD/darktable-3.8.0/src/views/view.c:1798: multiple definition of `quantize._omp_fn.6'
CMakeFiles/lib_darktable.dir/dtgtk/thumbnail.c.o:/builddir/build/BUILD/darktable-3.8.0/src/dtgtk/thumbnail.c:2011: first defined here
CMakeFiles/lib_darktable.dir/views/view.c.o: In function `quantize.resolver.53':
/builddir/build/BUILD/darktable-3.8.0/src/views/view.c:1798: multiple definition of `quantize'
CMakeFiles/lib_darktable.dir/dtgtk/thumbnail.c.o:/builddir/build/BUILD/darktable-3.8.0/src/dtgtk/thumbnail.c:2011: first defined here
CMakeFiles/lib_darktable.dir/views/view.c.o: In function `apply_linear_blending_w_geomean.resolver.55':
/builddir/build/BUILD/darktable-3.8.0/src/views/view.c:1798: multiple definition of `apply_linear_blending_w_geomean'
CMakeFiles/lib_darktable.dir/dtgtk/thumbnail.c.o:/builddir/build/BUILD/darktable-3.8.0/src/dtgtk/thumbnail.c:2011: first defined here
CMakeFiles/lib_darktable.dir/views/view.c.o: In function `apply_linear_blending.resolver.57':
/builddir/build/BUILD/darktable-3.8.0/src/views/view.c:1798: multiple definition of `apply_linear_blending'
CMakeFiles/lib_darktable.dir/dtgtk/thumbnail.c.o:/builddir/build/BUILD/darktable-3.8.0/src/dtgtk/thumbnail.c:2011: first defined here
CMakeFiles/lib_darktable.dir/views/view.c.o: In function `variance_analyse.resolver.59':
/builddir/build/BUILD/darktable-3.8.0/src/views/view.c:1798: multiple definition of `variance_analyse'
CMakeFiles/lib_darktable.dir/dtgtk/thumbnail.c.o:/builddir/build/BUILD/darktable-3.8.0/src/dtgtk/thumbnail.c:2011: first defined here
CMakeFiles/lib_darktable.dir/views/view.c.o: In function `interpolate_bilinear.resolver.61':
/builddir/build/BUILD/darktable-3.8.0/src/views/view.c:1798: multiple definition of `interpolate_bilinear'
CMakeFiles/lib_darktable.dir/dtgtk/thumbnail.c.o:/builddir/build/BUILD/darktable-3.8.0/src/dtgtk/thumbnail.c:2011: first defined here
CMakeFiles/lib_darktable.dir/views/view.c.o: In function `fast_clamp.resolver.63':
/builddir/build/BUILD/darktable-3.8.0/src/views/view.c:1798: multiple definition of `fast_clamp'
CMakeFiles/lib_darktable.dir/dtgtk/thumbnail.c.o:/builddir/build/BUILD/darktable-3.8.0/src/dtgtk/thumbnail.c:2011: first defined here
collect2: error: ld returned 1 exit status
make[2]: *** [bin/CMakeFiles/lib_darktable.dir/build.make:3195: bin/libdarktable.so] Error 1
make[2]: Leaving directory '/builddir/build/BUILD/darktable-3.8.0/ppc64le-redhat-linux-gnu'
make[1]: *** [CMakeFiles/Makefile2:1912: bin/CMakeFiles/lib_darktable.dir/all] Error 2
make: *** [Makefile:159: all] Error 2
RPM build errors:
error: Bad exit status from /var/tmp/rpm-tmp.DLJD17 (%build)
    Bad exit status from /var/tmp/rpm-tmp.DLJD17 (%build)
Child return code was: 1
EXCEPTION: [Error()]
Traceback (most recent call last):
  File "/usr/lib/python3.10/site-packages/mockbuild/trace_decorator.py", line 93, in trace
    result = func(*args, **kw)
  File "/usr/lib/python3.10/site-packages/mockbuild/util.py", line 600, in do_with_status
    raise exception.Error("Command failed: \n # %s\n%s" % (command, output), child.returncode)
mockbuild.exception.Error: Command failed: 
 # bash --login -c /usr/bin/rpmbuild -bb --target ppc64le --nodeps /builddir/build/SPECS/darktable.spec

Comment 1 Marek Polacek 2022-01-10 20:40:26 UTC
I've reproduced this with system GCC 8 and with GCC 9 from GTS 9.  It works with GCC 10 and GCC 11:

# gcc --version
gcc (GCC) 10.2.1 20201112 (Red Hat 10.2.1-8)
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


[...]
Wrote: /root/rpmbuild/RPMS/ppc64le/darktable-3.8.0-6.el8.ppc64le.rpm
Wrote: /root/rpmbuild/RPMS/ppc64le/darktable-tools-noise-3.8.0-6.el8.ppc64le.rpm
Wrote: /root/rpmbuild/RPMS/ppc64le/darktable-debugsource-3.8.0-6.el8.ppc64le.rpm
Wrote: /root/rpmbuild/RPMS/ppc64le/darktable-debuginfo-3.8.0-6.el8.ppc64le.rpm
Wrote: /root/rpmbuild/RPMS/ppc64le/darktable-tools-noise-debuginfo-3.8.0-6.el8.ppc64le.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.Wk5oQG
+ umask 022
+ cd /root/rpmbuild/BUILD
+ cd darktable-3.8.0
+ /usr/bin/rm -rf /root/rpmbuild/BUILDROOT/darktable-3.8.0-6.el8.ppc64le
+ exit 0

I'm not sure which commit fixed it yet.

Comment 2 Marek Polacek 2022-01-10 22:50:39 UTC
I think I found the problem; GCC 9 and earlier mark certain symbols as .globl which makes them visible to ld, which then complains about multiple definitions.
For instance,

.globl variance_analyse._omp_fn.0

If I compile the .c file into a .s file with GCC 9 but manually remove the .globl line, then assemble it into a .o from it, the linking works.

E.g.,
$ /opt/rh/gcc-toolset-9/root/usr/bin/cc -S ./view.i -fopenmp   -O3 -ffast-math -fno-finite-math-only -fexpensive-optimizations -fPIC -o- | grep -E '(globl.*fast_clamp|globl.*quantize._omp_fn.1)'
	.globl quantize._omp_fn.1
	.globl fast_clamp
$ /opt/rh/gcc-toolset-10/root/usr/bin/cc -S ./view.i -fopenmp   -O3 -ffast-math -fno-finite-math-only -fexpensive-optimizations -fPIC -o- | grep -E '(globl.*fast_clamp|globl.*quantize._omp_fn.1)'

I'll attach view.i.  It would be really very interesting to see what changed this.  We shall bisect & see.

Comment 3 Marek Polacek 2022-01-10 22:52:59 UTC
Created attachment 1849966 [details]
view.i

Comment 4 Marek Polacek 2022-01-11 17:11:05 UTC
Fixed upstream by 724ec02c2c6d1b79788be77f68ebb6ca7b5b6acd.

Comment 5 Marek Polacek 2022-01-11 17:58:57 UTC
This is r10-6242 + r10-7372 adjusted for GCC 8:

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 31502774ef3..990cc6f11f1 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -32828,26 +32828,16 @@ make_resolver_func (const tree default_decl,
 		    const tree ifunc_alias_decl,
 		    basic_block *empty_bb)
 {
-  char *resolver_name;
-  tree decl, type, decl_name, t;
+  tree decl, type, t;
 
-  /* IFUNC's have to be globally visible.  So, if the default_decl is
-     not, then the name of the IFUNC should be made unique.  */
-  if (TREE_PUBLIC (default_decl) == 0)
-    {
-      char *ifunc_name = make_unique_name (default_decl, "ifunc", true);
-      symtab->change_decl_assembler_name (ifunc_alias_decl,
-					  get_identifier (ifunc_name));
-      XDELETEVEC (ifunc_name);
-    }
-
-  resolver_name = make_unique_name (default_decl, "resolver", false);
+  /* Create resolver function name based on default_decl.  */
+  tree decl_name = clone_function_name (default_decl, "resolver");
+  const char *resolver_name = IDENTIFIER_POINTER (decl_name);
 
   /* The resolver function should return a (void *). */
   type = build_function_type_list (ptr_type_node, NULL_TREE);
 
   decl = build_fn_decl (resolver_name, type);
-  decl_name = get_identifier (resolver_name);
   SET_DECL_ASSEMBLER_NAME (decl, decl_name);
 
   DECL_NAME (decl) = decl_name;
@@ -32874,6 +32864,9 @@ make_resolver_func (const tree default_decl,
       DECL_COMDAT (decl) = 1;
       make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl));
     }
+  else
+    TREE_PUBLIC (ifunc_alias_decl) = 0;
+
   /* Build result decl and add to function_decl. */
   t = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, ptr_type_node);
   DECL_CONTEXT (t) = decl;
@@ -32899,7 +32892,6 @@ make_resolver_func (const tree default_decl,
 
   /* Create the alias for dispatch to resolver here.  */
   cgraph_node::create_same_body_alias (ifunc_alias_decl, decl);
-  XDELETEVEC (resolver_name);
   return decl;
 }
 
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 891c4c54e5f..f9dfa4dd9d6 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -38022,6 +38022,18 @@ make_resolver_func (const tree default_decl,
   DECL_INITIAL (decl) = make_node (BLOCK);
   DECL_STATIC_CONSTRUCTOR (decl) = 0;
 
+  if (DECL_COMDAT_GROUP (default_decl)
+      || TREE_PUBLIC (default_decl))
+    {
+      /* In this case, each translation unit with a call to this
+	 versioned function will put out a resolver.  Ensure it
+	 is comdat to keep just one copy.  */
+      DECL_COMDAT (decl) = 1;
+      make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl));
+    }
+  else
+    TREE_PUBLIC (dispatch_decl) = 0;
+
   /* Build result decl and add to function_decl.  */
   tree t = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, ptr_type_node);
   DECL_CONTEXT (t) = decl;
diff --git a/gcc/multiple_target.c b/gcc/multiple_target.c
index 97d2268663f..68f089e81ea 100644
--- a/gcc/multiple_target.c
+++ b/gcc/multiple_target.c
@@ -178,10 +178,6 @@ create_dispatcher_calls (struct cgraph_node *node)
   node->externally_visible = false;
   node->forced_by_abi = false;
   node->set_section (NULL);
-  node->unique_name = ((node->resolution == LDPR_PREVAILING_DEF_IRONLY
-			|| node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
-		       && !flag_incremental_link);
-  node->resolution = LDPR_PREVAILING_DEF_IRONLY;
 
   DECL_ARTIFICIAL (node->decl) = 1;
   node->force_output = true;
diff --git a/gcc/testsuite/gcc.dg/lto/pr94271_0.c b/gcc/testsuite/gcc.dg/lto/pr94271_0.c
new file mode 100644
index 00000000000..2ce7d65411a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr94271_0.c
@@ -0,0 +1,13 @@
+/* PR lto/94271 */
+/* { dg-lto-do link } */
+
+int a;
+
+static int __attribute__ ((target_clones ("default", "avx512f"))) fast_clamp ()
+{}
+
+void
+c ()
+{
+  a = fast_clamp ();
+}
diff --git a/gcc/testsuite/gcc.dg/lto/pr94271_1.c b/gcc/testsuite/gcc.dg/lto/pr94271_1.c
new file mode 100644
index 00000000000..db9bc9df6db
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr94271_1.c
@@ -0,0 +1,17 @@
+int aa;
+
+static inline int __attribute__ ((target_clones ("default", "avx512f")))
+fast_clamp ()
+{}
+
+void
+b ()
+{
+  aa = fast_clamp ();
+}
+
+int
+main ()
+{
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr81213-2.c b/gcc/testsuite/gcc.target/i386/pr81213-2.c
new file mode 100644
index 00000000000..a80622cb184
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81213-2.c
@@ -0,0 +1,11 @@
+__attribute__((target_clones("avx","arch=slm","arch=core-avx2","default")))
+static int
+foo ()
+{
+  return 2;
+}
+
+int bar()
+{
+  return foo();
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr81213.c b/gcc/testsuite/gcc.target/i386/pr81213.c
index 13e15d5fef0..334838631d0 100644
--- a/gcc/testsuite/gcc.target/i386/pr81213.c
+++ b/gcc/testsuite/gcc.target/i386/pr81213.c
@@ -1,6 +1,9 @@
 /* PR ipa/81214.  */
-/* { dg-do compile } */
+/* { dg-do run } */
 /* { dg-require-ifunc "" } */
+/* { dg-additional-sources "pr81213-2.c" } */
+
+int bar();
 
 __attribute__((target_clones("avx","arch=slm","arch=core-avx2","default")))
 static int
@@ -11,9 +14,9 @@ foo ()
 
 int main()
 {
-  return foo();
+  return foo() + bar();
 }
 
-/* { dg-final { scan-assembler "\t.globl\tfoo\\..*\\.ifunc" } } */
+/* { dg-final { scan-assembler "\t.globl\tfoo" } } */
 /* { dg-final { scan-assembler "foo.resolver:" } } */
-/* { dg-final { scan-assembler "foo\\..*\\.ifunc, @gnu_indirect_function" } } */
+/* { dg-final { scan-assembler "foo\\, @gnu_indirect_function" } } */

Comment 7 Marek Polacek 2022-01-13 17:58:17 UTC
Unfortunately, I can't fix this: the author of the fixes for PR 93274 thinks that target_clones is too fragile and backporting the fix above to GCC 8 might cause another breakage, which would need more fixes.

You could:

1) Use gcc-toolset-10-gcc which works well, and should be available in CentOS too.  You could do

scl enable gcc-toolset-10 bash

in the spec file and then GCC 10 gets used.

2) Try compiling with -Dtarget_clones=unknown_attr which will deactivate target_clones.


Note You need to log in before you can comment on or make changes to this bug.