This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH RFC] <math.h> issignaling


Hi!

On Thu, 07 Mar 2013 11:47:42 +0100, I wrote:
> On Wed, 6 Mar 2013 18:13:54 +0000, "Joseph S. Myers" <joseph@codesourcery.com> wrote:
> > On Wed, 6 Mar 2013, Thomas Schwinge wrote:
> > > On 32-bit x86, the __issignalingf and __issignaling functions already
> > > "fail" at the call site:
> > > 
> > >      804a130:       d9 05 18 e1 04 08       flds   0x804e118
> > >      804a136:       d9 1c 24                fstps  (%esp)
> > >      804a139:       e8 d2 eb ff ff          call   8048d10 <__issignalingf@plt>
> > 
> > Does this depend on compiler options (you don't say what specific code 
> > shows this problem)?  A test I did of passing a float variable to a 
> > function used integer load/store to move it to the stack, not 
> > floating-point.
> 
>     $ cat < ../snan.c
>     extern int __issignalingf(float);
>     
>     int main(void)
>     {
>       static VOLATILE float snan_var = __builtin_nansf("");
>     
>       return __issignalingf(snan_var);
>     }

Replacing this piece of code  with:

    extern int __issignalingif(int);
    
    int main(void)
    {
      static VOLATILE float snan_var = __builtin_nansf("");
    
      return __issignalingif((__extension__ (((union { float __d; int __i; }) {__d: snan_var}).__i)));
    }

..., this issue indeed is resolved.  Instead of:

> volatile, -O0 vs. -O1:
> 
>     $ diff -u <(gcc -Wall -S -o - ../snan.c -DVOLATILE=volatile -O0) <(gcc -Wall -S -o - ../snan.c -DVOLATILE=volatile -O1)
>     [...]
>     -       movl    snan_var.1360, %eax
>     -       movl    %eax, (%esp)
>     +       flds    snan_var.1360
>     +       fstps   (%esp)
>             call    __issignalingf

..., we now get:

    $ diff -u <(gcc -Wall -S -o - ../snan.c -DVOLATILE=volatile -O0) <(gcc -Wall -S -o - ../snan.c -DVOLATILE=volatile -O1)
    --- /dev/fd/63  2013-03-07 16:35:56.152357438 +0100
    +++ /dev/fd/62  2013-03-07 16:35:56.152357438 +0100
    @@ -11,10 +11,8 @@
            movl    %esp, %ebp
            .cfi_def_cfa_register 5
            andl    $-16, %esp
    -       subl    $32, %esp
    +       subl    $16, %esp
            movl    snan_var.1360, %eax
    -       movl    %eax, 28(%esp)
    -       movl    28(%esp), %eax
            movl    %eax, (%esp)
            call    __issignalingif
            leave

..., and instead of:

> -O1, volatile vs. not volatile:
> 
>     $ diff -u <(gcc -Wall -S -o - ../snan.c -DVOLATILE=volatile -O1) <(gcc -Wall -S -o - ../snan.c -DVOLATILE= -O1)
>     [...]
>     -       flds    snan_var.1360
>     -       fstps   (%esp)
>     +       movl    $0x7fa00000, (%esp)
>             call    __issignalingf
>     [...]
>     -       .data
>     -       .align 4
>     -       .type   snan_var.1360, @object
>     -       .size   snan_var.1360, 4
>     -snan_var.1360:
>     -       .long   2141192192
>             .ident  "GCC: (Debian 4.7.2-5) 4.7.2"

