"He who knows not, and knows not that he knows not, is a fool...shun him.
He who knows not, and knows that he knows not, is willing...teach him.
He who knows, and knows not that he knows, is asleep...awaken him.
He who knows, and knows that he knows, is wise...follow him."
- Chinese Probverb

Whoha, I found a compiler bug
Thursday, February 18, 2010 | Permalink

I gave Visual Studio 2010 RC a few quick runs and while doing so I noticed that it doesn't always generate optimal code with the StringHash code I mentioned recently. Often it behaves just like you expect and outputs the constant directly, but it happens that it generates some clearly suboptimal results. This is a call to Context::SetConstantBuffer():

mov eax, dword ptr [ebx+9D0h]
push eax
push ecx
mov eax, esp
mov dword ptr [eax], 0
mov dword ptr [eax], 54h
mov dword ptr [eax], 541514h
mov dword ptr [eax], 29C53055h
mov dword ptr [eax], 77DBE55Eh
mov dword ptr [eax], 647B726Bh
mov dword ptr [eax], 2CCC28C8h
mov dword ptr [eax], 2F060985h
mov dword ptr [eax], 9C015834h
mov dword ptr [eax], 0BC88B513h
mov dword ptr [eax], 1AB79019h
mov dword ptr [eax], 23457696h
mov dword ptr [eax], 24AE2F4Ch
mov dword ptr [eax], 3629A415h
mov dword ptr [eax], 0F8546197h
mov dword ptr [eax], 7E5B047Ch
mov dword ptr [eax], 1CE21AF8h
mov dword ptr [eax], 369CA37Ah
mov dword ptr [eax], 14063B6Fh
mov dword ptr [eax], 28F7A0BFh
push esi
mov dword ptr [eax], 0B5AF8F68h
call Context::SetConstantBuffer (404750h)

Clearly there's a lot of superfluous writes that should have been optimized away. At first I thought this was a new bug in Visual Studio 2010, so I tried it in Visual Studio 2008 and it did the same thing. It's unclear why this happens, or what triggers this behavior, but I just noticed it happening in a certain location in my program.

So I rewrote the StringHash() constructor in this way, which appears to fix the problem:

StringHash(const char (&str)[4])
    uint32 hash0 = 0;
    uint32 hash1 = hash0 * 65599 + str[0];
    uint32 hash2 = hash1 * 65599 + str[1];
    m_Hash = hash2 * 65599 + str[2];

[ 9 comments | Last comment by Aslan Dzodzikov (2010-05-14 18:43:42) ]