HEADSUP: math is broken with clang and optimization
Steve Kargl
sgk at troutmask.apl.washington.edu
Tue Feb 16 01:01:42 UTC 2021
On Mon, Feb 15, 2021 at 03:27:08PM -0800, Mark Millard wrote:
> > On Mon, Feb 15, 2021 at 01:03:36PM -0800, Steve Kargl wrote:
> > > On Mon, Feb 15, 2021 at 12:49:13PM -0800, Steve Kargl wrote:
> > > > On Sun, Feb 14, 2021 at 01:59:58PM -0800, Steve Kargl wrote:
> > > > > Just a headsup for anyone doing numerical work with
> > > > > FreeBSD-current. clang with optimization of -O1 or
> > > > > higher produces wrong results. Testing 1 million
> > > > > complex values of ccoshf and limiting |z| < 20,
> > > > > shows
> > > > >
> > > >
> > > > This is either an in-ling bug or discarding a cast issue.
> > > > With everything in the same file so clang has dp_ccosh
> > > > available to it when compiling main.
> > > >
> > >
> > > Code builds and works as expected with gcc 10.2and
> > > gcc 11.0.0.
> > >
> >
> > Can't find a list of options that is equivalent to -O1,
> > so cannot test various optimizations.
> >
> > Notice that -march=i686 gives the wrong results and
> > -march=core2 gives the correct result. Trying -march=i686
> > -msse -msse2 gives the correct result. It seems that
> > clang does not understand how the x87 (on i585-freebsd).
>
> I tried looking around some and got the following
> that might be contributing: variations in
> __FLT_EVAL_METHOD__ used . . .
>
> # cc -target i386-unknown-freebsd14.0 -march=i686 -O2 -x c /dev/null -dM -E | egrep "(FLT_EVAL_METHOD|ILP32|LP64)"
> #define _ILP32 1
> #define __FLT_EVAL_METHOD__ 2
> #define __ILP32__ 1
>
> # cc -target i386-unknown-freebsd14.0 -march=core2 -O2 -x c /dev/null -dM -E | egrep "(FLT_EVAL_METHOD|ILP32|LP64)"
> #define _ILP32 1
> #define __FLT_EVAL_METHOD__ 0
> #define __ILP32__ 1
>
> # cc -target x86_64-unknown-freebsd14.0 -march=core2 -O2 -x c /dev/null -dM -E | egrep "(FLT_EVAL_METHOD|ILP32|LP64)"
> #define _LP64 1
> #define __FLT_EVAL_METHOD__ 0
> #define __LP64__ 1
>
> FYI: It does not look like FreeBSD's /usr/include/x86/float.h
> matches all the detail:
>
> #if __ISO_C_VISIBLE >= 1999
> #ifdef __LP64__
> #define FLT_EVAL_METHOD 0 /* no promotions */
> #else
> #define FLT_EVAL_METHOD (-1) /* i387 semantics are...interesting */
> #endif
> . . .
> #endif
>
>
> For reference:
>
> # cc -target i386-unknown-freebsd14.0 -O2 -x c /dev/null -dM -E | egrep "(FLT_EVAL_METHOD|ILP32|LP64)"
> #define _ILP32 1
> #define __FLT_EVAL_METHOD__ 2
> #define __ILP32__ 1
>
> # cc -target x86_64-unknown-freebsd14.0 -O2 -x c /dev/null -dM -E | egrep "(FLT_EVAL_METHOD|ILP32|LP64)"
> #define _LP64 1
> #define __FLT_EVAL_METHOD__ 0
> #define __LP64__ 1
>
> # cc -target x86_64-unknown-freebsd14.0 -march=i686 -O2 -x c /dev/null -dM -E | grep FLT_EVAL_METHOD | sort
> error: unknown target CPU 'i686'
> note: valid target CPU values are: nocona, core2, penryn, bonnell, atom, silvermont, slm, goldmont, goldmont-plus, tremont, nehalem, corei7, westmere, sandybridge, corei7-avx, ivybridge, core-avx-i, haswell, core-avx2, broadwell, skylake, skylake-avx512, skx, cascadelake, cooperlake, cannonlake, icelake-client, icelake-server, tigerlake, knl, knm, k8, athlon64, athlon-fx, opteron, k8-sse3, athlon64-sse3, opteron-sse3, amdfam10, barcelona, btver1, btver2, bdver1, bdver2, bdver3, bdver4, znver1, znver2, x86-64
>
> # cc -v
> FreeBSD clang version 11.0.1 (git at github.com:llvm/llvm-project.git llvmorg-11.0.1-0-g43ff75f2c3fe)
> Target: x86_64-unknown-freebsd14.0
> Thread model: posix
> InstalledDir: /usr/bin
>
Doesn't surprise me. gcc knows about freebsd special handling of
the i387 on i686-*-freebsd. clang does not.
clang:
% cc -E -dM -c -march=i686 testf.c | egrep "(FLT_EVAL_METHOD|__ILP32|__LP64)"
#define FLT_EVAL_METHOD (-1)
#define __FLT_EVAL_METHOD__ 2
#define __ILP32__ 1
gcc10:
% gcc10 -E -dM -c -march=i686 testf.c | egrep "(FLT_EVAL_METHOD|__ILP32|__LP64)"
#define __FLT_EVAL_METHOD__ 2
#define __FLT_EVAL_METHOD_TS_18661_3__ 2
#define __ILP32__ 1
#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
--
Steve
More information about the freebsd-current
mailing list