https://compiler-explorer.com/z/K3GYY7Msc Testcase: #include <bit> #include <format> Compile on power64le with -O2 -std=c++23 -mcpu=power6 and optionally with -mlong-double-64
I think we need something like this in <bits/c++config.h> #ifndef __VSX__ # undef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT #endif Otherwise we might set the ALT128_COMPAT macro during configure, but then it becomes invalidated during compilation of user code if they "downgrade" to something that doesn't support ieee128, using -mcpu=power6 and/or -mlong-double-64
Mathias noted that still fails with -mcpu=power7 Checking for _ARCH_PWR8 or __POWER8_VECTOR__ instead works.
Adding Mike and Segher to correct me if I'm wrong on anything... :-) The canonical method for determining whether a specific cpu has VSX enabled or not is checking for "#if defined(_ARCH_PWR*) && defined(__VSX__)". I believe we're trying to move away from testing things like "__POWER8_VECTOR__". I seem to be blanking on the minimum cpu required for __ieee128, so I'll let Mike or Segher comment on that. I thought is was Power7, which would mean using _ARCH_PWR7 above, but given -mcpu=power7 still fails, maybe Power8 is the minimum needed for __ieee128 support? Mike and Segher???
The minimum architecture for IEEE 128-bit support is power7, because it needs the VSX registers to pass and return IEEE 128-bit values. Now, in theory, IEEE 128-bit support could have required only Altivec support (i.e. power6 adding -maltivec), but it was decided that the minimum processor to support IEEE 128-bit would be power7. Note, that the minimum CPU support for little endian is power8. So, using -mcpu=power6 or -mcpu=power7 on a LE system is not supported. On power8 systems, IEEE 128-bit is emulated in software. On power9 systems, IEEE 128-bit has hardware support. The macro __LONG_DOUBLE_IEEE128__ is defined if long double uses the IEEE 128-bit format, and __LONG_DOUBLE_IBM128__ is defined if long double uses the IBM 128-bit format that uses a pair of doubles.
(In reply to Michael Meissner from comment #4) > The macro __LONG_DOUBLE_IEEE128__ is defined if long double uses the IEEE > 128-bit format, and __LONG_DOUBLE_IBM128__ is defined if long double uses > the IBM 128-bit format that uses a pair of doubles. Yes, and libstdc++ relies on those heavily. But they isn't useful here, because those macros say what the *active* long double format is. The point of the _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT macro is to say that the library needs to support two long double formats at the same time. That is independent of which one happens to be active during a given compilation. There are files in libstdc++ which use both __ibm128 and __ieee128 in the same translation unit, but we need to not do that when __ieee128 is disabled by an option like -mlong-double-64 (In reply to Michael Meissner from comment #4) > Note, that the minimum CPU support for little endian is power8. So, using > -mcpu=power6 or -mcpu=power7 on a LE system is not supported. Ah! OK, so maybe this isn't an issue at all? The Compiler Explorer link in comment 0 is using power64le for both examples. If I switch the selected compilers to power64 (i.e. BE) there are no errors when using -mcpu=power6 or -mlong-double-64 But maybe that's because the compiler explorer VM for power64 BE has an old glibc without __float128 support in libm, and so in theory somebody could be running BE on a new glibc and need ALT128_COMPAT.
At least glibc on powerpc64 be I think doesn't have any __float128/_Float128 support I think.
OK, then ALT128_COMPAT is effectively only for LE. So I think I'll make whatever change is needed so that ALT128_COMPAT isn't defined for power6 LE and power7 LE, so the errors Matthias found don't happen. But I won't spend time trying to actually make it work well on the unsupported power6 LE combo.