- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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;
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- 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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page