- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I found a bug when using the inline ASM of Intel Parallel Studio XE 2015 Update 2 Composer Edition for C++ Windows. Since I'm not very familiar with inline ASM, I'm not sure if it is a bug.
#include <iostream> using namespace std; __forceinline void DoNothingWithMemory( float*const copyByValue ) { float* copyByValueAgain = copyByValue ; /* As you see, the two var in this function, "copyByValueAgain" and "copyByValue", are copied by value. Therefore, even if the code block of inline asm below changes one of them, there's nothing to do with the var "p" in the main function. However, the fact is, the var "p" in the main function IS changed after executing the code block of inline asm below! */ __asm__ __volatile__( "lea 4(%0),%0;" //In fact, nothing is done here. It's just a "lea", and has nothing to do with memory or pointer aliasing! : :"r"( copyByValueAgain ) : ); } int main() { float a; //just a place holder float* const p=&a; // As "p" is "const", it's impossible to change and should always point to "&a". for(int i = 0; i < 999; ++i) { cout<<p<<endl; // However, if you take a look at the output of this instruction, you will find that "p" changes every each loop, and that's really weird. DoNothingWithMemory(p); } system("PAUSE"); }
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
OK, I am clear about the issue now, in your case, copyByValueAgain is used as both input and output variable, you need to describe that to compiler so that it will not generate unexpected code.
You may refer to below link to know how to declare a variable in inline asm as both input and output.
And the working code is as below:
# cat temp.cpp
#include <stdio.h>
void DoNothingWithMemory(float* const copyByValue )
{
float* copyByValueAgain = copyByValue ;
/*
* As you see, the two var in this function, "copyByValueAgain" and "copyByValue", are copied by value. Therefore, even if the code block of inline asm below changes one of them, there's nothing to do with the var "p" in the main function. However, the fact is, the var "p" in the main function IS changed after executing the code block of inline asm below!
* */
__asm__ __volatile__(
"lea 8(%0),%0;" //In fact, nothing is done here. It's just a "lea", and has nothing to do with memory or pointer aliasing!
:"+r"(copyByValueAgain) // CHANGES HERE!!!!!!!!!!!
://"r"( copyByValueAgain ) // CHANGES HERE!!!!!!!!!!!
: ); } int main() { float a; //just a place holder float* const p=&a; // As "p" is "const", it's impossible to change and should always point to "&a". for(int i = 0; i < 5; ++i) { printf("%p\n", p); // However, if you take a look at the output of this instruction, you will find that "p" changes every each loop, and that's really weird. DoNothingWithMemory(p); } return 0; } # g++ temp.cpp -O3 && ./a.out 0x7fffb6337e50 0x7fffb6337e50 0x7fffb6337e50 0x7fffb6337e50 0x7fffb6337e50 # icc temp.cpp -O3 && ./a.out 0x7fff29fdad84 0x7fff29fdad84 0x7fff29fdad84 0x7fff29fdad84 0x7fff29fdad84 #
Thanks,
Shenghong
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
P.S. In the case of "/O2"
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I've reproduce the issue on Linux too. It seems like an optimization issue, which works with O1. I'll report to dev team to check.
Thanks,
Shenghong
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
oops....The same test case failed with g++ in optimization mode too.
# g++ temp.cpp -O1 && ./a.out 0x7fff33ed950c 0x7fff33ed9510 0x7fff33ed9514 0x7fff33ed9518 0x7fff33ed951c #
Maybe it is not a bug (the result may be undefined), I'll take a closer look at the code and hope I can get a good explanation on the behavior of gcc/icc.
Thanks,
Shenghong
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
OK, I am clear about the issue now, in your case, copyByValueAgain is used as both input and output variable, you need to describe that to compiler so that it will not generate unexpected code.
You may refer to below link to know how to declare a variable in inline asm as both input and output.
And the working code is as below:
# cat temp.cpp
#include <stdio.h>
void DoNothingWithMemory(float* const copyByValue )
{
float* copyByValueAgain = copyByValue ;
/*
* As you see, the two var in this function, "copyByValueAgain" and "copyByValue", are copied by value. Therefore, even if the code block of inline asm below changes one of them, there's nothing to do with the var "p" in the main function. However, the fact is, the var "p" in the main function IS changed after executing the code block of inline asm below!
* */
__asm__ __volatile__(
"lea 8(%0),%0;" //In fact, nothing is done here. It's just a "lea", and has nothing to do with memory or pointer aliasing!
:"+r"(copyByValueAgain) // CHANGES HERE!!!!!!!!!!!
://"r"( copyByValueAgain ) // CHANGES HERE!!!!!!!!!!!
: ); } int main() { float a; //just a place holder float* const p=&a; // As "p" is "const", it's impossible to change and should always point to "&a". for(int i = 0; i < 5; ++i) { printf("%p\n", p); // However, if you take a look at the output of this instruction, you will find that "p" changes every each loop, and that's really weird. DoNothingWithMemory(p); } return 0; } # g++ temp.cpp -O3 && ./a.out 0x7fffb6337e50 0x7fffb6337e50 0x7fffb6337e50 0x7fffb6337e50 0x7fffb6337e50 # icc temp.cpp -O3 && ./a.out 0x7fff29fdad84 0x7fff29fdad84 0x7fff29fdad84 0x7fff29fdad84 0x7fff29fdad84 #
Thanks,
Shenghong
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
shenghong-geng (Intel) wrote:
OK, I am clear about the issue now, in your case, copyByValueAgain is used as both input and output variable, you need to describe that to compiler so that it will not generate unexpected code.
You may refer to below link to know how to declare a variable in inline asm as both input and output.
http://stackoverflow.com/questions/15993934/extended-inline-assembly-sam...
And the working code is as below:
# cat temp.cpp #include <stdio.h> void DoNothingWithMemory(float* const copyByValue ) { float* copyByValueAgain = copyByValue ; /* * As you see, the two var in this function, "copyByValueAgain" and "copyByValue", are copied by value. Therefore, even if the code block of inline asm below changes one of them, there's nothing to do with the var "p" in the main function. However, the fact is, the var "p" in the main function IS changed after executing the code block of inline asm below! * */ __asm__ __volatile__( "lea 8(%0),%0;" //In fact, nothing is done here. It's just a "lea", and has nothing to do with memory or pointer aliasing! :"+r"(copyByValueAgain) // CHANGES HERE!!!!!!!!!!! ://"r"( copyByValueAgain ) // CHANGES HERE!!!!!!!!!!!: ); } int main() { float a; //just a place holder float* const p=&a; // As "p" is "const", it's impossible to change and should always point to "&a". for(int i = 0; i < 5; ++i) { printf("%p\n", p); // However, if you take a look at the output of this instruction, you will find that "p" changes every each loop, and that's really weird. DoNothingWithMemory(p); } return 0; } # g++ temp.cpp -O3 && ./a.out 0x7fffb6337e50 0x7fffb6337e50 0x7fffb6337e50 0x7fffb6337e50 0x7fffb6337e50 # icc temp.cpp -O3 && ./a.out 0x7fff29fdad84 0x7fff29fdad84 0x7fff29fdad84 0x7fff29fdad84 0x7fff29fdad84 #Thanks,
Shenghong
Hey Shenghong,
Thank you very much for your explicit explanation!
MengKe

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