From owner-freebsd-standards@FreeBSD.ORG Sat Jan 30 19:01:58 2010 Return-Path: Delivered-To: freebsd-standards@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id CF910106566C; Sat, 30 Jan 2010 19:01:58 +0000 (UTC) (envelope-from das@freebsd.org) Received: from zim.MIT.EDU (ZIM.MIT.EDU [18.95.3.101]) by mx1.freebsd.org (Postfix) with ESMTP id 891038FC1C; Sat, 30 Jan 2010 19:01:58 +0000 (UTC) Received: from zim.MIT.EDU (localhost [127.0.0.1]) by zim.MIT.EDU (8.14.3/8.14.2) with ESMTP id o0UJ1v6x064405; Sat, 30 Jan 2010 14:01:57 -0500 (EST) (envelope-from das@freebsd.org) Received: (from das@localhost) by zim.MIT.EDU (8.14.3/8.14.2/Submit) id o0UJ1v7m064404; Sat, 30 Jan 2010 14:01:57 -0500 (EST) (envelope-from das@freebsd.org) Date: Sat, 30 Jan 2010 14:01:57 -0500 From: David Schultz To: Kostik Belousov Message-ID: <20100130190157.GB63954@zim.MIT.EDU> Mail-Followup-To: Kostik Belousov , Bruce Evans , gavin@freebsd.org, freebsd-standards@freebsd.org, freebsd-amd64@freebsd.org References: <201001301251.o0UCpSEP077706@freefall.freebsd.org> <20100131014341.J78095@delplex.bde.org> <20100130181145.GA3877@deviant.kiev.zoral.com.ua> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20100130181145.GA3877@deviant.kiev.zoral.com.ua> Cc: gavin@freebsd.org, freebsd-standards@freebsd.org, freebsd-amd64@freebsd.org Subject: Re: standards/143358: nearbyint raises spurious inexact exception X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 30 Jan 2010 19:01:59 -0000 On Sat, Jan 30, 2010, Kostik Belousov wrote: > On Sun, Jan 31, 2010 at 02:20:30AM +1100, Bruce Evans wrote: > > On Sat, 30 Jan 2010 gavin@freebsd.org wrote: > > > > >Synopsis: nearbyint raises spurious inexact exception > > > > >Note that a comment in the function itself in lib/msun/src/s_nearbyint.c > > >does also suggest that this PR is valid, "We save and restore the > > >floating-point environment to avoid raising an inexact exception." I've > > >also verified Solaris 10, Linux and FreeBSD 7.2 show the expected > > >behaviour. > > > > This seems to be a bug in gcc-4.2, or perhaps a bug in the inline asms. > > gcc-4.2 still works with -O0, but with -O it removes the entire fesetenv() > > in nearbyint(). The fegetenv() isn't removed though its result is never > > used. I didn't get anywhere good trying to fix this, but I got to the > > following worse place of interest: after replacing the fesetenv(&env) by > > fesetenv(&xenv) where xenv is an invalidly initialized global variable > > (all 0's), the fegetenv(&env) corrupted the current environment (looks > > a bit like xenv was used to initialize the current environment). > > > > Removing fesetenv() in other contexts would give larger bugs. > > While looking at this, I tried to run the example on custom-build > gcc 4.4.3/binutils 2.20 toolchain, and bumped into the issue fixed > by > http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff/3eac7944b4112632ad6fb257c7ce31deda72d89f Hmm, we should fix that, but I think it's orthogonal to the issue in the PR. Here's the code I'm getting with -O2: nearbyint: .LFB9: subq $56, %rsp .LCFI1: movsd %xmm0, 8(%rsp) leaq 16(%rsp), %rdi call fegetenv #APP fldenv 16(%rsp) ldmxcsr 44(%rsp) #NO_APP movsd 8(%rsp), %xmm0 call rint addq $56, %rsp ret gcc isn't removing the fesetenv(); it's actually moving the fesetenv() to before the rint() call. I believe the bug is that gcc is using incorrect builtin knowledge that the rint() function is pure. FreeBSD doesn't declare it this way because that would be wrong; rint() depends upon and modifies the floating point environment. When I compile with -fno-builtins, the resulting code is correct. I can't think of any good workarounds except using -fno-builtin or making a _rint() alias for rint() to trick gcc. This is related to a long-standing and thorny issue with gcc, namely, that it doesn't understand how to cope with code that modifies or examines the floating point environment (rounding modes, exception flags, etc.) Basically, it assumes that all floating point arithmetic is performed in the default environment, and has no side effects. Implementing C99's FENV_ACCESS pragma to address this has been on their todo list for years, but it's a big task.