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

icpc (ICC) 12.0.4 20110427 bug???

Seunghwa_Kang
Beginner
449 Views
Hello,

I ran the following code and it works OK (does not exit the while loop)if I use -O1 to compile but fails (exits the while loop and prints "I reached here.") from -O2 (and -O3). This works OK with gcc. This also works OK if I merge test.cpp and main.cpp to a single file even with icpc -O3.

/opt/intel/bin/icpc --version prints

icpc (ICC) 12.0.4 20110427

Copyright (C) 1985-2011 Intel Corporation. All rights reserved.

and I am compiling on a Linux box (uname -r prints 2.6.18-274.3.1.e15) with four X7560 2.27 GHz processors.

* test.h *

class Test {

public:

int var;

public:

Test();

~Test();

void test();

};

* main.cpp *

#include

#include "test.h"

using namespace std;

int main( void ) {

int debugRun;

Test myTest;

myTest.var = 5;

if( myTest.var < 10 ) {

debugRun = 1;

}

else {

debugRun = 0;

}

while( true ) {

if( debugRun == 0 ) {

break;

}

}

cout << "I reached here." << endl;

myTest.test();

return 0;

}

* test.cpp *

#include

#include "test.h"

using namespace std;

Test::Test() {

}

Test::~Test() {

}

void Test::test() {

return;

}

0 Kudos
1 Solution
Hubert_H_Intel
Employee
449 Views
I filed a bug report and will keep you informed. Hubert.

View solution in original post

0 Kudos
9 Replies
Hubert_H_Intel
Employee
449 Views
Your finding is right.It's most likely an issue with optimizations where icpc optimizes away "unused" code. But let me check. Hubert.
0 Kudos
Hubert_H_Intel
Employee
449 Views

Yes, debugRun is being optimized away so that in the while loop is not being executed with a -O2 built. As a workaround you may declare debugRun as volatile.
Let me check with engineering. I my mind the bahvior of icpc is not correct.
Regards, Hubert.

0 Kudos
Hubert_H_Intel
Employee
450 Views
I filed a bug report and will keep you informed. Hubert.
0 Kudos
levicki
Valued Contributor I
449 Views
Weird behavior.
0 Kudos
Hubert_H_Intel
Employee
449 Views

I'm sorry to tell you that there will be no fix. The defect I filed has been rejected. It's the intended behavior of the Intel Compiler to eliminate all dead code after inlining and macro expansion. In your example the variable debugRun doesn't have any 'load' and isn't being processed and used further.
Declaring debugRun as int volatile (global in main()) will be the solutionto indicate the compiler that the varibale must not be optimized away since it may be used by anotherprocess outside the compiler's scope.
Makes sense.I hope you can deal with this solution.
Regards, Hubert.

0 Kudos
SergeyKostrov
Valued Contributor II
449 Views
I'm sorry to tell you that there will be no fix. The defect I filed has been rejected. It's the intended
behavior of the Intel Compiler to eliminate all dead code after inlining and macro expansion. In your
example the variable debugRun doesn't have any 'load' and isn't being processed and used further.

[SergeyK] Hold on, please. In aSINGLE THREAD Test-Casea software developer wanted to do
an INFINITE loop:

...
while( true )
{
if( debugRun == 0 )
{
break;
}
}
...

and deliberately didn't create acondition to exitthe loop.An ulitimate decision in that
Test-Case is made by a developer. A developer assumes that the'debugRun' variable won't be
changedby another thread, process, or anything else, because this is a SINGLE THREAD Test-Case.

That's very "interesting" when some optimization problems or bugs are explained as 'the intended behavior'.

Declaring debugRun as int volatile (global in main()) will be the solutionto indicate the compiler that
the varibale must not be optimized away since it may be used by anotherprocess outside the compiler's scope.

[SergeyK] No. I'd like to repeat this is a Test-Case with 'No-Exit' regardless of optimization options
ofany C/C++ compiler, except for Intel C/C++ compiler with options'-O2' or'-O3'.

Makes sense.

[SergeyK] Sorry, No.

I hope you can deal with this solution.
Regards, Hubert.


Best regards,
Sergey

0 Kudos
levicki
Valued Contributor I
449 Views
After looking more closely at the code:
[cpp]	int	debugRun;
	Test	myTest;

	myTest.var = 5;

	if (myTest.var < 10) {
		debugRun = 1;
	} else {
		debugRun = 0;
	}

	while (true) {
		if (debugRun == 0) {
			break;
		}
	}

	cout << "I reached here." << endl;
[/cpp]
I agree with Sergey that this is a compiler optimizer bug, and a serious one.

Analysis:

- myTest.var is assigned a value of 5 at compile time. Because of that, it can be treated as a constant.
- Compiler evaluates the conditional (myTest.var < 10) at compile time, and since it evaluates to true it sets variable debugRun to 1.
- Since variable debugRun is now 1 and hence constant, the code inside of a conditional (debugRun == 0) will never be executed so the compiler correctly decides that the whole conditional can be removed from the while loop.
- What compiler does incorrectly is that it assumes that it can also remove now empty while loop since inner code (or what it considers a loop workload) has been removed!

So, it is not a problem that the variable debugRun is getting optimized away (that indeed can be eliminated by declaring it volatile or even better, declaring myTest.var volatile) -- it is a problem that the while loop is optimized away as a consequence of removing its contents, which in turn produces exactly the opposite logic result from the one expected.

0 Kudos
SergeyKostrov
Valued Contributor II
449 Views
Quoting Igor Levicki
...
- Since variable debugRun is now 1 and hence constant, the code inside of a conditional (debugRun == 0) will never be executed so the compiler correctly decides that the whole conditional can be removed from the while loop.

[SergeyK] Thank you, Igor, for the analysis!

- What compiler does incorrectly is that it assumes that it can also remove now empty while loop since inner code (or what it considers a loop workload) has been removed!

So, it is not a problem that the variable debugRun is getting optimized away (that indeed can be eliminated by declaring it volatile or even better, declaring myTest.var volatile) -- it is a problem that the while loop is optimized away as a consequence of removing its contents, which in turn produces exactly the opposite logic result from the one expected.


Just in case... Here is whata 'Quick-Reference Guide to Optimization with Intel Compilers version 12' says
about oprimization options:

...
O1 - Optimize for size. Omits optimizations that tend to increase object size. Creates the
smallest optimized code in most cases. This option is useful in many large server/database
applications where memory paging due to larger code size is an issue.

O2 - Maximize speed. Default setting. Enables many optimizations, including vectorization.
Creates faster code than /O1 (-O1) in most cases.

O3 - Enables /O2 (-O2) optimizations plus more aggressive loop and memory-access optimizations,
such as scalar replacement, loop unrolling, code replication to eliminate branches,
loop blocking to allow more efficient use of cache and additional data prefetching.
The /O3 (-O3) option is particularly recommended for applications that have loops that
do many floating-point calculations or process large data sets. These aggressive
optimizations may occasionally slow down other types of applications compared to /O2 (-O2).
...

Best regards,
Sergey

0 Kudos
levicki
Valued Contributor I
449 Views
I have submitted an issue together with a test case to Intel Premier support. The issue number is 659148.

In creating and verifying a test case I have also noticed that the compiler produces expected result if all the code is in a single .cpp file.
0 Kudos
Reply