PR 85075, Fix PowerPC __float182/__ibm128 types and mangling

Message ID 20180415195044.GA2441@ibm-tiger.the-meissners.org
State New
Headers show
Series
  • PR 85075, Fix PowerPC __float182/__ibm128 types and mangling
Related show

Commit Message

Michael Meissner April 15, 2018, 7:50 p.m.
PR target/85075 shows that there are some problems with the types for the 3
128-bit floating point types on the PowerPC:

	__float128	(and _Float128 in C, IEEE 128-bit)
	__ieee128	(IBM extended double)
	long double	(either IEEE 128-bit or IBM extended double)

With GCC 8, we are beginning the transition of long double from the IBM
extended double format to IEEE 128-bit.

I implemented __float128 and __ieee128 initially as being separate types when
the long double format was the other type, and mapped to long double when the
long double format was the same as the type.

However, the use of C++ templates and overloaded functions within classes shows
that we really need to have 3 separate types.  Each type needs to have
different mangling.

Since __float128 and __ibm128 are now always separate types, I relaxed the
restriction that __ibm128 can only be used if -mlong-double-128.

In developing this patch, Segher noticed that the mangling for __float128
violated the mangling standards.  This patch includes a change to use a more
official mangling (u10__float128).  This means that GCC 8 will not be able to
link with C++ functions that pass or return __float128 values compiled with GCC
6 or GCC 7.  I have put in a warning if __float128 is mangled.  The warning can
be silenced by using -Wno-psabi.

In addition, when I built this on big endian system, the changes exposed a
latent bug with the way __builtin_packlongdouble was done when it tried to
support the first argument overlapping with the result.  I have removed the
code to support overlapping input/output for this builtin.  I imagine that we
will need to add __builtin_packieee128 and __builtin_unpackieee128 as well in
the future (or make __builtin_{,un}packlongdouble support all three types).

The manglings that are now used are:

For -mabi=ieeelongdouble:

	__float128	"u10__float128"
	__ibm128	"u8__ibm128"
	long double	"u9__ieee128"

For -mabi=ibmlongdouble:

	__float128	"u10__float128"
	__ibm128	"u8__ibm128"
	long double	"g"

For -mlong-double-64:

	__float128	"u10__float128"
	__ibm128	"u8__ibm128"
	long double	"e"

I have tested these patches on a little endian power8 system and a big endian
power7 system (both 32/64-bit).  I also tested a previous version of the patch
on a big endian power8 system (both 32/64-bit).  There were no regressions.

Can I apply these patches to the GCC 8 trunk?

[gcc]
2018-04-15  Michael Meissner  <meissner@linux.vnet.ibm.com>

	PR target/85075
	* config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): __ibm128 is
	now a separate type, don't #define __ibm128 as long double.
	* config/rs6000/rs6000.c (rs6000_init_builtins): Make __ibm128 a
	separate type on systems that support IEEE 128-bit floating point.
	(rs6000_mangle_type): Use separate manglings for __ibm128 and
	__float128.  Change __float128 mangling from U10__float128 to
	u10__float128.  Issue a warning that the mangling has changed in
	GCC 8.
	* config/rs6000/rs6000.md (pack<mode>): Do not try handle a pack
	where the inputs overlap with the output.

[gcc/testsuite]
2018-04-15  Michael Meissner  <meissner@linux.vnet.ibm.com>

	PR target/85075
	* g++.dg/pr85075-1.C: New tests.  Make sure that __float128,
	__ibm128, and long double are different types, and that you can
	mix them in templates and with overloaded functions.  Test all 3
	different long dobule variants (IEEE 128 bit, IBM 128 bit, and 64
	bit).
	* g++.dg/pr85075-2.C: Likewise.
	* g++.dg/pr85075-3.C: Likewise.

Comments

Michael Meissner April 15, 2018, 7:52 p.m. | #1
I should mention that the x86_64 port has the same issue with mangling if you
use the -mlong-double-128 option, since __float128 and long double use the same
mangling.
Segher Boessenkool April 16, 2018, 4:53 p.m. | #2
Hi!

Thank you for working on this.

On Sun, Apr 15, 2018 at 03:50:44PM -0400, Michael Meissner wrote:
> PR target/85075 shows that there are some problems with the types for the 3
> 128-bit floating point types on the PowerPC:
> 
> 	__float128	(and _Float128 in C, IEEE 128-bit)
> 	__ieee128	(IBM extended double)

(You mean __ibm128, right?)

> 	long double	(either IEEE 128-bit or IBM extended double)

> In developing this patch, Segher noticed that the mangling for __float128
> violated the mangling standards.  This patch includes a change to use a more
> official mangling (u10__float128).

To use a mangling that works *at all*, yeah.

