I'm writing some math code in C#, forcing it to compile for x86 in release, optimized, and I'm looking at the disassembly in windbg. It's usually pretty good, often writing better assembly than I could (not that I'm all that good at assembly, but there you go).
However, I've noticed that this function:
static void TemporaryWork()
{
double x = 4;
double y = 3;
double z = Math.Atan2(x, y);
}
Is producing this disassembly:
001f0078 55 push ebp
001f0079 8bec mov ebp,esp
001f007b dd05a0001f00 fld qword ptr ds:[1F00A0h]
001f0081 83ec08 sub esp,8
001f0084 dd1c24 fstp qword ptr [esp]
001f0087 dd05a8001f00 fld qword ptr ds:[1F00A8h]
001f008d 83ec08 sub esp,8
001f0090 dd1c24 fstp qword ptr [esp]
001f0093 e86e9ba66f call clr!GetHashFromBlob+0x94e09 (6fc59c06) (System.Math.Atan2(Double, Double), mdToken: 06000de7)
001f0098 ddd8 fstp st(0)
001f009a 5d pop ebp
001f009b c3 ret
Even if you're not an x86 guru, you'll notice something odd in there: there's a call to System.Math.Atan2. As in a function call.
But there's actually an x86 opcode that would do that: FPATAN
Why is the JITer calling a function when there's an actual assembly instruction to do the operation? I thought that System.Math was basically a wrapper for native assembly instructions. Most of the operations in there have direct assembly opcodes. But that's apparently not the case?
Does anyone have any information on why the JITer isn't/can't perform this rather obvious optimization?
You can chase down the reason from this answer, it shows how these math functions are mapped by the jitter.
Which takes you to clr/src/classlibnative/float/comfloat.cpp, ComDouble::Atan2() function. Which explains the reason:
// the intrinsic for Atan2 does not produce Nan for Atan2(+-inf,+-inf)
if (IS_DBL_INFINITY(x) && IS_DBL_INFINITY(y)) {
return(x / y); // create a NaN
}
return (double) atan2(x, y);
So it is a workaround to fix FPU behavior that is not CLI compliant.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With