Subject: Re: Problem and fix for systat/top/ps
To: Johnny Billquist <bqt@softjar.se>
From: Anders Magnusson <ragge@ludd.ltu.se>
List: port-vax
Date: 03/13/2007 19:23:25
Heh, you found the bug!
If you add -fno-builtin when compiling that file then finite won't be
optimized
away and it (probably) works, I have no machine to test on right now.
Someone with knowledge of gcc maybe can make gcc DTRT (or, at least, remove
the finite() builtin)?
-- Ragge
Johnny Billquist wrote:
> I looked at the problems with top and family today, and located the
> problem.
> In a way it's confusing that it exists, but I have an easy solution to
> it, anyway.
>
> The problem comes from the log() function in libm, and the code starts
> like this:
>
> ---
> if (x <= 0) {
> if (_IEEE && x == zero) /* log(0) = -Inf */
> return (-one/zero);
> else if (_IEEE) /* log(neg) = NaN */
> return (zero/zero);
> else if (x == zero) /* NOT REACHED IF _IEEE */
> return (infnan(-ERANGE));
> else
> return (infnan(EDOM));
> } else if (!finite(x)) {
> if (_IEEE) /* x = NaN, Inf */
> return (x+x);
> else
> return (infnan(ERANGE));
> }
> ---
>
> The interesting thing is, if you look at the produced code, it looks
> like this:
>
> ---
> 00000228 <log>:
> 228: 00 00 Entry mask 0x0000 = < >
> 22a: c2 04 5e subl2 $0x4,sp
> 22d: 70 ac 04 50 movd 0x4(ap),r0
> 231: 73 50 tstd r0
> 233: 15 0d bleq 242 <log+0x1a>
> 235: dd 22 pushl $0x22
> 237: fb 01 ef c2 calls $0x1,0 <__log__D>
> 23b: fd ff ff
> 23e: 6e 50 50 cvtld r0,r0
> 241: 04 ret
> 242: 73 50 tstd r0
> 244: 13 0d beql 253 <log+0x2b>
> 246: dd 21 pushl $0x21
> 248: fb 01 ef b1 calls $0x1,0 <__log__D>
> 24c: fd ff ff
> 24f: 6e 50 50 cvtld r0,r0
> 252: 04 ret
> 253: d2 21 7e mcoml $0x21,-(sp)
> 256: fb 01 ef a3 calls $0x1,0 <__log__D>
> 25a: fd ff ff
> 25d: 6e 50 50 cvtld r0,r0
> 260: 04 ret
> ---
>
> (all the three "calls $0x1,0" are really calls to infnan.)
>
> Which is rather interesting. Looking at the produced code, it appears
> that the test:
> if (!finite(x)) {
> gets optimized away, and is assumed to always be true, so that branch
> is always taken. In effect, the log() function always returns infnan()
> right away. And infnan() on the vax is designed to always give an
> illegal instruction trap.
>
> Now, I haven't really understood how on earth gcc can think that
> finite() itself would always be false, but therein lies the problem.
> I've searched the whole source tree for macro definitions of finite
> without finding any. Anyway, adding the following line before the
> log() function in n_log.c fixes everything:
>
> #define finite(x) 1
>
> And, based on the code in n_support.c, finite() should always return
> true on a VAX.
>
> There are finite() calls in other pieces of code in noieee_src as
> well, but nothing else seems to be used by any code I've stumbled on
> so far, but this fix is applicable to all of those files.
>
> So this leaves us with one question:
>
> Why does gcc optimize away the call to finite()? Is there a built-in
> macro in gcc for this on the vax perhaps???
>
> After this fix, what's left is that gcc crash if you turn on any
> optimizations on the VAX. Someone who knows gcc needs to help out with
> this one. And we'd probably want the PIC ability back in gcc for VAX
> again, so that we can have shared libraries.
>
> Anyone feel like helping out? :-)
>
> Johnny
>