> This means that GCC 8 will not be able to
> link with C++ functions that pass or return __float128 values compiled with GCC
> 6 or GCC 7.  I have put in a warning if __float128 is mangled.  The warning can
> be silenced by using -Wno-psabi.

It's a note, not a warning (so -Werror won't fail builds, etc.)

> In addition, when I built this on big endian system, the changes exposed a
> latent bug with the way __builtin_packlongdouble was done when it tried to
> support the first argument overlapping with the result.  I have removed the
> code to support overlapping input/output for this builtin.  I imagine that we
> will need to add __builtin_packieee128 and __builtin_unpackieee128 as well in
> the future (or make __builtin_{,un}packlongdouble support all three types).

Please send this part as a separate patch.  It will need backports, too.

> The manglings that are now used are:
> 
> For -mabi=ieeelongdouble:
> 
> 	__float128	"u10__float128"
> 	__ibm128	"u8__ibm128"
> 	long double	"u9__ieee128"
> 
> For -mabi=ibmlongdouble:
> 
> 	__float128	"u10__float128"
> 	__ibm128	"u8__ibm128"
> 	long double	"g"
> 
> For -mlong-double-64:
> 
> 	__float128	"u10__float128"
> 	__ibm128	"u8__ibm128"
> 	long double	"e"

If __float128 is the same type as _Float128, as which of those should
it be mangled?  The C++ ABI has "DF" for _FloatN, but the demangler uses
that same code for fixed points types.  Ugh.

I don't think mangling "long double" as "u9__ieee128" works well with for
example GDB.

Cc:ing Joseph Myers; Joseph, do you have any advice here?


Segher
Michael Meissner April 16, 2018, 7:22 p.m. | #3
On Mon, Apr 16, 2018 at 11:53:13AM -0500, Segher Boessenkool wrote:
> Hi!
> 
> Thank you for working on this.
> 
> On Sun, Apr 15, 2018 at 03:50:44PM -0400, Michael Meissner wrote:
> > PR target/85075 shows that there are some problems with the types for the 3
> > 128-bit floating point types on the PowerPC:
> > 
> > 	__float128	(and _Float128 in C, IEEE 128-bit)
> > 	__ieee128	(IBM extended double)
> 
> (You mean __ibm128, right?)

Yes.

> > 	long double	(either IEEE 128-bit or IBM extended double)
> 
> > In developing this patch, Segher noticed that the mangling for __float128
> > violated the mangling standards.  This patch includes a change to use a more
> > official mangling (u10__float128).
> 
> To use a mangling that works *at all*, yeah.
> 
> > This means that GCC 8 will not be able to
> > link with C++ functions that pass or return __float128 values compiled with GCC
> > 6 or GCC 7.  I have put in a warning if __float128 is mangled.  The warning can
> > be silenced by using -Wno-psabi.
> 
> It's a note, not a warning (so -Werror won't fail builds, etc.)
> 
> > In addition, when I built this on big endian system, the changes exposed a
> > latent bug with the way __builtin_packlongdouble was done when it tried to
> > support the first argument overlapping with the result.  I have removed the
> > code to support overlapping input/output for this builtin.  I imagine that we
> > will need to add __builtin_packieee128 and __builtin_unpackieee128 as well in
> > the future (or make __builtin_{,un}packlongdouble support all three types).
> 
> Please send this part as a separate patch.  It will need backports, too.

I opened up PR 85424, and submitted this patch:
https://gcc.gnu.org/ml/gcc-patches/2018-04/msg00767.html

Here is the PR 85075 patch without the rs6000.md bits:

[gcc]
2018-04-16  Michael Meissner  <meissner@linux.vnet.ibm.com>

	PR target/85075
	* config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): __ibm128 is
	now a separate type, don't #define __ibm128 as long double.
	* config/rs6000/rs6000.c (rs6000_init_builtins): Make __ibm128 a
	separate type on systems that support IEEE 128-bit floating point.
	(rs6000_mangle_type): Use separate manglings for __ibm128 and
	__float128.  Change __float128 mangling from U10__float128 to
	u10__float128.  Issue a warning that the mangling has changed in
	GCC 8.

[gcc/testsuite]
2018-04-16  Michael Meissner  <meissner@linux.vnet.ibm.com>

	PR target/85075
	* g++.dg/pr85075-1.C: New tests.  Make sure that __float128,
	__ibm128, and long double are different types, and that you can
	mix them in templates and with overloaded functions.  Test all 3
	different long dobule variants (IEEE 128 bit, IBM 128 bit, and 64
	bit).
	* g++.dg/pr85075-2.C: Likewise.
	* g++.dg/pr85075-3.C: Likewise.
Segher Boessenkool April 17, 2018, 2:57 p.m. | #4
On Mon, Apr 16, 2018 at 03:22:16PM -0400, Michael Meissner wrote:
> Here is the PR 85075 patch without the rs6000.md bits:

