Patchwork [libitm,build] Clear hardware capabilities on libitm.so with Sun ld

login
register
mail settings
Submitter Rainer Orth
Date Nov. 21, 2011, 1:53 p.m.
Message ID <ydd4nxxlgyq.fsf@manam.CeBiTec.Uni-Bielefeld.DE>
Download mbox | patch
Permalink /patch/126792/
State New
Headers show

Comments

Rainer Orth - Nov. 21, 2011, 1:53 p.m.
The libitm execution tests are currently failing on Solaris 10 and up
with Sun as/ld:

ld.so.1: cancel.exe: fatal: /var/gcc/regression/trunk/11-gcc/build/i386-pc-solaris2.11/./libitm/.libs/libitm.so.0: hardware capability (CA_SUNW_HW_1) unsupported: 0x20000000  [ AVX ]
FAIL: libitm.c/cancel.c execution test

This is the same issue solved by
gcc/testsuite/gcc.target/i386/clearcap.map, and the following patch
adresses it in the same way:

* Detect if the linker used supports -M <map file>.

* Use it when linking libitm.so.

Right now, it is only possible to clear the hardware capabilities
completely, while the new v2 mapfile syntax supports selectively adding
and removing capabilities.  It is only available in Solaris 11 and
Solaris 10 Update 10, though, so I'm restricting us to the v1 syntax for
now.

It may make sense to move the test to toplevel config/ld-hwcap.m4 later,
but for now libitm is the only user.

Bootstrapped on i386-pc-solaris2.11 with Sun as/ld, gas/Sun ld, and
gas/gld, on i386-pc-solaris2.8 to make sure it doesn't break the build
with the old linker there, and on x86_64-unknown-linux-gnu.

Ok for mainline?

	Rainer


2011-11-18  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>

	* clearcap.map: New file.
	* acinclude.m4 (LIBITM_CHECK_LINKER_HWCAP): New test.
	* configure.ac: Call it.
	* Makefile.am (AM_LDFLAGS): Add $(HWCAP_LDFLAGS)
	* configure: Regenerate.
	* Makefile.in: Regenerate.
	* testsuite/Makefile.in: Regenerate.
Richard Henderson - Nov. 21, 2011, 5:16 p.m.
On 11/21/2011 05:53 AM, Rainer Orth wrote:
> The libitm execution tests are currently failing on Solaris 10 and up
> with Sun as/ld:
> 
> ld.so.1: cancel.exe: fatal: /var/gcc/regression/trunk/11-gcc/build/i386-pc-solaris2.11/./libitm/.libs/libitm.so.0: hardware capability (CA_SUNW_HW_1) unsupported: 0x20000000  [ AVX ]
> FAIL: libitm.c/cancel.c execution test
> 
> This is the same issue solved by
> gcc/testsuite/gcc.target/i386/clearcap.map, and the following patch
> adresses it in the same way:
> 
> * Detect if the linker used supports -M <map file>.
> 
> * Use it when linking libitm.so.
> 
> Right now, it is only possible to clear the hardware capabilities
> completely, while the new v2 mapfile syntax supports selectively adding
> and removing capabilities.  It is only available in Solaris 11 and
> Solaris 10 Update 10, though, so I'm restricting us to the v1 syntax for
> now.

This is only ok if the compiler and library are build with default options.
If you use --with-arch=corei7-avx then we may well use AVX insns all through
the library, not just in the one interface that will only be used if the 
user of the library is using avx.

Can you auto-foo this based on CC+CFLAGS?  E.g.  compile-time tests for the
various __SSE__ / __AVX__ macros?


r~
Rainer Orth - Nov. 21, 2011, 5:23 p.m.
Richard Henderson <rth@redhat.com> writes:

> This is only ok if the compiler and library are build with default options.
> If you use --with-arch=corei7-avx then we may well use AVX insns all through
> the library, not just in the one interface that will only be used if the 
> user of the library is using avx.
>
> Can you auto-foo this based on CC+CFLAGS?  E.g.  compile-time tests for the
> various __SSE__ / __AVX__ macros?

Probably, but it occured to me that it might be easier to just apply the
mapfile to x86_avx.o unconditionally before linking libitm.la.

	Rainer
Richard Henderson - Nov. 21, 2011, 5:54 p.m.
On 11/21/2011 09:23 AM, Rainer Orth wrote:
> Richard Henderson <rth@redhat.com> writes:
> 
>> This is only ok if the compiler and library are build with default options.
>> If you use --with-arch=corei7-avx then we may well use AVX insns all through
>> the library, not just in the one interface that will only be used if the 
>> user of the library is using avx.
>>
>> Can you auto-foo this based on CC+CFLAGS?  E.g.  compile-time tests for the
>> various __SSE__ / __AVX__ macros?
> 
> Probably, but it occured to me that it might be easier to just apply the
> mapfile to x86_avx.o unconditionally before linking libitm.la.

Possibly.  Though you'd want to do the same thing for x86_sse.o too.
Again, that file is only used if the main program uses SSE.


r~
David Miller - Nov. 21, 2011, 6:25 p.m.
From: Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
Date: Mon, 21 Nov 2011 14:53:33 +0100

> Right now, it is only possible to clear the hardware capabilities
> completely, while the new v2 mapfile syntax supports selectively adding
> and removing capabilities.  It is only available in Solaris 11 and
> Solaris 10 Update 10, though, so I'm restricting us to the v1 syntax for
> now.

I really wish Sun had never added this hwcap checking, 99 times out of
100 it's a nuisance rather than a help in any way.
Rainer Orth - Nov. 22, 2011, 6:14 p.m.
David Miller <davem@davemloft.net> writes:

> From: Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
> Date: Mon, 21 Nov 2011 14:53:33 +0100
>
>> Right now, it is only possible to clear the hardware capabilities
>> completely, while the new v2 mapfile syntax supports selectively adding
>> and removing capabilities.  It is only available in Solaris 11 and
>> Solaris 10 Update 10, though, so I'm restricting us to the v1 syntax for
>> now.
>
> I really wish Sun had never added this hwcap checking, 99 times out of
> 100 it's a nuisance rather than a help in any way.

I beg to differ: I prefer a ld.so.1 message telling me that my
executable or library uses ISA extension x, but my machine doesn't
support that, over the same binary beginning to run, but crashing with a
SIGILL every time.  I posit that's similar to symbol versioning where
the runtime linker can tell me: you're trying to use interface x in
liby.so.3, but the library doesn't provide it.  That's far better than
letting the programs start and crash later with an unsupported insn or
missing symbol, perhaps losing work.  True, you may be lucky and not
hit that codepath, but I'd rather not depend on my luck if running
software ;-)

I suppose that everyone who's able to play cute tricks with code
selection at runtime depending on machine hardware capabilities is smart
enough to deal with the linker's hwcap stuff, too.

As an aside, in Solaris 10 Update 10 and Solaris 11, there's direct
support in ld and ld.so.1 to select different implementations of the
same interface, depending on hardware capabilites present:

http://docs.oracle.com/cd/E23824_01/html/819-0690/chapter2-13.html#giskh

	Rainer
Richard Henderson - Nov. 22, 2011, 6:49 p.m.
On 11/22/2011 10:14 AM, Rainer Orth wrote:
> As an aside, in Solaris 10 Update 10 and Solaris 11, there's direct
> support in ld and ld.so.1 to select different implementations of the
> same interface, depending on hardware capabilites present:
> 
> http://docs.oracle.com/cd/E23824_01/html/819-0690/chapter2-13.html#giskh

Hum.  So, not entirely incompatible with the gnu ifunc extension,
but certainly not exactly like it either.

Off and on I've been pondering, post-toplevel-libgcc-move, whether
it would make sense to implement the functions therein with different
ISAs and either select the proper version with pre-processor macros
(generating a target-specific libgcc) or with ifuncs if available.

