Re: floating point types seems to need VSX support ?
On Fri, Oct 20, 2017 at 10:55:34PM -0400, Dennis Clarke wrote:
> WARNING : long and winding but full of examples.
>
>
> This is quite confusing with gcc 7.2.0 on latest ppc64 sid.
>
> nix_$ uname -a
> Linux nix 4.13.0-1-powerpc64 #1 SMP Debian 4.13.4-1 (2017-10-01) ppc64
> GNU/Linux
>
> nix_$ gcc --version
> gcc (Debian 7.2.0-11) 7.2.0
> Copyright (C) 2017 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.
>
>
> I have carefulyl checked the the data in memory to represent a specific
> constant should be perfect across big endian 64-bit architectures. At
> least that is my hope.
>
> So I attempt to use 128 bit long floating point data thus :
>
> nix_$ cat not_pi.c
>
> #include <stdio.h>
> #include <stdlib.h>
>
> /* note : see glibc source code
> sysdeps/ieee754/ldbl-128ibm/e_atan2l.c
> line 51 says :
> pi = 3.14159265358979323846264338327950280e+00L
> which is hex 4000921fb54442d18469898cc51701b8
> however that seems to not work
> */
>
> int main ( int argc, char* argv[])
> {
> long double pi_ld = 3.1415926535897932384626433832795028841971L;
>
> printf ( "sizeof(long double) = %2i\n", sizeof(long double) );
>
> printf ( " pi is not %38.36Lf\n", pi_ld );
>
> return ( EXIT_SUCCESS );
> }
>
> Compiles fine and prints out pi but the hex is wrong :
>
> nix_$ gcc -m64 -g -mlong-double-128 -o not_pi not_pi.c
> nix_$ gdb not_pi
> GNU gdb (GDB) 8.0.1
> Copyright (C) 2017 Free Software Foundation, Inc.
> License GPLv3+: GNU GPL version 3 or later
> <http://gnu.org/licenses/gpl.html>
> This is free software: you are free to change and redistribute it.
> There is NO WARRANTY, to the extent permitted by law. Type "show copying"
> and "show warranty" for details.
> This GDB was configured as "powerpc64-unknown-linux-gnu".
> Type "show configuration" for configuration details.
> For bug reporting instructions, please see:
> <http://www.gnu.org/software/gdb/bugs/>.
> Find the GDB manual and other documentation resources online at:
> <http://www.gnu.org/software/gdb/documentation/>.
> For help, type "help".
> Type "apropos word" to search for commands related to "word"...
> Reading symbols from not_pi...done.
> (gdb) break 19
> Breakpoint 1 at 0x9c0: file not_pi.c, line 19.
> (gdb) run
> Starting program: /home/dclarke/pgm/C/pi/not_pi
> sizeof(long double) = 16
>
> Breakpoint 1, main (argc=1, argv=0x7ffffffffa38) at not_pi.c:19
> 19 printf ( " pi is not %38.36Lf\n", pi_ld );
> (gdb) print pi_ld
> $1 = 3.1415926535897932384626433832794812
> (gdb) print &pi_ld
> $2 = (long double *) 0x7ffffffff5d0
> (gdb) x/16xb &pi_ld
> 0x7ffffffff5d0: 0x40 0x09 0x21 0xfb 0x54 0x44 0x2d 0x18
> 0x7ffffffff5d8: 0x3c 0xa1 0xa6 0x26 0x33 0x14 0x5c 0x06
> (gdb) cont
> Continuing.
> pi is not 3.141592653589793238462643383279481227
> [Inferior 1 (process 18815) exited normally]
> (gdb) quit
> nix_$
>
>
> The data in memory should be 0x4000921fb54442d18469898cc51701b8h.
> * * * It is not. * * *
>
> Clearly something else is at work here.
>
> However IF we do have exactly that value in memory and the IBM long
> double data type then we get even stranger results :
>
> nix_$ gcc -m64 -g -mabi=ieeelongdouble -o not_pi not_pi.c
> gcc: warning: using IEEE extended precision long double
> cc1: warning: using IEEE extended precision long double
>
> nix_$ gdb not_pi
> GNU gdb (GDB) 8.0.1
> Copyright (C) 2017 Free Software Foundation, Inc.
> License GPLv3+: GNU GPL version 3 or later
> <http://gnu.org/licenses/gpl.html>
> This is free software: you are free to change and redistribute it.
> There is NO WARRANTY, to the extent permitted by law. Type "show copying"
> and "show warranty" for details.
> This GDB was configured as "powerpc64-unknown-linux-gnu".
> Type "show configuration" for configuration details.
> For bug reporting instructions, please see:
> <http://www.gnu.org/software/gdb/bugs/>.
> Find the GDB manual and other documentation resources online at:
> <http://www.gnu.org/software/gdb/documentation/>.
> For help, type "help".
> Type "apropos word" to search for commands related to "word"...
> Reading symbols from not_pi...done.
> (gdb) break 19
> Breakpoint 1 at 0x9c0: file not_pi.c, line 19.
> (gdb) run
> Starting program: /home/dclarke/pgm/C/pi/not_pi
> sizeof(long double) = 16
>
> Breakpoint 1, main (argc=1, argv=0x7ffffffffa38) at not_pi.c:19
> 19 printf ( " pi is not %38.36Lf\n", pi_ld );
> (gdb) print pi_ld
> $1 = 2.0713495408493618477052677917527035
> (gdb) print &pi_ld
> $2 = (long double *) 0x7ffffffff5d0
> (gdb) x/16xb &pi_ld
> 0x7ffffffff5d0: 0x40 0x00 0x92 0x1f 0xb5 0x44 0x42 0xd1
> 0x7ffffffff5d8: 0x84 0x69 0x89 0x8c 0xc5 0x17 0x01 0xb8
> (gdb) cont
> Continuing.
> pi is not 2.071349540849361847705267791752703488
> [Inferior 1 (process 18825) exited normally]
> (gdb) quit
> nix_$
>
> Looking at this page :
> https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html
>
> Suggests that I need -mfloat128 however that won't work at all :
>
>
> nix_$ gcc -m64 -g -mfloat128 -o not_pi not_pi.c
> cc1: error: -mfloat128 requires VSX support
> nix_$
>
> There is not vector scalar support until Power7 at least. This is an old
> PowerMac G5 with 970 processors.
>
> It seems very confusing as to how the value in memory can be perfect and
> yet printf can not output a correct value and I suspect simple math
> functions also go out the window :
>
> So lets add in #include <math.h> and :
>
> printf ( "sinl(pi) may be %38.36Lf\n", sinl(pi_ld) );
>
>
> nix_$ gcc -m64 -g -o not_pi not_pi.c -lm
> nix_$ ./not_pi
> sizeof(long double) = 16
> pi is not 3.141592653589793238462643383279481227
> sinl(pi) may be 0.000000000000000000000000000000021657
> nix_$
>
> Looks correct. However I know the in memory data is not.
>
> nix_$ gcc -m64 -g -mfloat128 -o not_pi not_pi.c -lm
> cc1: error: -mfloat128 requires VSX support
> nix_$
>
> So that won't work at all.
>
> nix_$ gcc -m64 -g -mabi=ieeelongdouble -o not_pi not_pi.c -lm
> gcc: warning: using IEEE extended precision long double
> cc1: warning: using IEEE extended precision long double
>
> nix_$ ./not_pi
> sizeof(long double) = 16
> pi is not 2.071349540849361847705267791752703488
> sinl(pi) may be 0.877317202667654982757140306348340873
> nix_$
>
> The value of "pi" in memory is perfectly correct but all functions are
> wrong that deal with it.
>
> Attempt to use ordinary "sin(pi)" and I see this :
>
> nix_$ gcc -m64 -g -mabi=ieeelongdouble -o not_pi not_pi.c -lm
> gcc: warning: using IEEE extended precision long double
> cc1: warning: using IEEE extended precision long double
> /tmp/ccIyUnGd.o: In function `main':
> /home/dclarke/pgm/C/pi/not_pi.c:22: undefined reference to `_q_qtod'
> collect2: error: ld returned 1 exit status
> nix_$
>
> So this seems messy and may be related to the need for a Power7 system
> as a minimum. I see this :
>
> "Enable -mfloat128 by default on PowerPC VSX systems"
> https://patchwork.ozlabs.org/patch/802272/
>
> Here I wonder if GCC on PowerPC 64-bit systems requires the Power7 VSX
> support as a minimum or all computations go out the window. Does someone
> have one handy and can show what they see in memory as well as the
> output from sinl and printf?
>
> As a comparison on another big endian risc type here is sparc Vii+ :
>
> (dbx) run
> Running: not_pi
> (process id 21760)
> Reading libc_psr.so.1
> sizeof(long double) = 16
> stopped in main at line 20 in file "not_pi.c"
> 20 printf ( " pi is not %38.36Lf\n", pi_ld );
> (dbx) print &pi_ld
> &pi_ld = 0xffffffff7ffff590
> (dbx) x 0xffffffff7ffff590/8x
> 0xffffffff7ffff590: 0x4000 0x921f 0xb544 0x42d1 0x8469 0x898c 0xc517
> 0x01b8
> (dbx) cont
> pi is not 3.141592653589793238462643383279502797
> sinl(pi) may be 0.000000000000000000000000000000000087
>
> execution completed, exit code is 0
> (dbx) quit
>
> * * * The data in memory is perfect as is the output. * * *
>
> sparcvii+$ /usr/local/gcc6/bin/gcc --version
> gcc (genunix Wed Jul 26 02:41:24 GMT 2017) 6.4.0
> Copyright (C) 2017 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.
>
> sparcvii+$ mcs -p not_pi
> not_pi:
>
> as: Studio 12.5 Compiler Common 12.5 SunOS_sparc Patch 05/02/2016
>
> @(#)SunOS 5.10 Generic January 2005
> GCC: (genunix Wed Jul 26 02:41:24 GMT 2017) 6.4.0
> ld: Software Generation Utilities - Solaris Link Editors: 5.10-1.1522
>
>
> I can try the same thing on a very very old sparc with gcc 7.2.0 and get
> again the correct value in memory and the correct output :
>
> $ /usr/local/gcc7/bin/gcc --version
> gcc (genunix Tue Aug 29 11:48:17 GMT 2017) 7.2.0
> Copyright (C) 2017 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.
>
> $ /usr/local/gcc7/bin/gcc -m64 -g -o not_pi not_pi.c -lm
>
> $ file not_pi
> not_pi: ELF 64-bit MSB executable SPARCV9 Version 1, dynamically linked, not
> stripped
> $ mcs -p not_pi
> not_pi:
>
> as: Studio 12.5 Compiler Common 12.5 SunOS_sparc Patch 05/02/2016
>
> @(#)SunOS 5.10 Generic January 2005
> GCC: (genunix Tue Aug 29 11:48:17 GMT 2017) 7.2.0
> ld: Software Generation Utilities - Solaris Link Editors: 5.10-1.1522
>
> $
>
> $ ./not_pi
> sizeof(long double) = 16
> pi is not 3.141592653589793238462643383279502797
> sinl(pi) may be 0.000000000000000000000000000000000087
> $
>
> (dbx) stop at 19
>
> (2) stop at "not_pi.c":20
> (dbx) run
> Running: not_pi
> (process id 21345)
> Reading libc_psr.so.1
> sizeof(long double) = 16
> stopped in main at line 20 in file "not_pi.c"
> 20 printf ( " pi is not %38.36Lf\n", pi_ld );
> (dbx) print &pi_ld
> &pi_ld = 0xffffffff7ffff550
> (dbx) x &pi_ld/8x
> 0xffffffff7ffff550: 0x4000 0x921f 0xb544 0x42d1 0x8469 0x898c 0xc517
> 0x01b8
> (dbx) cont
> pi is not 3.141592653589793238462643383279502797
> sinl(pi) may be 0.000000000000000000000000000000000087
>
> execution completed, exit code is 0
> (dbx) quit
> $
>
> So regardless if I use gcc 6.4.0 or gcc 7.2.0 or even the Oracle cc we
> always see the correct data in memory and the correct output. However
> on PowerPC 64-bit with gcc 7.2.0 there seems to be an entirely other
> data representation at work internally and a need for -mfloat128 ? That
> won't work unless the hardware has VSX support. Then again I don't know
> but I do know that the output is wrong if the in memory data is correct.
>
> Am I missing something here to make the exact same functionality on
> ppc64 ? Personally I am confused about what floating point support
> there is in the hardware and gcc combination. Any input from anyone
> would be great and would really love to see what a Power7 system does.
>
So the comment mentions pi = 3.14159265358979323846264338327950280e+00L
while you use pi_ld = 3.1415926535897932384626433832795028841971L;
so that's different and might explain the slight difference in hex value.
And given you have to pass the -m argument, makes you wonder of
the math library functions are compiled with the same option or some
other option with different results. After all I believe the default
128bit floating point used to be the ibm extended format, not IEEE.
It looks like it might still be the case. Apparently there are options
-mabi=ieeelongdouble and -mabi=ibmlongdouble with the ibm one being
the default. That probably means the libraries are compiled that way
too and seems to be a powerpc specific weirdness which could be why
other architectures have no such crazyness.
--
Len Sorensen
Reply to: