My guess is that this is a similar bug to issue 13474, where ad is truncated by saving it to the stack then reloading it, while cd is kept in a register after being returned with >double precision.
Comment #2 by ilyayaroshenko — 2015-02-14T13:18:44Z
Probably this is reduced example for FreeBSD_32 and Win32:
----
double two = 2.0;
assert(sqrt(two) == sort(2.0));
----
Comment #3 by bugzilla — 2020-08-31T09:16:49Z
Code:
import core.stdc.math;
void main() {
double two = 2.0;
assert(sqrt(two) == sqrt(2.0));
}
Generates for main():
enter 014h,0
fld qword ptr FLAT:CONST[00h]
fstp qword ptr -8[EBP]
push dword ptr -4[EBP]
push dword ptr -8[EBP]
call near ptr _sqrt
add ESP,8
push dword ptr FLAT:CONST[04h]
push dword ptr FLAT:CONST[00h]
fstp qword ptr -014h[EBP]
call near ptr _sqrt
add ESP,8
fld qword ptr -014h[EBP]
fxch ST(1)
fucompp ST(1),ST
fstsw AX
sahf
jp L40
je L4D
L40: push 6
mov EAX,offset FLAT:___a7_74657374322e64
push EAX
call near ptr __d_assertp
L4D: xor EAX,EAX
leave
ret
Both calls to sqrt() produce the same result in ST0. But the first one stores and reloads it as a double, thus causing a round-to-double operation. The second does not, so they compare unequal. yebblies is right.
I'm not sure what the right fix would be. I could change sqrt() in DMC's runtime library to store/load the value it returns, but that wouldn't fix things for FreeBSD32.
On Win64 there isn't a problem because the sqrt() result is returned in XMM0 rather than ST0.