What support does the Solaris 11 assembler have for this feature?
The documentation only mentions the compiler...


r~
Rainer Orth - Nov. 23, 2011, 12:49 p.m.
Richard Henderson <rth@redhat.com> writes:

> What support does the Solaris 11 assembler have for this feature?
> The documentation only mentions the compiler...

I've asked exactly the same question when the spec was posted early last
year:

	http://arc.opensolaris.org/caselog/PSARC/2010/022/mail

Unfortunately, there was none at the time.  The assembler manuals
mention nothing either, but they are incomplete and outdated,
unfortuantely.  There's nothing obvious even in the last beta (12.3) of
the Studio compilers either, so it seems you'll have to use the ld
mapfile trick to convert from object capabilities to symbol capabilities
for now, which feels clumsy.

I'll ask the linker engineers that developed that feature.

	Rainer
Rainer Orth - Nov. 28, 2011, 4:31 p.m.
Richard Henderson <rth@redhat.com> writes:

> On 11/21/2011 05:53 AM, Rainer Orth wrote:
>> The libitm execution tests are currently failing on Solaris 10 and up
>> with Sun as/ld:
>> 
>> ld.so.1: cancel.exe: fatal: /var/gcc/regression/trunk/11-gcc/build/i386-pc-solaris2.11/./libitm/.libs/libitm.so.0: hardware capability (CA_SUNW_HW_1) unsupported: 0x20000000  [ AVX ]
>> FAIL: libitm.c/cancel.c execution test
>> 
>> This is the same issue solved by
>> gcc/testsuite/gcc.target/i386/clearcap.map, and the following patch
>> adresses it in the same way:
>> 
>> * Detect if the linker used supports -M <map file>.
>> 
>> * Use it when linking libitm.so.
>> 
>> Right now, it is only possible to clear the hardware capabilities
>> completely, while the new v2 mapfile syntax supports selectively adding
>> and removing capabilities.  It is only available in Solaris 11 and
>> Solaris 10 Update 10, though, so I'm restricting us to the v1 syntax for
>> now.
>
> This is only ok if the compiler and library are build with default options.
> If you use --with-arch=corei7-avx then we may well use AVX insns all through
> the library, not just in the one interface that will only be used if the 
> user of the library is using avx.
>
> Can you auto-foo this based on CC+CFLAGS?  E.g.  compile-time tests for the
> various __SSE__ / __AVX__ macros?

My first attempt was to apply the equivalent of ld -r -M clearcap.map to
x86_avx.lo and x86_sse.lo.  While this works fine if calling ld -r
directly, you need to get this through libtool and this is where things
start breaking in all sorts of ways:

I tried

      $ libtool --mode=link --tag=CC gcc -r -Wl,-M,clearcap.map -o x86_nhc.lo x86_sse.lo
      libtool: link: collect-ld -r -o x86_nhc.o  .libs/x86_sse.o  
      libtool: link: collect-ld -r -o x86_nhc.lo .libs/x86_sse.o 

