By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,269 Members | 1,506 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,269 IT Pros & Developers. It's quick & easy.

Observable behavior and instruction reordering

P: n/a
<CODE>

#include <iostream>
using namespace std;

int Foo(int x,int y)
{
int result = x;
result*=y;
result+=y;
return result;
}

int main()
{
cout<<Foo(2,4)<<endl; // I expect this to output 12 --LINE 1

cout<<Foo(4,2)<<endl; //I expect this to output 10 --LINE 2

return 0;
}

</CODE>

Are my expectations concerning the output of this program reasonable?

My concern stems from a lack of understanding of instruction reordering as it
relates to observable behavior.

Specifically I wonder if the expressions result*=y and result+=y in function
Foo could be swapped. That of course would change the meaning of Foo.
However, the following quote from the Draft Ansi C++ Standard makes me think
that the meaning of Foo is not observable behavior...

"The observable behavior of the abstract machine is its sequence of reads and
writes to volatile data and calls to library I/O functions."

Based on this quote the only behavior I would expect is that LINE 1 will
execute before LINE 2.

When a compiler reorders instructions that don't involve R/W to volatile data
and calls to library I/O functions how does it know that it is not changing the
meaning of a program?

Any insights as to what I am not grokking would be appreciated.
Jul 22 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a

"DaKoadMunky" <da*********@aol.com> wrote in message
news:20***************************@mb-m22.aol.com...
<CODE>

#include <iostream>
using namespace std;

int Foo(int x,int y)
{
int result = x;
result*=y;
result+=y;
return result;
}

int main()
{
cout<<Foo(2,4)<<endl; // I expect this to output 12 --LINE 1

cout<<Foo(4,2)<<endl; //I expect this to output 10 --LINE 2

return 0;
}

</CODE>

Are my expectations concerning the output of this program reasonable?

My concern stems from a lack of understanding of instruction reordering as it relates to observable behavior.

Specifically I wonder if the expressions result*=y and result+=y in function Foo could be swapped. That of course would change the meaning of Foo.
However, the following quote from the Draft Ansi C++ Standard makes me think that the meaning of Foo is not observable behavior...

"The observable behavior of the abstract machine is its sequence of reads and writes to volatile data and calls to library I/O functions."

Based on this quote the only behavior I would expect is that LINE 1 will
execute before LINE 2.

When a compiler reorders instructions that don't involve R/W to volatile data and calls to library I/O functions how does it know that it is not changing the meaning of a program?

Any insights as to what I am not grokking would be appreciated.


If the instructions were reordered in the way you suggest then you would not
see cout << 12 followed by cout << 10 (you would see cout << 24 followed by
cout << 12), therefore the observable behaviour would have changed because
the values of the arguments used in a standard library call would have
changed, and therefore the compiler would not be allowed to do that
reordering.

John
Jul 22 '05 #2

P: n/a
da*********@aol.com (DaKoadMunky) wrote in
news:20***************************@mb-m22.aol.com:
<CODE>

#include <iostream>
using namespace std;

int Foo(int x,int y)
{
int result = x;
result*=y;
result+=y;
return result;
}

int main()
{
cout<<Foo(2,4)<<endl; // I expect this to output 12 --LINE 1

cout<<Foo(4,2)<<endl; //I expect this to output 10 --LINE 2

return 0;
}

</CODE>

Are my expectations concerning the output of this program reasonable?

My concern stems from a lack of understanding of instruction
reordering as it relates to observable behavior.

Specifically I wonder if the expressions result*=y and result+=y in
function Foo could be swapped. That of course would change the
meaning of Foo. However, the following quote from the Draft Ansi C++
Standard makes me think that the meaning of Foo is not observable
behavior...

"The observable behavior of the abstract machine is its sequence of
reads and writes to volatile data and calls to library I/O functions."

Based on this quote the only behavior I would expect is that LINE 1
will execute before LINE 2.

When a compiler reorders instructions that don't involve R/W to
volatile data and calls to library I/O functions how does it know that
it is not changing the meaning of a program?


