Thursday, April 21, 2022

Careful with mixing types in loop variables


 The other day I stumbled upon code which accidentally used a double as end condition:

#include <cstdint>
#include <cstdlib>

constexpr double g_dW = 10;

int main()
int res = 0;

for (int n = 0; n < g_dW; ++n)
res += std::rand(); // use rand just to have a valid loop

return res;

One would think that the optimizer Visual Studio 2019 16.13 is smart enough to use integer comparison but this is not the case. VS2019 issues a relative expensive integer to double conversion and comparison:

    for (int n = 0; n < g_dW; ++n)
00007FF7C9A01011  movsd       xmm6,mmword ptr [__real@4024000000000000 (07FF7C9A02240h)]  
00007FF7C9A01019  mov         edi,ebx  
00007FF7C9A0101B  nop         dword ptr [rax+rax]  
        res += std::rand();
00007FF7C9A01020  call        qword ptr [__imp_rand (07FF7C9A02188h)]  
00007FF7C9A01026  inc         edi  
00007FF7C9A01028  add         ebx,eax  
00007FF7C9A0102A  movd        xmm0,edi  
00007FF7C9A0102E  cvtdq2pd    xmm0,xmm0  
00007FF7C9A01032  comisd      xmm6,xmm0  
00007FF7C9A01036  ja          main+20h (07FF7C9A01020h)  
    return res;

The solution is simple to use an integer as block condition:

 constexpr int g_dW = 10;

Therefore watch out that VS2019 does not optimize things automatically.


C++ horrible aspects

C++ horrible aspects  Linus Torvalds described C++ as being a horrible language. While C++ has its dark corners I choose it any day ove...