This is of no use at all since -Wl,-M,clearcap.map is lost completely
and I've found no way to get this through libtool at all.  This beast
tries to be smart and messes everything up completely.  But even if I
could get that part to work, what happens is still wrong: the .lo file
is a real object file now, not the usual text file, so once I try to
link the shared lib, libtool rightly complains.  While the libtool docs
claim that this relinking (.lo -> .lo) should work, it obviously does
not, even with libtool 2.2.4 ;-(

So unless I'm overlooking something, I'll have to go the route you
outlined above and check for __SSE__/__AVX__ to make the decision.

	Rainer

Patch

# HG changeset patch
# Parent fe631cce39f95ae2f718499a8e82260c18149752
Clear hardware capabilities on libitm.so with Sun ld

diff --git a/libitm/Makefile.am b/libitm/Makefile.am
--- a/libitm/Makefile.am
+++ b/libitm/Makefile.am
@@ -21,7 +21,7 @@  AM_CFLAGS = $(XCFLAGS)
 AM_CXXFLAGS = -std=gnu++0x -funwind-tables -fno-exceptions -fno-rtti \
 	$(XCFLAGS) $(abi_version)
 AM_CCASFLAGS = $(XCFLAGS)
-AM_LDFLAGS = $(XLDFLAGS) $(SECTION_LDFLAGS) $(OPT_LDFLAGS)
+AM_LDFLAGS = $(XLDFLAGS) $(SECTION_LDFLAGS) $(OPT_LDFLAGS) $(HWCAP_LDFLAGS)
 
 toolexeclib_LTLIBRARIES = libitm.la
 nodist_toolexeclib_HEADERS = libitm.spec
diff --git a/libitm/acinclude.m4 b/libitm/acinclude.m4
--- a/libitm/acinclude.m4
+++ b/libitm/acinclude.m4
@@ -256,6 +256,34 @@  AC_DEFUN([LIBITM_CHECK_LINKER_FEATURES],
 
 
 dnl
+dnl Check if the linker used supports linker maps to clear hardware
+dnl capabilities.  This is only supported by Sun ld at the moment.
+dnl
+dnl Defines:
+dnl  HWCAP_LDFLAGS='-Wl,-M,clearcap.map' if possible
+dnl  LD (as a side effect of testing)
+dnl
+AC_DEFUN([LIBITM_CHECK_LINKER_HWCAP], [
+  test -z "$HWCAP_LDFLAGS" && HWCAP_LDFLAGS=''
+  AC_REQUIRE([AC_PROG_LD])
+
+  ac_save_LDFLAGS="$LDFLAGS"
+  LDFLAGS="$LFLAGS -Wl,-M,$srcdir/clearcap.map"
+
+  AC_MSG_CHECKING([for ld that supports -Wl,-M,mapfile])
+  AC_TRY_LINK([], [return 0;], [ac_hwcap_ldflags=yes],[ac_hwcap_ldflags=no])
+  if test "$ac_hwcap_ldflags" = "yes"; then
+    HWCAP_LDFLAGS="-Wl,-M,$srcdir/clearcap.map $HWCAP_LDFLAGS"
+  fi
+  AC_MSG_RESULT($ac_hwcap_ldflags)
+
+  LDFLAGS="$ac_save_LDFLAGS"
+
+  AC_SUBST(HWCAP_LDFLAGS)
+])
+
+
+dnl
 dnl Add version tags to symbols in shared library (or not), additionally
 dnl marking other symbols as private/local (or not).
 dnl
diff --git a/libitm/clearcap.map b/libitm/clearcap.map
new file mode 100644
--- /dev/null
+++ b/libitm/clearcap.map
@@ -0,0 +1,14 @@ 
+# Clear hardware capabilities emitted by Sun as: calls to the x86_avx.c
+# functions are only emitted with -mavx.
+#
+# The v1 mapfile syntax has no support for clearing specific capabilities,
+# so clear everything.
+#
+hwcap_1 = V0x0 OVERRIDE;
+#
+# If we can assume mapfile v2 syntax, we can specificially clear AVX.
+#
+#$mapfile_version 2
+#CAPABILITY {
+#	HW -= AVX;
+#};
diff --git a/libitm/configure.ac b/libitm/configure.ac
--- a/libitm/configure.ac
+++ b/libitm/configure.ac
@@ -208,10 +208,11 @@  GCC_LINUX_FUTEX(:)
 # See if we support thread-local storage.
 GCC_CHECK_TLS
 
-# See what sort of export controls are availible.
+# See what sort of export controls are available.
 LIBITM_CHECK_ATTRIBUTE_VISIBILITY
 LIBITM_CHECK_ATTRIBUTE_DLLEXPORT
 LIBITM_CHECK_ATTRIBUTE_ALIAS
+LIBITM_CHECK_LINKER_HWCAP
 LIBITM_ENABLE_SYMVERS
 
 if test $enable_symvers = gnu; then