Because the people who created it, told it to only reorder those things
that won't break the meaning of the program. Observable behaviour is not
the only criteria when dealing with instruction reordering, obviously.

Cheers.
--
:: bartekd / o2 pl
:: "out of confusion comes chaos -- out of chaos comes confusion and fear
:: -- then comes lunch."

Jul 22 '05 #3

P: n/a
On 09 Aug 2004 11:17:04 GMT, da*********@aol.com (DaKoadMunky) wrote:
<CODE>

#include <iostream>
using namespace std;

int Foo(int x,int y)
{
int result = x;
result*=y;
result+=y;
return result;
}

int main()
{
cout<<Foo(2,4)<<endl; // I expect this to output 12 --LINE 1

cout<<Foo(4,2)<<endl; //I expect this to output 10 --LINE 2

return 0;
}

</CODE>

Are my expectations concerning the output of this program reasonable?
Yes, any standards conforming compiler should produce a program that
outputs:
12
10
My concern stems from a lack of understanding of instruction reordering as it
relates to observable behavior.

Specifically I wonder if the expressions result*=y and result+=y in function
Foo could be swapped. That of course would change the meaning of Foo.
However, the following quote from the Draft Ansi C++ Standard makes me think
that the meaning of Foo is not observable behavior...

"The observable behavior of the abstract machine is its sequence of reads and
writes to volatile data and calls to library I/O functions."

Based on this quote the only behavior I would expect is that LINE 1 will
execute before LINE 2.
"calls to library I/O functions" includes what is passed to those
functions! i.e. any reorderings that the compiler does must not change
the appearance of the output of a conforming program in any way.
When a compiler reorders instructions that don't involve R/W to volatile data
and calls to library I/O functions how does it know that it is not changing the
meaning of a program?


If it can't determine that it won't make a difference to observable
behaviour, it won't reorder (since it is forbidden by the standard).

Tom
Jul 22 '05 #4

P: n/a
DaKoadMunky wrote:
<CODE>

#include <iostream>
using namespace std;

int Foo(int x,int y)
{
int result = x;
result*=y;
result+=y;
return result;
}

int main()
{
cout<<Foo(2,4)<<endl; // I expect this to output 12 --LINE 1

cout<<Foo(4,2)<<endl; //I expect this to output 10 --LINE 2

return 0;
}

</CODE>

Are my expectations concerning the output of this program reasonable?

My concern stems from a lack of understanding of instruction reordering as it
relates to observable behavior.

Specifically I wonder if the expressions result*=y and result+=y in function
Foo could be swapped. That of course would change the meaning of Foo.
However, the following quote from the Draft Ansi C++ Standard makes me think
that the meaning of Foo is not observable behavior...

"The observable behavior of the abstract machine is its sequence of reads and
writes to volatile data and calls to library I/O functions."

Based on this quote the only behavior I would expect is that LINE 1 will
execute before LINE 2.

When a compiler reorders instructions that don't involve R/W to volatile data
and calls to library I/O functions how does it know that it is not changing the
meaning of a program?

Any insights as to what I am not grokking would be appreciated.


A translator is allowed to set the ordering of the instructions as long
as the functionality remains the same.

In your example, changing the order of the mathematical assignments
will change the meaning. However, there is nothing stopping a
translator changing the order of the assignment operation.

Your function evaluates the expression: f(x,y) = x * y + y;
The actually assignment of the value to result could be postponed
or not even occur at all (since the value is returned and not
stored in any static memory location). For example, your function
could be translated as:
int Foo(int x, int y)
{
return x * y + y;
}
The above function provides the same functionality, but has
no assignment operations.

There are no libraries calls, no I/O and no volatile or static
variables.

However, changing the order of the operations will change the
functionality.

The rules allow for compilers to optimize code. The qualifiers
"static", "volatile" and "mutable" are used to control the
optimization. During debugging, I may declare a variable
in a function as "static" so that the variable isn't "optimized
away". I use "volatile" when accessing hardware values so that
the compiler doesn't "optimize away" a variable that is read
only once.

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.comeaucomputing.com/learn/faq/
Other sites:
http://www.josuttis.com -- C++ STL Library book

Jul 22 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.