Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.

Infinite loop - bug?

Markus_G_
Beginner
405 Views

Hi,

the do-while loop in the following code segment won't terminate in release mode.

(Windows 7, Visual Studio 2013, ICL version 15.0.3.208 Build 20150407)

unsigned short arr[256];
signed char index = SCHAR_MIN;
do {
	arr[(unsigned char)index] = (unsigned short)index;
} while(index++ < SCHAR_MAX);

Compiled in release mode with:

/GS /W3 /Gy /Zc:wchar_t /Zi /O2 /Ob2 /Fd"x64\Release\vc120.pdb" /Quse-intel-optimized-headers /D "_HAS_EXCEPTIONS=0" /D "_WIN64" /D "NDEBUG" /D "_CONSOLE" /D "_LIB" /D "_UNICODE" /D "UNICODE" /Qipo /Zc:forScope /arch:AVX /Oi /MD /Fa"x64\Release\" /EHsc /nologo /Fo"x64\Release\" /Qprof-dir "x64\Release\" /Fp"x64\Release\testing.pch" 

In debug mode everything goes fine. Debug mode compiler arguments:

/GS /W3 /Zc:wchar_t /Zi /Od /Fd"x64\Debug\vc120.pdb" /D "_HAS_EXCEPTIONS=0" /D "_WIN64" /D "_DEBUG" /D "_CONSOLE" /D "_LIB" /D "_UNICODE" /D "UNICODE" /Zc:forScope /RTC1 /arch:AVX /MDd /Fa"x64\Debug\" /EHsc /nologo /Fo"x64\Debug\" /Qprof-dir "x64\Debug\" /Fp"x64\Debug\testing.pch" 

When inserting a print statement after the array access the issue is gone.

Thank you.

-------------------------

ASM Code:

Release:

signed char index = SCHAR_MIN;
000000013F481049  xor         eax,eax  
	do {
		arr[(unsigned char)index] = (unsigned char)index;
000000013F48104B  vpshufd     xmm0,xmm0,0  
000000013F481050  vpaddb      xmm5,xmm1,xmm0  
000000013F481054  vpaddb      xmm8,xmm5,xmm0  
000000013F481058  vpaddb      xmm11,xmm8,xmm0  
	unsigned short arr[256];
	signed char index = SCHAR_MIN;
000000013F48105C  add         eax,0FFFFFF80h  
	do {
		arr[(unsigned char)index] = (unsigned char)index;
000000013F48105F  vpaddb      xmm14,xmm11,xmm0  
000000013F481063  vpaddb      xmm2,xmm14,xmm0  
000000013F481067  vpaddb      xmm5,xmm2,xmm0  
000000013F48106B  vpaddb      xmm8,xmm5,xmm0  
000000013F48106F  vpaddb      xmm1,xmm8,xmm0  
000000013F481073  jmp         main+50h (013F481050h)  

Release with print statement:

signed char index = SCHAR_MIN;
000000013F8D106E  mov         ebx,0FFFFFF80h  
	do {
		arr[(unsigned char)index] = (unsigned char)index;
		std::cout << index << std::endl;
000000013F8D1073  mov         edx,ebx  
000000013F8D1075  mov         rcx,qword ptr [__imp_std::cout (013F8DF0A0h)]  
000000013F8D107C  call        std::operator<< (013F8D2B30h)  
000000013F8D1081  mov         rcx,rax  
000000013F8D1084  lea         rdx,[std::endl (013F8D6850h)]  
000000013F8D108B  call        qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (013F8DF150h)]  
	} while(index++ < SCHAR_MAX);
000000013F8D1091  movsx       rax,bl  
000000013F8D1095  inc         ebx  
000000013F8D1097  cmp         eax,7Fh  
000000013F8D109A  jl          main+73h (013F8D1073h)  

Debug:

signed char index = SCHAR_MIN;
000000013FCF2B0D  mov         byte ptr [rbp],80h  
	do {
		arr[(unsigned char)index] = (unsigned char)index;
000000013FCF2B11  movsx       eax,byte ptr [rbp]  
000000013FCF2B15  movsx       rax,al  
000000013FCF2B19  movzx       eax,al  
000000013FCF2B1C  lea         rdx,[arr]  
000000013FCF2B23  movsx       ecx,byte ptr [rbp]  
000000013FCF2B27  movsx       rcx,cl  
000000013FCF2B2B  movzx       ecx,cl  
000000013FCF2B2E  imul        rcx,rcx,2  
000000013FCF2B32  add         rdx,rcx  
000000013FCF2B35  mov         word ptr [rdx],ax  
	} while(index++ < SCHAR_MAX);
000000013FCF2B38  movsx       eax,byte ptr [rbp]  
000000013FCF2B3C  movsx       rax,al  
000000013FCF2B40  mov         dword ptr [rbp+4],eax  
000000013FCF2B43  movsx       eax,byte ptr [rbp]  
000000013FCF2B47  mov         edx,1  
000000013FCF2B4C  add         eax,edx  
000000013FCF2B4E  mov         byte ptr [rbp],al  
000000013FCF2B51  mov         eax,dword ptr [rbp+4]  
000000013FCF2B54  cmp         eax,7Fh  
000000013FCF2B57  jl          main+0C9h (013FCF2B11h)  

 

0 Kudos
4 Replies
jimdempseyatthecove
Honored Contributor III
405 Views

This may be a case of the optimization process not removing the entire loop due to it being dead code. (IOW arr is not used after initialization). Try to fool the compiler into your using it:

unsigned short arr[256];
signed char index = SCHAR_MIN;
do {
 arr[(unsigned char)index] = (unsigned short)index;
} while(index++ < SCHAR_MAX);
// dummy statement to use something in arr
if(arr[99] == 0) std::cout << "this won't happen";

Jim Dempsey

0 Kudos
jimdempseyatthecove
Honored Contributor III
405 Views

In cases like this, it might be useful to have a #pragma that turns off/on dead code elimination. Though I'd place this at the bottom of the wish list.

Example of practical use is you have an array that traces progress of various sections of your (Release) code and this trace array is not used by any of your code (other than for writing progress updates). The array is use though in a post-mortem dump or debug session. Currently one must resort to inserting something apparently useless, as I did above. Note, at some point, compiler optimization may advance to a point where you otherwise useless statements are recognized as such and are eliminated, then this undoes your attempt at thwarting dead code elimination.

Jim Dempsey

0 Kudos
Markus_G_
Beginner
405 Views
A macro wouldn't solve the problem, because the code segment was part of a bigger program (inside a function). With Clang and MSVC everything was fine, but when switching to the Intel compiler a infinite loop was created. I also realized, that changing from a do-while to a for loop solves the problem. The lookup table being created inside the loop is being used several times afterwards, so it's no dead code. Markus
0 Kudos
Feilong_H_Intel
Employee
405 Views

Hi Markus,

Would you please upload a preprocessed source file, so that we can try to compile it with different options?  Otherwise, please at lease show us a bigger code snippet or even better, the whole function.

Thanks.

0 Kudos
Reply