Bug 26374 - Compile failure on long double
Summary: Compile failure on long double
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.1.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
: 26462 27054 31321 (view as bug list)
Depends on: 19779
Blocks: 88204
  Show dependency treegraph
 
Reported: 2006-02-19 21:59 UTC by Dirk Mueller
Modified: 2024-04-24 06:52 UTC (History)
12 users (show)

See Also:
Host:
Target: powerpc-*-*
Build:
Known to work:
Known to fail:
Last reconfirmed: 2013-12-26 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dirk Mueller 2006-02-19 21:59:24 UTC
=== Cut ===
static const double  coeff[] = { 1.0l/42 };
=== Cut ===

gives: 

testcase.c:1: error: initializer element is not constant
testcase.c:1: error: (near initialization for ‘coeff[0]’)
Comment 1 Andrew Pinski 2006-02-19 22:01:38 UTC
This is actually because the middle-end does not constant fold 128bit IBM long double.  I am assuming you are using -mlong-double-128.
Comment 2 Andrew Pinski 2006-02-19 22:02:23 UTC
Which is PR 19779.
Comment 3 Richard Biener 2006-02-19 22:03:39 UTC
I'm not sure 1.0l/42 is a valid constant initializer.
Comment 4 Dirk Mueller 2006-02-19 22:04:44 UTC
yes, full configure line: 

Target: powerpc64-suse-linux
Configured with: ../configure --enable-threads=posix --prefix=/usr --with-local-prefix=/usr/local --infodir=/usr/share/info --mandir=/usr/share/man --libdir=/usr/lib64 --libexecdir=/usr/lib64 --enable-languages=c,c++,objc,fortran,java --enable-checking=release --with-gxx-include-dir=/usr/include/c++/4.1.0 --enable-ssp --disable-libssp --enable-java-awt=gtk --disable-libjava-multilib --with-slibdir=/lib64 --with-system-zlib --enable-shared --enable-__cxa_atexit --enable-libstdcxx-allocator=new --without-system-libunwind --enable-secureplt --with-long-double-128 --host=powerpc64-suse-linux
Comment 5 Dirk Mueller 2006-02-19 22:20:37 UTC
hmm, I guess I'm find with resolving this as duplicate to 19779, even though I don't understand why this is only an issue on PPC for me..

Comment 6 Andrew Pinski 2006-02-19 22:24:49 UTC
(In reply to comment #5)
> hmm, I guess I'm find with resolving this as duplicate to 19779, even though I
> don't understand why this is only an issue on PPC for me..

It is because the long double format used on PPC is IBM's 128bit long double which is two doubles basicially added together.
Comment 7 Andrew Pinski 2006-02-20 19:33:44 UTC
Confirmed.
Comment 8 Andrew Pinski 2006-02-24 21:04:14 UTC
*** Bug 26462 has been marked as a duplicate of this bug. ***
Comment 9 Andrew Pinski 2006-04-06 16:13:56 UTC
*** Bug 27054 has been marked as a duplicate of this bug. ***
Comment 10 David Woodhouse 2006-12-28 14:32:09 UTC
Any progress on this?
Comment 11 Andrew Pinski 2006-12-28 14:48:01 UTC
(In reply to comment #10)
> Any progress on this?
There are two way of fixing this as far as I can see:
teach real.c about how to fold IBM 128bit long double format
use MPFR instead

I would use the latter if I got any time but I don't have any time to do either.
Comment 12 Andrew Pinski 2007-03-22 23:49:57 UTC
*** Bug 31321 has been marked as a duplicate of this bug. ***
Comment 13 Jackie Rosen 2014-02-16 13:12:36 UTC Comment hidden (spam)
Comment 14 beebe 2022-03-08 18:36:23 UTC
>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=26374

That is a really old one, from early 2006; I would have hoped that it
had long since been repaired in gcc.

However, I just checked my VM for CentOS 7 on PowerPC, and found this:

	% cat foo.c
	static const double x = 1.0L / 42 ;

	% /usr/bin/gcc -c foo.c
	foo.c:1:1: error: initializer element is not computable at load time
	 static const double x = 1.0L / 42 ;

That is gcc-4.8.5 (20150623 (Red Hat 4.8.5-44)).

I recently built gcc-8.5.0 on that system, and it raises the same
error.

Changing 42 to 42.0L to have a pure long-double expression does not
eliminate the error with either compiler.

The assignment is perfectly legal in all ISO Standards for C from 1989
to date, and the expression must be evaluated to IEEE 754 requirements
by the compiler, producing a correctly rounded result.  That latter
would not be possible if it were expressed as a fractional value,
because the C Standards do not require correct conversion of decimal
fractions to binary fractions.

The build of gcc-8.5.0 took five days on this qemu-emulated CPU, so it
really is not practical for me to try the test file with gcc-9 through
gcc-12 versions.  I needed 8.5.0 to be able to build TeX Live 2022:
see

	http://www.math.utah.edu/pub/texlive-utah/#centos-7-ppc64be

for my report (and many others elsewhere in that Web page).

-------------------------------------------------------------------------------
- Nelson H. F. Beebe                    Tel: +1 801 581 5254                  -
- University of Utah                    FAX: +1 801 581 4148                  -
- Department of Mathematics, 110 LCB    Internet e-mail: beebe@math.utah.edu  -
- 155 S 1400 E RM 233                       beebe@acm.org  beebe@computer.org -
- Salt Lake City, UT 84112-0090, USA    URL: http://www.math.utah.edu/~beebe/ -
-------------------------------------------------------------------------------
Comment 15 Andrew Pinski 2022-03-08 18:43:42 UTC
(In reply to beebe from comment #14)
> >> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=26374
> 
> That is a really old one, from early 2006; I would have hoped that it
> had long since been repaired in gcc.
> 
> However, I just checked my VM for CentOS 7 on PowerPC, and found this:

Well powerpc currently uses what is called double double for 128bit long double. GCC does not know how to constant fold that nicely. But powerpc linux targets are moving over to use standard 128bit IEEE long double and IIRC for GCC 12 (or is it 13) will default to IEEE long double so this will be less of an issue.
Comment 16 Jakub Jelinek 2022-03-08 20:22:13 UTC
(In reply to Andrew Pinski from comment #15)
> (In reply to beebe from comment #14)
> > >> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=26374
> > 
> > That is a really old one, from early 2006; I would have hoped that it
> > had long since been repaired in gcc.
> > 
> > However, I just checked my VM for CentOS 7 on PowerPC, and found this:
> 
> Well powerpc currently uses what is called double double for 128bit long
> double. GCC does not know how to constant fold that nicely. But powerpc
> linux targets are moving over to use standard 128bit IEEE long double and
> IIRC for GCC 12 (or is it 13) will default to IEEE long double so this will
> be less of an issue.

Will not default to unless configured so, but e.g. in Fedora 36 GCC 12 is configured to default to long double being IEEE quad on powerpc64 little endian.
As for constant folding, even with double double gcc is able to fold some constant arithmetics in that format, but because the emulation is only approximate (it pretends it is 106-bit precision format while in reality it is variable precision up to some thousands depending on the exact values).
As has been said elsewhere, the emulation would be implementable if gcc handled double double in all the arithmetics as a pair of doubles with all the rules for it.  But e.g. mpfr/libmpc isn't able to do something like that, so we'd need to compute everything with much bigger precision etc.
In any case, I think nobody is going to work on it now that ppc64le is switching to IEEE quad.
Comment 17 beebe 2022-03-08 20:40:40 UTC
>> ... powerpc currently uses what is called double double for 128bit
>> long double. GCC does not know how to constant fold that nicely.

Yes, I know about the double double format that IBM, SGI, and possibly
others introduced in the 1990s for implementing long double.  I
strongly disapprove of that decision, and wrote about it extensively
in my big book

	The Mathematical-Function Computation Handbook
	https://doi.org/10.1007/978-3-319-64110-2
	http://www.math.utah.edu/pub/tex/bib/master.html#Beebe:2017:MFC

that addresses accurate computation in binary and decimal arithmetic,
for IEEE 754, and also for some important historical floating-point
designs.

>> GCC does not know how to constant fold that nicely.

Because gcc has used gmp for several years now for correctly rounded
conversions of decimal numbers to binary IEEE 754 formats, I would
have thought that handling a constant expression like "1.0L / 42.0L"
would have been relatively trivial.

>> powerpc linux targets are moving over to use standard 128bit IEEE
>> long double and IIRC for GCC 12 (or is it 13) will default to IEEE
>> long double so this will be less of an issue.

Thanks for that interesting news!  It is a big change, because it
affects both -lc and -lm libraries, plus lots of user code.  

The IBM POWER architecture was introduced to the world in February
1990, and we here in Utah had some of the earliest models available,
so now that we are 2**5 years later, it is high time to conform to
IEEE 754.

POWER made a big impact for those who learned how to exploit its
interesting features.  I wrote about it here:

	High-Performance Matrix Multiplication
	http://www.math.utah.edu/pub/benchmarks/usirep.pdf

That document showed there that a 44x performance boost was possible
in some cases, without leaving standard programming languages for
assembly code fragments.

I wrote a lot more about the importance of understanding architecture
and memory designs it here:

	The Impact of Memory and Architecture on Computer Performance
	http://www.math.utah.edu/~beebe/memperf.pdf

-------------------------------------------------------------------------------
- Nelson H. F. Beebe                    Tel: +1 801 581 5254                  -
- University of Utah                    FAX: +1 801 581 4148                  -
- Department of Mathematics, 110 LCB    Internet e-mail: beebe@math.utah.edu  -
- 155 S 1400 E RM 233                       beebe@acm.org  beebe@computer.org -
- Salt Lake City, UT 84112-0090, USA    URL: http://www.math.utah.edu/~beebe/ -
-------------------------------------------------------------------------------
Comment 18 Jakub Jelinek 2022-03-08 20:45:29 UTC
Note, for the time being only little endian powerpc64 can switch (I think only power9 and later have hw support for IEEE quad and in the ABI it is passed in Altivec/VSX registers.  ppc64le only supports power8 and later CPUs.
Comment 19 beebe 2022-03-08 21:04:03 UTC
Thanks for the further comments on PowerPC, double double as fake long
double, and the news of gcc-12 on Fedora 36 for that CPU.  I'll soon
build a VM to get access to that combination.  I have VMs already for
PowerPC on CentOS 7 (big endian), CentOS 8 (little endian), and Debian
10 (little endian).

Let's consider the initializer bug an "unfixed (mis)feature" of gcc
history, and move on to better arithmetic!

-------------------------------------------------------------------------------
- Nelson H. F. Beebe                    Tel: +1 801 581 5254                  -
- University of Utah                    FAX: +1 801 581 4148                  -
- Department of Mathematics, 110 LCB    Internet e-mail: beebe@math.utah.edu  -
- 155 S 1400 E RM 233                       beebe@acm.org  beebe@computer.org -
- Salt Lake City, UT 84112-0090, USA    URL: http://www.math.utah.edu/~beebe/ -
-------------------------------------------------------------------------------
Comment 20 David Edelsohn 2022-03-08 21:12:38 UTC
Double-double has advantages and disadvantages. You're welcome to debate William Kahan about the choice instead of making snarky comments here.
Comment 21 Vincent Lefèvre 2022-03-08 23:17:21 UTC
(In reply to Jakub Jelinek from comment #16)
> As for constant folding, even with double double gcc is able to fold some
> constant arithmetics in that format, but because the emulation is only
> approximate (it pretends it is 106-bit precision format while in reality it
> is variable precision up to some thousands depending on the exact values).
> As has been said elsewhere, the emulation would be implementable if gcc
> handled double double in all the arithmetics as a pair of doubles with all
> the rules for it.  But e.g. mpfr/libmpc isn't able to do something like
> that, so we'd need to compute everything with much bigger precision etc.

Well, the C standard does not require correct rounding, and while correct rounding is important for the IEEE formats, it is rather useless for the double-double format, whose goal was just to provide more precision than double, but still be rather fast (compared to quad emulation). The main drawback would be that results could be different whether a FP expression is evaluated at run time or at compile time, but unless users seek to control everything (e.g. with IEEE formats), they should get use to that (FYI, you can have the same kind of issues with the contraction of FP expressions, such as FMA generation from mul-add, which GCC enable by default). So, in short, doing the compile-time evaluation at a 106-bit precision or more would be acceptable IMHO, at least better than a compiler error.

Note: Even though double-double can be very interesting as a compromise between performance and accuracy, there exist various algorithms and which algorithm should be chosen depends on the context, which only the author of the program can know in general. Thus it was a bad idea to implement double-double as a native FP type (here, long double); instead, the selection of the algorithms should be left to the developer. So the switch to IEEE quad is a good thing. But for how long will old ABIs be around?
Comment 22 beebe 2022-03-11 17:35:46 UTC
Yesterday, I got a Fedora 36 PPC64LE VM up, and left it installing
hundreds of packages overnight.  QEMU 4.2.1 on Ubuntu 20.04 picks a
default CPU type of POWER9.  Alas, the ISO installation gets nicely
into a normal boot, then dies with a kernel panic.  I changed the
default CPU type to POWER8, and that led to a successful installation.

This morning, I built my feature test package

	http://www.math.utah.edu/pub/features/

and got this nice report back:

        LDBL_DECIMAL_DIG = 36
        LDBL_DIG         = 33
        LDBL_EPSILON     = 0x1p-112
        LDBL_HAS_SUBNORM = 1
        LDBL_MANT_DIG    = 113
        LDBL_MAX         = 0x1.ffffffffffffffffffffffffffffp+16383
        LDBL_MAX_10_EXP  = 4932
        LDBL_MAX_EXP     = 16384
        LDBL_MIN         = 0x1p-16382
        LDBL_MIN_10_EXP  = -4931
        LDBL_MIN_EXP     = -16381
        LDBL_NORM_MAX    = [not defined]
        LDBL_TRUE_MIN    = 0x0.0000000000000000000000000001p-16382
        HUGE_VALL        = inf
	...

	Computed long double limits:
		smallest floating-point number: 0.00000000e+00 == 2^(-16494)    [IEEE 754 smallest 128-bit subnormal]
		machine epsilon:                1.92592994e-34 == 2^(-112)      [IEEE 754 128-bit conformant]
		long double appears to be 128-bit value stored in 128-bit (16-byte) field

That indicates that long double implemented as doubled double is now
history on this platform, and that is good news for me.

Thanks for telling me about this change for Fedora on PowePC.



-------------------------------------------------------------------------------
- Nelson H. F. Beebe                    Tel: +1 801 581 5254                  -
- University of Utah                    FAX: +1 801 581 4148                  -
- Department of Mathematics, 110 LCB    Internet e-mail: beebe@math.utah.edu  -
- 155 S 1400 E RM 233                       beebe@acm.org  beebe@computer.org -
- Salt Lake City, UT 84112-0090, USA    URL: http://www.math.utah.edu/~beebe/ -
-------------------------------------------------------------------------------