Tuesday, May 4, 2010

C++ compiler VS human

There is a very nice article about writing fast math library on gamasutra. It shows for example that using operator overloading generates slower code than when using functions. A lot of people believe that compiler will generate better code than a programmer can. They just happily write code and don't check that their compiler generates.

Let's test how good is VC++ against simple algebra and OOP crap :). I decided to be not too harsh, so I omitted here topics like SIMD, FPU or aliasing.  I have chosen VC++ 2008, because it's the most popular compiler in gamedev industry (and I think it will maintain it's position until the VC++2010 SP1 release :) ).

Default release build settings - /O2 etc. + very simple test cases, just int main(), scanf and printf.

// x/x = 1
int y = x / x;

00401018  mov         ecx,dword ptr [esp+8] 
0040101C  mov         eax,ecx 
0040101E  cdq              
0040101F  idiv        eax,ecx
mov and idiv? FAIL.

// 0/x = 0
int y = 0 / x;

00401018  xor         eax,eax 
0040101A  cdq              
0040101B  idiv        eax,dword ptr [esp+8] 
Another idiv, but at least compiler uses xor instead of loading 0 from memory.

// z = x * x
// w = z * z
// y = w * w
int y = x * x * x * x * x * x * x * x;

00401018  mov         eax,dword ptr [esp+8] 
0040101C  mov         ecx,eax 
0040101E  imul        ecx,eax 
00401021  imul        ecx,eax 
00401024  imul        ecx,eax 
00401027  imul        ecx,eax 
0040102A  imul        ecx,eax 
0040102D  imul        ecx,eax 
00401030  imul        ecx,eax
It was also too difficult for the compiler.

Ok, so maybe let's try some OO code?
#include <stdio.h>

class Object0
{
public:
    void virtual Print() { printf( "a" ); }
};

int main()
{
    Object0 *obj = new Object0;
    obj->Print();
    return 0;
}

0040101E  mov         dword ptr [eax],offset Object0::`vftable' (402104h)
00401024  mov         edx,dword ptr [eax] 
00401026  mov         ecx,eax 
00401028  mov         eax,dword ptr [edx] 
0040102A  call        eax
vftable? Another failure. Generated code can be fixed by writing obj->Object1::Print(); or removing virtual keyword.

Remember to hit alt+8 next time to open the disasm window :).

0 comments:

Post a Comment