This fails on powerpc64-linux bootstrap (w/ --with-cpu=power7 if that
matters):

/home/segher/src/gcc/libgcc/config/rs6000/ibm-ldouble.c: In function '__gcc_qadd
':
/home/segher/src/gcc/libgcc/config/rs6000/ibm-ldouble.c:157:1: error: insn does 
not satisfy its constraints:
 }
 ^
(insn 144 197 198 15 (set (reg:TF 32 0 [orig:143 _47 ] [143])
        (unspec:TF [
                (reg:DF 33 1 [orig:143 _47+8 ] [143])
                (reg/v:DF 36 4 [orig:139 xl ] [139])
            ] UNSPEC_PACK_128BIT)) "/home/segher/src/gcc/libgcc/config/rs6000/ib
m-ldouble.c":106 1003 {packtf}
     (nil))
during RTL pass: reload


Segher


> 	PR target/85075
> 	* config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): __ibm128 is
> 	now a separate type, don't #define __ibm128 as long double.
> 	* config/rs6000/rs6000.c (rs6000_init_builtins): Make __ibm128 a
> 	separate type on systems that support IEEE 128-bit floating point.
> 	(rs6000_mangle_type): Use separate manglings for __ibm128 and
> 	__float128.  Change __float128 mangling from U10__float128 to
> 	u10__float128.  Issue a warning that the mangling has changed in
> 	GCC 8.
Michael Meissner April 17, 2018, 4:29 p.m. | #5
On Tue, Apr 17, 2018 at 09:57:52AM -0500, Segher Boessenkool wrote:
> On Mon, Apr 16, 2018 at 03:22:16PM -0400, Michael Meissner wrote:
> > Here is the PR 85075 patch without the rs6000.md bits:
> 
> This fails on powerpc64-linux bootstrap (w/ --with-cpu=power7 if that
> matters):
> 
> /home/segher/src/gcc/libgcc/config/rs6000/ibm-ldouble.c: In function '__gcc_qadd
> ':
> /home/segher/src/gcc/libgcc/config/rs6000/ibm-ldouble.c:157:1: error: insn does 
> not satisfy its constraints:
>  }
>  ^
> (insn 144 197 198 15 (set (reg:TF 32 0 [orig:143 _47 ] [143])
>         (unspec:TF [
>                 (reg:DF 33 1 [orig:143 _47+8 ] [143])
>                 (reg/v:DF 36 4 [orig:139 xl ] [139])
>             ] UNSPEC_PACK_128BIT)) "/home/segher/src/gcc/libgcc/config/rs6000/ib
> m-ldouble.c":106 1003 {packtf}
>      (nil))
> during RTL pass: reload

Yes, you need the patch for 85358 applied (which you've approved, but I haven't
checked in yet).  That in fact is why I needed to patch rs6000.md in the
original patch.
Michael Meissner April 17, 2018, 4:38 p.m. | #6
On Tue, Apr 17, 2018 at 12:29:31PM -0400, Michael Meissner wrote:
> On Tue, Apr 17, 2018 at 09:57:52AM -0500, Segher Boessenkool wrote:
> > On Mon, Apr 16, 2018 at 03:22:16PM -0400, Michael Meissner wrote:
> > > Here is the PR 85075 patch without the rs6000.md bits:
> > 
> > This fails on powerpc64-linux bootstrap (w/ --with-cpu=power7 if that
> > matters):
> > 
> > /home/segher/src/gcc/libgcc/config/rs6000/ibm-ldouble.c: In function '__gcc_qadd
> > ':
> > /home/segher/src/gcc/libgcc/config/rs6000/ibm-ldouble.c:157:1: error: insn does 
> > not satisfy its constraints:
> >  }
> >  ^
> > (insn 144 197 198 15 (set (reg:TF 32 0 [orig:143 _47 ] [143])
> >         (unspec:TF [
> >                 (reg:DF 33 1 [orig:143 _47+8 ] [143])
> >                 (reg/v:DF 36 4 [orig:139 xl ] [139])
> >             ] UNSPEC_PACK_128BIT)) "/home/segher/src/gcc/libgcc/config/rs6000/ib
> > m-ldouble.c":106 1003 {packtf}
> >      (nil))
> > during RTL pass: reload
> 
> Yes, you need the patch for 85358 applied (which you've approved, but I haven't
> checked in yet).  That in fact is why I needed to patch rs6000.md in the
> original patch.

Whoops, it is 85424, not 85835.

And note, you will get a lot of warnings when building libstc++-v3 with the PR
85075 patch, due to the new warning that __float128 changed the name mangling.
I probably should look to see if there is a way to add -Wno-psabi to the
libstdc++-v3 flags on the PowerPC.
Joseph Myers April 24, 2018, 5:42 p.m. | #7
On Mon, 16 Apr 2018, Segher Boessenkool wrote:

