bearophile wrote:
Don:
Actually it's not so difficult. I've created a patch for bug 2807 -- it's only 5 lines long! It gives an error message if a nested pure function accesses a mutable variable from an outer scope.

Thank you very much Don, your work helps a lot.

Every time I try a tiny program I find something I don't understand:

import std.stdio: writeln;
import std.math: sqrt;
import std.conv: to;

void main(string[] args) {
    double x = args.length == 2 ? to!(double)(args[1]) : 4.0;
    writeln(sqrt(x) + sqrt(x));
}

I have also tried with std.math.sin with similar results:

L0:             enter   8,0
                mov     EAX,8[EBP]
                cmp     EAX,2
                jne     L30
                cmp     EAX,1
                ja      L1B
                mov     EAX,6
                call    near ptr _D6test7__arrayZ
L1B:            mov     EDX,0Ch[EBP]
                mov     EAX,8[EBP]
                mov     EAX,8[EDX]
                mov     EDX,0Ch[EDX]
                push    EDX
                push    EAX
                call    near ptr _D3std4conv13__T2toTdTAyaZ2toFAyaZd
                jmp short       L36
L30:            fld     qword ptr FLAT:_DATA[00h]
L36:            fstp    qword ptr -8[EBP]
                fld     qword ptr -8[EBP]
                fsin
                fld     qword ptr -8[EBP]
                fsin
                faddp   ST(1),ST
                sub     ESP,0Ch
                fstp    tbyte ptr [ESP]
                call    near ptr _D3std5stdio14__T7writelnTeZ7writelnFeZv
                xor     EAX,EAX
                leave
                ret

Isn't sin(x)+sin(x) pure? Even if the compiler doesn't want to replace x+x with 
x*2 because x is a floating point, it can do:

y = sin(x)
y+y

And that gives the same result even with FPs.

Yes. From further investigation, I've found that:
(1) the optimisation of pure only happens for int returns, not for floating-point return types. It should convert purefunc(x)+purefunc(x) into 2*purefunc(x) if the return type of purefunc is int, float, or complex.

(2) the back-end isn't smart enough to convert f*2 into f+f.

It's difficult to work out where it's optimising the int return. I can see where it marks pure calls as subexpressions to be potentially eliminated: OTae(op) is true in gflow.c(660) if it's a pure call, false if it's an impure call. The problem may simply be that the backend doesn't do much common subexpression elimination of floating-point expressions.

I really don't understand the backend. It's quite cryptic. Key acronyms are AE, CP and VBE. Then there's Bin, Bgen, Bkill, etc.
AE *might* be Available Expression (but what does that mean?)
CP might be Copy Propagation info
I've found that VBE = "Very Busy Expression"! (what does that mean?)

Fixing your problem is beyond me at present, I think.

Reply via email to