Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 29 Jun 2018 17:05:13 -0700
From:      Ryan Libby <rlibby@gmail.com>
To:        John Baldwin <jhb@freebsd.org>
Cc:        Mark Millard <marklmi@yahoo.com>, Bryan Drewery <bdrewery@freebsd.org>, svn-src-head@freebsd.org, FreeBSD Current <freebsd-current@freebsd.org>
Subject:   Re: head -r335782 (?) broke ci.freebsd.org's FreeBSD-head-amd64-gcc build (lib32 part of build)
Message-ID:  <CAHgpiFxUt9dShZ_tES3PGvrV4qE%2BW%2B-%2BCVnsAGLb6--ykH0cAg@mail.gmail.com>
In-Reply-To: <ec55a330-17e1-75d5-7e30-7f1ff49c038f@FreeBSD.org>
References:  <00D1127A-1F0E-4E0E-B86C-1C5AA5B2E085@yahoo.com> <CF0230A1-1384-4F0F-A96A-5AB555FD17AC@yahoo.com> <7A845F2C-C994-4828-823D-33A97B7B6EB0@yahoo.com> <ec55a330-17e1-75d5-7e30-7f1ff49c038f@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, Jun 29, 2018 at 1:26 PM, John Baldwin <jhb@freebsd.org> wrote:
> On 6/28/18 7:54 PM, Mark Millard wrote:
>> On 2018-Jun-28, at 6:04 PM, Mark Millard <marklmi at yahoo.com> wrote:
>>
>>> On 2018-Jun-28, at 5:39 PM, Mark Millard <marklmi at yahoo.com> wrote:
>>>
>>>> [ ci.free.bsd.org jumped from -r335773 (built) to -r335784 (failed)
>>>> for FreeBSD-head-amd64-gcc. It looked to me like the most likely
>>>> breaking-change was the following but I've not tried personal
>>>> builds to confirm.
>>>> ]
>
> So this is a bit complicated and I'm not sure what the correct fix is.
>
> What is happening is that the <float.h> shipped with GCC is now being used
> after this change instead of sys/x86/include/float.h.  A sledgehammer approach
> would be to remove float.h from the GCC package (we currently don't install
> the float.h for the base system clang either).  However, looking at this
> in more detail, it seems that x86/include/float.h is also busted in some
> ways.
>
> First, the #error I don't understand how it is happening.  The GCC float.h
> defines LDBL_MAX_EXP to the __LDBL_MAX_EXP__ builtin which is 16384 just
> like the x86 float.h:
>
> # x86_64-unknown-freebsd12.0-gcc -dM -E empty.c -m32 | grep LDBL_MAX_EXP
> #define __LDBL_MAX_EXP__ 16384
>
> I even hacked catrigl.c to add the following lines before the #error
> check:
>
> LDBL_MAX_EXP_ = LDBL_MAX_EXP
> LDBL_MANT_DIG_ = LDBL_MANT_DIG
>
> #if LDBL_MAX_EXP != 0x4000
> #error "Unsupported long double format"
> #endif
>
> And the -E output is:
>
> DBL_MAX_EXP_ = 16384
> LDBL_MANT_DIG_ = 53
>
> # 51 "/zoo/jhb/zoo/jhb/git/freebsd/lib/msun/src/catrigl.c:93:2: error: #error "U
> nsupported long double format"
>  #error "Unsupported long double format"
>   ^~~~~
>
> Yet clearly, 16384 == 0x4000 assuming it is doing a numeric comparison (which
> it must be since the x86 float.h uses '16384' not '0x4000' as the value).
>

Isn't this just the unsupported LDBL_MANT_DIG you're hitting here?  Note
line 93.  I reused the same error message for LDBL_MAX_EXP :/