> > The manglings that are now used are:
> > 
> > For -mabi=ieeelongdouble:
> > 
> > 	__float128	"u10__float128"
> > 	__ibm128	"u8__ibm128"
> > 	long double	"u9__ieee128"
> > 
> > For -mabi=ibmlongdouble:
> > 
> > 	__float128	"u10__float128"
> > 	__ibm128	"u8__ibm128"
> > 	long double	"g"
> > 
> > For -mlong-double-64:
> > 
> > 	__float128	"u10__float128"
> > 	__ibm128	"u8__ibm128"
> > 	long double	"e"
> 
> If __float128 is the same type as _Float128, as which of those should
> it be mangled?  The C++ ABI has "DF" for _FloatN, but the demangler uses
> that same code for fixed points types.  Ugh.
> 
> I don't think mangling "long double" as "u9__ieee128" works well with for
> example GDB.
> 
> Cc:ing Joseph Myers; Joseph, do you have any advice here?

I believe it has been stated that the goal is for IEEE long double not to 
require separate multilibs of GCC's libraries; that is, for both libgcc 
and libstdc++ to provide all the required functions under appropriate 
names, whichever is the default when GCC is built, and for the right 
functions to be used automatically.

For libgcc, this is achieved by the existing *tf* names continuing to be 
bound to IBM long double, and new *kf* names being used for IEEE long 
double.  (I don't know if the correct functions now get built for both 
choices of the default ABI - i.e. all *tf* functions, including those from 
libgcc2.c, always being built for IBM long double even when TFmode is IEEE 
long double, all *kf* functions always being built for IEEE long double, 
and the compiler always generating calls to the correct functions for 
IFmode, KFmode and TFmode, whichever format TFmode has.  But if there are 
any remaining issues in this area, they are orthogonal to the C++ issues.)

For libstdc++, avoiding multilibs means the same set of mangled names 
should be present, with the same ABIs, regardless of the default ABI.  
This is why, for example, the existing IBM long double uses "g" rather 
than "e" (the normal long double mangling) - because when long double 
originally had the same ABI as double, that meant "e" symbols were used 
for that 64-bit long double.

It is of course possible for different files in libstdc++ to be built with 
different ABI options (given the existing use of -mno-gnu-attribute for 
building libstdc++ to avoid this causing linker errors for incompatible 
ABIs), and for symbols using one mangled name for a given floating-point 
format to be aliases for symbols using another mangled name for that 
format.  And whereas libstdc++ needs to support long double, whatever type 
long double is in that particular compilation, it's less clear if it needs 
to provide much if any support for the other types (although the compiler 
needs to).

The requirement for _Float128 to be different from long double even if 
they have the same format is a C requirement coming from TS 18661-3.  The 
_FloatN names are deliberately not supported for C++ in GCC, because of an 
expectation that any C++ binding for types for particular floating-point 
formats would be class-based, given that was the approach C++ chose for 
decimal floating point (rather than the C _DecimalN approach).  glibc 
headers do "typedef long double _Float128;" in the C++ case where long 
double has the correct format, so the distinct _Float128 type is not 
normally accessible from C++ in that case.  However, you *can* access 
those _FloatN types via typeof and built-in functions, resulting in ICEs 
for which I've just filed bug 85518.

Returning to the long double, __ibm128 and __float128 types, I suppose 
there are questions:

* Which types need to be different types at the C++ language level?  If 
people do want to use these types in templates and overloads, I suppose 
that indicates always having three separate types as you suggest.

* Where does __ieee128 fit in?

* Where does __typeof (__builtin_inff128 ()) (GCC's internal _Float128 
type, cf. bug 85518) fit in?

* What is the mangling for all those types?

* Which types are supported by libstdc++ (in that it's valid to use them 
as arguments to libstdc++ functions / templates)?

* Which function names are provided by libstdc++ (possibly as aliases)?

The "DF<number>_" mangling was introduced to distinguish _Float16 from 
__fp16, see <https://github.com/itanium-cxx-abi/cxx-abi/issues/21>.  *If* 
it were decided to address bug 85518 by generically supporting mangling 
for the not-quite-hidden-for-C++ _FloatN types (as opposed to arranging 
for float64_type_node etc. to actually be copies of double etc. for C++, 
or for the types to otherwise be completely hidden), I suppose it would be 
natural to use that mangling for those types - but the C++ ABI would need 
to be extended to cover _FloatNx as well if that bug is to be completely 
fixed that way.  (And this ignores the fixed-point issue - I don't know 
why that support is in the demangler, since we don't support fixed-point 
for C++, though I suppose mode attributes might allow fixed-point to creep 
into C++ code anyway - bug 39059 was constants formerly allowing them into 
C++.)

As I understand the proposed patch, it would mean __float128 and __ieee128 
are always aliases for the not-quite-hidden _Float128 type.  In that case, 
generic DF128_ mangling would apply to those.  __ibm128, being always 
different from long double after the patch, would then have u8__ibm128 
mangling as suggested.  Making __float128 always different from long 
double would mean *some* different mangling for IEEE long double would be 
needed (which would not be the same as the _Float128 mangling).

Then libstdc++ would need to contain, independent of the default ABI used 
by the compiler, the "e" functions (aliases / wrappers for "d" ones), the 
"g" functions (existing IBM long double functions), and functions for the 
new mangling for IEEE long double.  It might or might not have functions / 
aliases (and typeinfo etc.) that can be used for __ibm128 or __float128.

I don't know what if anything GDB would then need to handle the new 
mangling.
Segher Boessenkool May 14, 2018, 1:04 p.m. | #8
On Tue, Apr 24, 2018 at 05:42:39PM +0000, Joseph Myers wrote:
> On Mon, 16 Apr 2018, Segher Boessenkool wrote:
> 
> > > The manglings that are now used are:
> > > 
> > > For -mabi=ieeelongdouble:
> > > 
> > > 	__float128	"u10__float128"
> > > 	__ibm128	"u8__ibm128"
> > > 	long double	"u9__ieee128"
> > > 
> > > For -mabi=ibmlongdouble:
> > > 
> > > 	__float128	"u10__float128"
> > > 	__ibm128	"u8__ibm128"
> > > 	long double	"g"
> > > 
> > > For -mlong-double-64:
> > > 
> > > 	__float128	"u10__float128"
> > > 	__ibm128	"u8__ibm128"
> > > 	long double	"e"
> > 
> > If __float128 is the same type as _Float128, as which of those should
> > it be mangled?  The C++ ABI has "DF" for _FloatN, but the demangler uses
> > that same code for fixed points types.  Ugh.
> > 
> > I don't think mangling "long double" as "u9__ieee128" works well with for
> > example GDB.
> > 
> > Cc:ing Joseph Myers; Joseph, do you have any advice here?
> 
> I believe it has been stated that the goal is for IEEE long double not to 
> require separate multilibs of GCC's libraries; that is, for both libgcc 
> and libstdc++ to provide all the required functions under appropriate 
> names, whichever is the default when GCC is built, and for the right 
> functions to be used automatically.

Yes, as long as no incompatible ABI is required, and that is part of
why currently ieee128 is only supported on systems with VSX.  Supporting
it on other systems sould be akin to soft float.

> For libgcc, this is achieved by the existing *tf* names continuing to be 
> bound to IBM long double, and new *kf* names being used for IEEE long 
> double.  (I don't know if the correct functions now get built for both 
> choices of the default ABI - i.e. all *tf* functions, including those from 
> libgcc2.c, always being built for IBM long double even when TFmode is IEEE 
> long double, all *kf* functions always being built for IEEE long double, 
> and the compiler always generating calls to the correct functions for 
> IFmode, KFmode and TFmode, whichever format TFmode has.  But if there are 
> any remaining issues in this area, they are orthogonal to the C++ issues.)

I checked, and it seems to work correctly.

> For libstdc++, avoiding multilibs means the same set of mangled names 
> should be present, with the same ABIs, regardless of the default ABI.  

Yes.

> This is why, for example, the existing IBM long double uses "g" rather 
> than "e" (the normal long double mangling) - because when long double 
> originally had the same ABI as double, that meant "e" symbols were used 
> for that 64-bit long double.

So we need a new mangling for IEEE 128-bit float.  Mangling it the same
as the "__ieee128" type is probably going to cause problems, and at the
very least it is a confusing name.

(The demangler shows "e" as "long double", but it shows "g" as "__float128",
which is wrong; adding "__ieee128" to the mix will not help).

> Returning to the long double, __ibm128 and __float128 types, I suppose 
> there are questions:
> 
> * Which types need to be different types at the C++ language level?  If 
> people do want to use these types in templates and overloads, I suppose 
> that indicates always having three separate types as you suggest.
> 
> * Where does __ieee128 fit in?
> 
> * Where does __typeof (__builtin_inff128 ()) (GCC's internal _Float128 
> type, cf. bug 85518) fit in?
> 
> * What is the mangling for all those types?
> 
> * Which types are supported by libstdc++ (in that it's valid to use them 
> as arguments to libstdc++ functions / templates)?
> 
> * Which function names are provided by libstdc++ (possibly as aliases)?

