[cfe-dev] incorrect floating point accrued exception flags with -O

Michael Clark via cfe-dev cfe-dev at lists.llvm.org
Sat Apr 15 14:51:11 PDT 2017


Hi,

First, apologies if this is not the right place to post.

I am seeing unexpected values in the floating point accrued exception flags with clang generated programs. My original issue is seeing FE_INEXACT after an exact float to unsigned int conversion within a ternary expression. This issue does not occur with gcc. In trying to isolate the problem I wrote a simple test program, which results in completely opposite behaviour. FE_INEXACT is not getting set for an inexact conversion when optimisation is enabled. 

Given I’m not yet seeing predictable results for accrued exception flags, I gave up trying to reproduce my original issue (FE_INEXACT for exact conversion) until I am certain which floating point optimisations are being enabled, and under what conditions floating point accrued exceptions are optimised away, otherwise I can’t be sure to isolate my first problem.

I have two versions of a simple test program below, one which even returns incorrect results in gcc. The tests below run on Linux using Debian vendor build of clang 3.8.1 and on macos with the Xcode 8.3.1 vendor build of clang. I don’t have -fast-math enabled so I would expect standards compliant behaviour. I would like to know what optimisations are preventing floating point accrued exceptions from being set and how to disable these optimisation so that I am get deterministic results, then I can try to reproduce my first issue in isolation.

- fcvt1.c triggers the same issue with gcc (FE_INEXACT not set for inexact conversion)
- fcvt2.c triggers the issue only with clang (FE_INEXACT not set for inexact conversion)
- no reproducer yet… (FE_INEXACT set after exact conversion)

Happy Holidays,

Michael.

$ gcc --version
gcc (Debian 6.3.0-6) 6.3.0 20170205
Copyright (C) 2016 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.

$ gcc -O0 -lm fcvt1.c 
$ ./a.out 
1 exact
1 inexact
$ gcc -O3 -lm fcvt1.c 
$ ./a.out 
1 exact
1 exact
$ gcc -O0 -lm fcvt2.c 
$ ./a.out 
1 exact
1 inexact
$ gcc -O3 -lm fcvt2.c 
$ ./a.out 
1 exact
1 inexact

$ clang --version
clang version 3.8.1-16 (tags/RELEASE_381/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

$ clang -O0 -lm fcvt1.c 
$ ./a.out 
1 exact
1 inexact
$ clang -O3 -lm fcvt1.c 
$ ./a.out 
1 exact
1 exact
$ clang -O0 -lm fcvt2.c 
$ ./a.out 
1 exact
1 inexact
$ clang -O3 -lm fcvt2.c 
$ ./a.out 
1 exact
1 exact

$ clang --version
Apple LLVM version 8.1.0 (clang-802.0.41)
Target: x86_64-apple-darwin16.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

$ cc -O0 fcvt1.c 
$ ./a.out 
1 exact
1 inexact
$ cc -O3 fcvt1.c 
$ ./a.out 
1 exact
1 exact
$ cc -O0 fcvt2.c 
$ ./a.out 
1 exact
1 inexact
$ cc -O3 fcvt2.c 
$ ./a.out 
1 exact
1 exact


$ cat fcvt1.c 
#include <stdio.h>
#include <fenv.h>

unsigned fcvt(float a)
{
        return (unsigned)a;
}

int main()
{
        fesetround(FE_TONEAREST);

        feclearexcept(FE_ALL_EXCEPT);
        printf("%d ", fcvt(1.0f));
        printf("%s\n", fetestexcept(FE_INEXACT) ? "inexact" : "exact");

        feclearexcept(FE_ALL_EXCEPT);
        printf("%d ", fcvt(1.1f));
        printf("%s\n", fetestexcept(FE_INEXACT) ? "inexact" : "exact");
}


$ cat fcvt2.c
#include <stdio.h>
#include <fenv.h>

unsigned fcvt(float a)
{
        return (unsigned)a;
}

void test_fcvt(float a)
{
        feclearexcept(FE_ALL_EXCEPT);
        printf("%d ", fcvt(a));
        printf("%s\n", fetestexcept(FE_INEXACT) ? "inexact" : "exact");
}

int main()
{
        fesetround(FE_TONEAREST);

        test_fcvt(1.0f);
        test_fcvt(1.1f);
}




More information about the cfe-dev mailing list