> However, LDBL_MANT_DIG of 53 is a bit more fun.  We have a comment about the
> initial FPU control word in sys/amd64/include/fpu.h that reads thus:
>
> /*
>  * The hardware default control word for i387's and later coprocessors is
>  * 0x37F, giving:
>  *
>  *      round to nearest
>  *      64-bit precision
>  *      all exceptions masked.
>  *
>  * FreeBSD/i386 uses 53 bit precision for things like fadd/fsub/fsqrt etc
>  * because of the difference between memory and fpu register stack arguments.
>  * If its using an intermediate fpu register, it has 80/64 bits to work
>  * with.  If it uses memory, it has 64/53 bits to work with.  However,
>  * gcc is aware of this and goes to a fair bit of trouble to make the
>  * best use of it.
>  *
>  * This is mostly academic for AMD64, because the ABI prefers the use
>  * SSE2 based math.  For FreeBSD/amd64, we go with the default settings.
>  */
> #define __INITIAL_FPUCW__       0x037F
> #define __INITIAL_FPUCW_I386__  0x127F
> #define __INITIAL_NPXCW__       __INITIAL_FPUCW_I386__
> #define __INITIAL_MXCSR__       0x1F80
> #define __INITIAL_MXCSR_MASK__  0xFFBF
>
> GCC is indeed aware of this in gcc/config/i386/freebsd.h which results in
> __LDBL_MANT_DIG__ being set to 53 instead of 64:
>
> /* FreeBSD sets the rounding precision of the FPU to 53 bits.  Let the
>    compiler get the contents of <float.h> and std::numeric_limits correct.  */
> #undef TARGET_96_ROUND_53_LONG_DOUBLE
> #define TARGET_96_ROUND_53_LONG_DOUBLE (!TARGET_64BIT)
>
> clang seems unaware of this as it reports all the same values for
> LDBL_MIN/MAX for both amd64 and i386 (values that match GCC for amd64
> but not i386):
>
> # cc -dM -E empty.c | egrep 'LDBL_(MIN|MAX)__'
> #define __LDBL_MAX__ 1.18973149535723176502e+4932L
> #define __LDBL_MIN__ 3.36210314311209350626e-4932L
> # cc -dM -E empty.c -m32 | egrep 'LDBL_(MIN|MAX)__'
> #define __LDBL_MAX__ 1.18973149535723176502e+4932L
> #define __LDBL_MIN__ 3.36210314311209350626e-4932L
> # x86_64-unknown-freebsd12.0-gcc -dM -E empty.c | egrep 'LDBL_(MIN|MAX)__'
> #define __LDBL_MAX__ 1.18973149535723176502e+4932L
> #define __LDBL_MIN__ 3.36210314311209350626e-4932L
> # x86_64-unknown-freebsd12.0-gcc -dM -E empty.c -m32 | egrep 'LDBL_(MIN|MAX)__'
> #define __LDBL_MAX__ 1.1897314953572316e+4932L
> #define __LDBL_MIN__ 3.3621031431120935e-4932L
>
> The x86/include/float.h header though reports the MIN/MAX values somewhere
> in between the two ranges for both amd64 and i386 while reporting an
> LDBL_MANT_DIG of 64:
>
> #define LDBL_MANT_DIG   64
> #define LDBL_MIN        3.3621031431120935063E-4932L
> #define LDBL_MAX        1.1897314953572317650E+4932L
>
> I guess for now I will remove float.h from the amd64-gcc pkg-plist, but we
> should really be fixing our tree to work with compiler-provided language
> headers when at all possible.  It's not clear to me if amd64 should be
> using the compiler provided values of things like LDBL_MIN/MAX either btw.
>
> --
> John Baldwin
> _______________________________________________
> freebsd-current@freebsd.org mailing list
> https://lists.freebsd.org/mailman/listinfo/freebsd-current
> To unsubscribe, send any mail to "freebsd-current-unsubscribe@freebsd.org"

The whole situation is a little messed up.  LDBL_MAX, LDBL_MIN, and
LDBL_MANT_DIG are IMHO broken by design, because they are just the
defaults.  User code can change the mode, and then the constants
necessarily yield weird things, like max - epsilon becoming infinity, or
not actually being the maximum possible finite value.  It's difficult
for code to use them correctly--which was why I removed references to
LDBL_MAX in [1].

Some general background on that aspect here [2].

[1] https://svnweb.freebsd.org/base?view=revision&revision=323003
[2] https://lists.freebsd.org/pipermail/freebsd-numerics/2012-September/000288.html



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAHgpiFxUt9dShZ_tES3PGvrV4qE%2BW%2B-%2BCVnsAGLb6--ykH0cAg>