Date: Fri, 12 May 2017 23:08:03 -0700 From: Steve Kargl <sgk@troutmask.apl.washington.edu> To: Bruce Evans <brde@optusnet.com.au> Cc: numerics@freebsd.org, freebsd-hackers@freebsd.org Subject: Re: catrig[fl].c and inexact Message-ID: <20170513060803.GA84399@troutmask.apl.washington.edu> In-Reply-To: <20170513103208.M845@besplex.bde.org> References: <20170512215654.GA82545@troutmask.apl.washington.edu> <20170513103208.M845@besplex.bde.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Sat, May 13, 2017 at 11:35:49AM +1000, Bruce Evans wrote: > On Fri, 12 May 2017, Steve Kargl wrote: > > > So, I've been making improvements to my implementations of > > the half-cycle trig functions. In doing so, I decide to > > add WARNS=2 to msun/Makefile. clang 4.0.0 dies with an > > error about an unused variable in raise_inexact() from > > catrig[fl].c. > > > > /usr/home/kargl/trunk/math/libm/msun/src/catrigl.c:195:2: error: unused variable > > 'junk' [-Werror,-Wunused-variable] > > raise_inexact(); > > ^ > > /usr/home/kargl/trunk/math/libm/msun/src/catrigl.c:56:45: note: expanded from > > macro 'raise_inexact' > > #define raise_inexact() do { volatile float junk = 1 + tiny; } while(0) > > ^ > > Grepping catrig.o for the variable 'junk' suggests that 'junk' is > > optimized out (with at least -O2). > > Just another bug in clang. Volatile variables cannot be optimized out > (if they are accessed). Does this depend on scope? 'junk' is local to the do {...} while(0); construct. Can a compiler completely eliminate a do-nothing scoping unit? I don't know C well enough to know. I do know what I have observed in clang. > > A quick and dirty patch to achieve the intent of the original > > code follows. It would be nice if some would like to commit > > the patch. Of course, you may want to wait for Bruce to > > review the diff. > > > > Index: src/catrig.c > > =================================================================== > > --- src/catrig.c (revision 1935) > > +++ src/catrig.c (working copy) > > @@ -37,7 +37,7 @@ __FBSDID("$FreeBSD: head/lib/msun/src/catrig.c 313863 > > #define isinf(x) (fabs(x) == INFINITY) > > #undef isnan > > #define isnan(x) ((x) != (x)) > > -#define raise_inexact() do { volatile float junk = 1 + tiny; } while(0) > > +#define raise_inexact(x) do { (x) = 1 + tiny; } while(0) > > #undef signbit > > #define signbit(x) (__builtin_signbit(x)) > > > > @@ -315,7 +315,7 @@ casinh(double complex z) > > return (z); > > > > /* All remaining cases are inexact. */ > > - raise_inexact(); > > + raise_inexact(new_y); > > > > if (ax < SQRT_6_EPSILON / 4 && ay < SQRT_6_EPSILON / 4) > > return (z); > > Now it doesn't take compiler bugs to optimize it out, since new_y is not > volatile, and a good compiler would optimize it out in all cases. I've yet to find a good compiler. They all seem to have bugs. > new_y > is obviously unused before the early returns, so it doesn't need to be > evalated before the returns as far as the compiler can see. Later, > new_y is initialized indirectly, and the compiler can see that too (not > so easily, so it can see that raise_inexact() has no effect except possibly > for its side effect of raising inexact for 1 + tiny. The later call passes the address of new_y to the routine. How can the compiler short of inlining the called routine know that the value assigned to new_y isn't used? > The change might defeat the intent of the original code in another way. > 'junk' is intentionally independent of other variables, so that there are > no dependencies on it. If the compiler doesn't optimize away the assignment > to new_y, then it is probably because it doesn't see that the assignment is > dead, so there is a dependency. It may defeat the intent of the original code, but it seems that the original code provokes undefined behavior. > Actually, we want the variable 'junk' to be optimized away. We only want > the side effect of evaluating 1 + tiny. Compilers have bugs evaluating > expressions like 1 + tiny, tiny*tiny and huge*huge, and we use assignments > of the result to volatile variables in tens if not hundreds of places to > try to work around compiler bugs. If that doesn't work here, then all the > other places are probably broken too. The other places mostly use a static > volatile, while this uses an auto volatile. 'tiny' is also volatile, as > required for the standard magic. I planned to fix all this magic using > macros like raise_inexact(). If you plan to fix the magic with raise_inexact, then please test with a suite of compilers. AFAICT, clang is optimizing out the code. I haven't written a testcase to demonstrate this as I have other irons in the fire. -- Steve 20170425 https://www.youtube.com/watch?v=VWUpyCsUKR4 20161221 https://www.youtube.com/watch?v=IbCHE-hONow
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20170513060803.GA84399>