[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: