<?xml version="1.0" encoding="UTF-8" standalone="yes"?><oembed><version><![CDATA[1.0]]></version><provider_name><![CDATA[Krzysztof Narkowicz]]></provider_name><provider_url><![CDATA[https://knarkowicz.wordpress.com]]></provider_url><author_name><![CDATA[Krzysztof Narkowicz]]></author_name><author_url><![CDATA[https://knarkowicz.wordpress.com/author/knarkowicz/]]></author_url><title><![CDATA[C++ compiler VS&nbsp;human]]></title><type><![CDATA[link]]></type><html><![CDATA[<div>
<p>There is a very nice article about writing fast math library on <a href="http://www.gamasutra.com/view/feature/4248/designing_fast_crossplatform_simd_.php">gamasutra</a>. 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&#8217;t check that their compiler generates.</p>
</div>
<p>Let&#8217;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 <a href="http://realtimecollisiondetection.net/pubs/GDC03_Ericson_Memory_Optimization.ppt"><span id="goog_800920421"></span>aliasing<span id="goog_800920422"></span></a>.  I have chosen VC++ 2008, because it&#8217;s the most popular compiler in gamedev industry (and I think it will maintain it&#8217;s position until the VC++2010 SP1 release 🙂 ).</p>
<p>Default release build settings &#8211; /O2 etc. + very simple test cases, just int main(), scanf and printf.</p>
<pre class="brush: cpp; title: ; notranslate" title="">
// x/x = 1
int y = x / x;

00401018 mov ecx,dword ptr [esp+8]
0040101C mov eax,ecx
0040101E cdq
0040101F idiv eax,ecx

</pre>
<p>mov and idiv? FAIL.</p>
<pre class="brush: cpp; title: ; notranslate" title="">
// 0/x = 0
int y = 0 / x;

00401018 xor eax,eax
0040101A cdq
0040101B idiv eax,dword ptr [esp+8]

</pre>
<p>Another idiv, but at least compiler uses xor instead of loading 0 from memory.</p>
<pre class="brush: cpp; title: ; notranslate" title="">
// 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

</pre>
<p>It was also too difficult for the compiler.</p>
<p>Ok, so maybe let&#8217;s try some OO code?</p>
<pre class="brush: cpp; title: ; notranslate" title="">
class Object0
{
public:
    void virtual Print() { printf( &quot;a&quot; ); }
};

int main()
{
    Object0 *obj = new Object0;
    obj-&gt;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

</pre>
<p>vftable? Another failure. Generated code can be fixed by writing obj-&gt;Object1::Print(); or removing virtual keyword.</p>
<p>Remember to hit alt+8 next time to open the disasm window :).</p>
]]></html></oembed>