..., we now get:

    $ diff -u <(gcc -Wall -S -o - ../snan.c -DVOLATILE=volatile -O1) <(gcc -Wall -S -o - ../snan.c -DVOLATILE= -O1)
    --- /dev/fd/63  2013-03-07 16:37:45.343935402 +0100
    +++ /dev/fd/62  2013-03-07 16:37:45.343935402 +0100
    @@ -12,8 +12,7 @@
            .cfi_def_cfa_register 5
            andl    $-16, %esp
            subl    $16, %esp
    -       movl    snan_var.1360, %eax
    -       movl    %eax, (%esp)
    +       movl    $2141192192, (%esp)
            call    __issignalingif
            leave
            .cfi_restore 5
    @@ -22,11 +21,5 @@
            .cfi_endproc
     .LFE0:
            .size   main, .-main
    -       .data
    -       .align 4
    -       .type   snan_var.1360, @object
    -       .size   snan_var.1360, 4
    -snan_var.1360:
    -       .long   2141192192
            .ident  "GCC: (Debian 4.7.2-5) 4.7.2"
            .section        .note.GNU-stack,"",@progbits

However, the next problem is not far away...  ISO/IEC TS 18661, Working
Group Draft â March 1, 2013, WG 14 N1676 in Â8 Operation binding states
that Â[4] The unary - operator raises no floating-point exceptions, even
if the operand is a signaling NaNÂ.

    $ cat < ../snan_neg.c
    extern int __issignalingif(int);
    
    int main(void)
    {
      static VOLATILE float snan_var = __builtin_nansf("");
    
      return __issignalingif((__extension__ (((union { float __d; int __i; }) {__d: -snan_var}).__i)));
    }

(As before, but using -snan_var instead of snan_var.)  The following is
fine:

    $ diff -u <(gcc -Wall -S -o - ../snan.c -DVOLATILE= -O1) <(gcc -Wall -S -o - ../snan_neg.c -DVOLATILE= -O1)
    --- /dev/fd/63  2013-03-07 16:46:48.766268697 +0100
    +++ /dev/fd/62  2013-03-07 16:46:48.766268697 +0100
    @@ -1,4 +1,4 @@
    -       .file   "snan.c"
    +       .file   "snan_neg.c"
            .text
            .globl  main
            .type   main, @function
    @@ -12,7 +12,7 @@
            .cfi_def_cfa_register 5
            andl    $-16, %esp
            subl    $16, %esp
    -       movl    $2141192192, (%esp)
    +       movl    $-6291456, (%esp)
            call    __issignalingif
            leave
            .cfi_restore 5

(This indeed is the canonical sNaN value with the sign bit set.)
However, with Â-DVOLATILE= -O0Â we now get:

        flds    snan_var.1360
        fchs
        fstps   28(%esp)
        movl    28(%esp), %eax
        movl    %eax, (%esp)
        call    __issignalingif

..., and likewise with Â-DVOLATILE=volatile and any optimization level.

Now, I have no idea if this version of GCC that I'm using for testing is
actually meant to follow that specification, but not matter what, this is
still unusable for our glibc purposes.

Given this, I'm reluctant to implement the "int calling convention" for
the __issignaling functions:

> > Or the macro could use a union to pass the value to a function defined to 
> > take an integer value, if that helps.
> 
> To avoid any such issues, that may indeed be the more workable solution,
> so I'll give that a try, thanks.

..., because doing this would be a non-trivial effort (so far, I only
hacked in the easy 32-bit float case): we have to replicate (something
like) the ieee*_shape_type unions in installed header files (they're
currently defined in math_private.h as well as several math_ldbl.h
files), and yet this won't generally solve all problems, as shown above.

How do you suggest to proceed?  Can we be sure that the volatile cases
cited above as failing, are not actually "just" GCC bugs, and the "float
calling convention" for the __issignaling functions is fine, in fact?
This I already have implemented as posted before, and it works fine (for
this one version of GCC that I tested) for x86_64 and MIPS32 O32.

Should I gather additional data what happens for other architectures
using the "float calling convention"?  And, if they're generally fine,
should we just XFAIL (or disable) the faulty tests for 32-bit x86 until
we can rely on versions of GCC that have this issue fixed for building
and testing glibc?


GrÃÃe,
 Thomas

Attachment: pgp00000.pgp
Description: PGP signature


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]