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
>