Yes, lots of questions :-(

> The "DF<number>_" mangling was introduced to distinguish _Float16 from 
> __fp16, see <https://github.com/itanium-cxx-abi/cxx-abi/issues/21>.  *If* 
> it were decided to address bug 85518 by generically supporting mangling 
> for the not-quite-hidden-for-C++ _FloatN types (as opposed to arranging 
> for float64_type_node etc. to actually be copies of double etc. for C++, 
> or for the types to otherwise be completely hidden), I suppose it would be 
> natural to use that mangling for those types - but the C++ ABI would need 
> to be extended to cover _FloatNx as well if that bug is to be completely 
> fixed that way.  (And this ignores the fixed-point issue - I don't know 
> why that support is in the demangler, since we don't support fixed-point 
> for C++, though I suppose mode attributes might allow fixed-point to creep 
> into C++ code anyway - bug 39059 was constants formerly allowing them into 
> C++.)

And another, in generic code.

> As I understand the proposed patch, it would mean __float128 and __ieee128 
> are always aliases for the not-quite-hidden _Float128 type.  In that case, 
> generic DF128_ mangling would apply to those.  __ibm128, being always 
> different from long double after the patch, would then have u8__ibm128 
> mangling as suggested.  Making __float128 always different from long 
> double would mean *some* different mangling for IEEE long double would be 
> needed (which would not be the same as the _Float128 mangling).

Agreed on all these.

> Then libstdc++ would need to contain, independent of the default ABI used 
> by the compiler, the "e" functions (aliases / wrappers for "d" ones), the 
> "g" functions (existing IBM long double functions), and functions for the 
> new mangling for IEEE long double.  It might or might not have functions / 
> aliases (and typeinfo etc.) that can be used for __ibm128 or __float128.

Yup.

> I don't know what if anything GDB would then need to handle the new 
> mangling.

(This is primarily a demangler problem).

If there are different manglings for long double, GDB should be able
to distinguish between them some way.  Not that people have seemed to
mind so far.  But at least the demangled names should make sense: "g"
is "long double", but it shows as "__float128", which is a different
type, with a different representation too (depending on options).


Segher

Patch

Index: gcc/config/rs6000/rs6000-c.c
===================================================================
--- gcc/config/rs6000/rs6000-c.c	(revision 259376)
+++ gcc/config/rs6000/rs6000-c.c	(working copy)
@@ -617,8 +617,6 @@  rs6000_cpu_cpp_builtins (cpp_reader *pfi
     builtin_define ("__RSQRTEF__");
   if (TARGET_FLOAT128_TYPE)
     builtin_define ("__FLOAT128_TYPE__");
-  if (TARGET_LONG_DOUBLE_128 && FLOAT128_IBM_P (TFmode))
-    builtin_define ("__ibm128=long double");
 #ifdef TARGET_LIBC_PROVIDES_HWCAP_IN_TCB
   builtin_define ("__BUILTIN_CPU_SUPPORTS__");
 #endif
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 259376)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -16994,28 +16994,22 @@  rs6000_init_builtins (void)
      For IEEE 128-bit floating point, always create the type __ieee128.  If the
      user used -mfloat128, rs6000-c.c will create a define from __float128 to
      __ieee128.  */
-  if (TARGET_LONG_DOUBLE_128 && FLOAT128_IEEE_P (TFmode))
+  if (TARGET_FLOAT128_TYPE)
     {
       ibm128_float_type_node = make_node (REAL_TYPE);
       TYPE_PRECISION (ibm128_float_type_node) = 128;
       SET_TYPE_MODE (ibm128_float_type_node, IFmode);
       layout_type (ibm128_float_type_node);
-
       lang_hooks.types.register_builtin_type (ibm128_float_type_node,
 					      "__ibm128");
-    }
-  else
-    ibm128_float_type_node = long_double_type_node;
 
-  if (TARGET_FLOAT128_TYPE)
-    {
       ieee128_float_type_node = float128_type_node;
       lang_hooks.types.register_builtin_type (ieee128_float_type_node,
 					      "__ieee128");
     }
 
   else
-    ieee128_float_type_node = long_double_type_node;
+    ieee128_float_type_node = ibm128_float_type_node = long_double_type_node;
 
   /* Initialize the modes for builtin_function_type, mapping a machine mode to
      tree type node.  */
@@ -32902,24 +32896,32 @@  rs6000_mangle_type (const_tree type)
   if (type == bool_int_type_node) return "U6__booli";
   if (type == bool_long_long_type_node) return "U6__boolx";
 
-  /* Use a unique name for __float128 rather than trying to use "e" or "g". Use
-     "g" for IBM extended double, no matter whether it is long double (using
-     -mabi=ibmlongdouble) or the distinct __ibm128 type.  */
-  if (TARGET_FLOAT128_TYPE)
-    {
-      if (type == ieee128_float_type_node)
-	return "U10__float128";
+  /* Use a unique name for __float128/__ibm128 rather than trying to use "e" or
+     "g".  While, "g" in theory should be used for __float128, the PowerPC
+     compiler has used "g" for IBM extended double for a long time.  Use
+     u10__float128 for the separate __float128 type (_Float128 in C), and
+     u9__ieee128 for long double when -mabi=ieeelongdouble is used.
 
-      if (TARGET_LONG_DOUBLE_128)
+     GCC 6/7 used U10__float128 instead of u10__float128.  */
+  if (type == ieee128_float_type_node)
+    {
+      static bool warned;
+      if (!warned && warn_psabi)
 	{
-	  if (type == long_double_type_node)
-	    return (TARGET_IEEEQUAD) ? "U10__float128" : "g";
-
-	  if (type == ibm128_float_type_node)
-	    return "g";
+	  warned = true;
+	  inform (input_location,
+		  "the name mangling for __float128 types changed in GCC 8");
 	}
+      return "u10__float128";
     }
 
+  if (type == ibm128_float_type_node)
+    return "u8__ibm128";
+
+  if (TARGET_FLOAT128_TYPE && TARGET_LONG_DOUBLE_128
+      && type == long_double_type_node)
+    return (TARGET_IEEEQUAD) ? "u9__ieee128" : "g";
+
   /* Mangle IBM extended float long double as `g' (__float128) on
      powerpc*-linux where long-double-64 previously was the default.  */
   if (TYPE_MAIN_VARIANT (type) == long_double_type_node
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(revision 259376)
+++ gcc/config/rs6000/rs6000.md	(working copy)
@@ -13934,16 +13934,14 @@  (define_insn_and_split "unpack<mode>_nod
    (set_attr "length" "4")])
 
 (define_insn_and_split "pack<mode>"
-  [(set (match_operand:FMOVE128 0 "register_operand" "=d,&d")
+  [(set (match_operand:FMOVE128 0 "register_operand" "=&d")
 	(unspec:FMOVE128
-	 [(match_operand:<FP128_64> 1 "register_operand" "0,d")
-	  (match_operand:<FP128_64> 2 "register_operand" "d,d")]
+	 [(match_operand:<FP128_64> 1 "register_operand" "d")
+	  (match_operand:<FP128_64> 2 "register_operand" "d")]
 	 UNSPEC_PACK_128BIT))]
   "FLOAT128_2REG_P (<MODE>mode)"
-  "@
-   fmr %L0,%2
-   #"
-  "&& reload_completed && REGNO (operands[0]) != REGNO (operands[1])"
+  "#"
+  "&& reload_completed"
   [(set (match_dup 3) (match_dup 1))
    (set (match_dup 4) (match_dup 2))]
 {
@@ -13956,8 +13954,8 @@  (define_insn_and_split "pack<mode>"
   operands[3] = gen_rtx_REG (<FP128_64>mode, dest_hi);
   operands[4] = gen_rtx_REG (<FP128_64>mode, dest_lo);
 }
-  [(set_attr "type" "fpsimple,fp")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "fp")
+   (set_attr "length" "8")])
 
 (define_insn "unpack<mode>"
   [(set (match_operand:DI 0 "register_operand" "=wa,wa")
Index: gcc/testsuite/g++.dg/pr85075-1.C
===================================================================
--- gcc/testsuite/g++.dg/pr85075-1.C	(revision 0)
+++ gcc/testsuite/g++.dg/pr85075-1.C	(revision 0)
@@ -0,0 +1,58 @@ 
+// { dg-do compile { target { powerpc*-*-linux* } } }
+// { dg-require-effective-target ppc_float128_sw }
+// { dg-options "-mvsx -mfloat128 -O2 -mabi=ieeelongdouble -Wno-psabi" } */
+
+// PR 85075
+// If you used a template for both long double and __float128, it would
+// complain that the same mangling was used for different types.  Previously,
+// __float128 was defined to __ieee128 (the keyword where the the _Float128
+// type is defined).  Note, __float128 is defined to be 'long double' if
+// -mabi=ieeelongdouble is used.
+
+template <class __T> inline bool
+iszero (__T __val)
+{
+  return __val == 0;
+}
+
+#ifdef _ARCH_PWR7
+#ifdef __LONG_DOUBLE_IEEE128__
+#define LD_CONSTRAINT "wa"
+#else
+#define LD_CONSTRAINT "d"
+#endif
+#endif
+
+int
+use_template (void)
+{
+  long double q1 = 0.0l;
+  __float128 q = 0.0q;
+
+#ifdef _ARCH_PWR7
+  __asm__ (" # %x0, %x1" : "+" LD_CONSTRAINT (q1), "+wa" (q));
+#endif
+
+  return iszero (q1) + iszero (q);
+}
+
+class foo {
+public:
+  foo () {}
+  ~foo () {}
+  inline bool iszero (long double ld) { return ld == 0.0L; }
+  inline bool iszero (__float128 f128) { return f128 == 0.0Q; }
+} st;
+
+int
+use_class (void)
+{
+  long double q1 = 0.0l;
+  __float128 q = 0.0q;
+
+#ifdef _ARCH_PWR7
+  __asm__ (" # %x0, %x1" : "+" LD_CONSTRAINT (q1), "+wa" (q));
+#endif
+
+  return st.iszero (q1) + st.iszero (q);
+}
Index: gcc/testsuite/g++.dg/pr85075-2.C
===================================================================
--- gcc/testsuite/g++.dg/pr85075-2.C	(revision 0)
+++ gcc/testsuite/g++.dg/pr85075-2.C	(revision 0)
@@ -0,0 +1,58 @@ 
+// { dg-do compile { target { powerpc*-*-linux* } } }
+// { dg-require-effective-target ppc_float128_sw }
+// { dg-options "-mvsx -mfloat128 -O2 -mabi=ibmlongdouble -Wno-psabi" } */
+
+// PR 85075
+// If you used a template for both long double and __float128, it would
+// complain that the same mangling was used for different types.  Previously,
+// __float128 was defined to __ieee128 (the keyword where the the _Float128
+// type is defined).  Note, __float128 is defined to be 'long double' if
+// -mabi=ieeelongdouble is used.
+
+template <class __T> inline bool
+iszero (__T __val)
+{
+  return __val == 0;
+}
+
+#ifdef _ARCH_PWR7
+#ifdef __LONG_DOUBLE_IEEE128__
+#define LD_CONSTRAINT "wa"
+#else
+#define LD_CONSTRAINT "d"
+#endif
+#endif
+
+int
+use_template (void)
+{
+  long double q1 = 0.0l;
+  __float128 q = 0.0q;
+
+#ifdef _ARCH_PWR7
+  __asm__ (" # %x0, %x1" : "+" LD_CONSTRAINT (q1), "+wa" (q));
+#endif
+
+  return iszero (q1) + iszero (q);
+}
+
+class foo {
+public:
+  foo () {}
+  ~foo () {}
+  inline bool iszero (long double ld) { return ld == 0.0L; }
+  inline bool iszero (__float128 f128) { return f128 == 0.0Q; }
+} st;
+
+int
+use_class (void)
+{
+  long double q1 = 0.0l;
+  __float128 q = 0.0q;
+
+#ifdef _ARCH_PWR7
+  __asm__ (" # %x0, %x1" : "+" LD_CONSTRAINT (q1), "+wa" (q));
+#endif
+
+  return st.iszero (q1) + st.iszero (q);
+}
Index: gcc/testsuite/g++.dg/pr85075-3.C
===================================================================
--- gcc/testsuite/g++.dg/pr85075-3.C	(revision 0)
+++ gcc/testsuite/g++.dg/pr85075-3.C	(revision 0)
@@ -0,0 +1,58 @@ 
+// { dg-do compile { target { powerpc*-*-linux* } } }
+// { dg-require-effective-target ppc_float128_sw }
+// { dg-options "-mvsx -mfloat128 -O2 -mlong-double-64 -Wno-psabi" } */
+
+// PR 85075
+// If you used a template for both long double and __float128, it would
+// complain that the same mangling was used for different types.  Previously,
+// __float128 was defined to __ieee128 (the keyword where the the _Float128
+// type is defined).  Note, __float128 is defined to be 'long double' if
+// -mabi=ieeelongdouble is used.
+
+template <class __T> inline bool
+iszero (__T __val)
+{
+  return __val == 0;
+}
+
+#ifdef _ARCH_PWR7
+#ifdef __LONG_DOUBLE_IEEE128__
+#define LD_CONSTRAINT "wa"
+#else
+#define LD_CONSTRAINT "d"
+#endif
+#endif
+
+int
+use_template (void)
+{
+  long double q1 = 0.0l;
+  __float128 q = 0.0q;
+
+#ifdef _ARCH_PWR7
+  __asm__ (" # %x0, %x1" : "+" LD_CONSTRAINT (q1), "+wa" (q));
+#endif
+
+  return iszero (q1) + iszero (q);
+}
+
+class foo {
+public:
+  foo () {}
+  ~foo () {}
+  inline bool iszero (long double ld) { return ld == 0.0L; }
+  inline bool iszero (__float128 f128) { return f128 == 0.0Q; }
+} st;
+
+int
+use_class (void)
+{
+  long double q1 = 0.0l;
+  __float128 q = 0.0q;
+
+#ifdef _ARCH_PWR7
+  __asm__ (" # %x0, %x1" : "+" LD_CONSTRAINT (q1), "+wa" (q));
+#endif
+
+  return st.iszero (q1) + st.iszero (q);
+}