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

floating point types seems to need VSX support ?




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.

Dennis


Reply to: