473,809 Members | 2,876 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Ternary operator and memory access


Hi all,

In a ternary statement such as: x = (cond ? a : b); it is obviously guaranteed
that "x" will be equal to "a" only if the condition "cond" holds. Assuming that
"a" is a memory location, is it also guaranteed that "a" will not be accessed
in memory if the condition does not hold?

Or, in other words, is a compiler allowed to speculatively fetch a and b from
memory and then assign one of them to x based on the condition?

- Udo
Aug 7 '06
20 2167
Eric Sosman <Er*********@su n.comwrites:
Richard wrote On 08/07/06 10:24,:
>la************@ ugs.com writes:

>>>Udo A. Steinberg <st*******@doma in.invalidwrote :

In a ternary statement such as: x = (cond ? a : b); it is obviously guaranteed
that "x" will be equal to "a" only if the condition "cond" holds. Assuming that
"a" is a memory location, is it also guaranteed that "a" will not be accessed
in memory if the condition does not hold?

Yes. The ?: operator is defined to only evaluate one of a and b, it is
not permitted to evaluate both. On the other hand, compilers are free
to do whatever they want, as long as a strictly conforming program can't
tell any difference. So a particular implementation *could*
speculativel y evaluate both a and b as long as it ensures that nothing
bad (like a trap) happens when evaluating something it shouldn't be
evaluating .


And how would a compiler determine that at compile time? It cant as far
as I can see in the case of variable memory references. So it shouldnt
access the non matching expression.

int a = f();
int b = g();
int x = cond ? (1) a : b (2);

"Hmmm. As the compiler, I happen to know that register
R0 still contains the value returned by g(), the thing I just
stored into b a moment ago. So if cond turns out to be false,
I don't need to fetch anything from memory; I've already got
exactly what's needed right here in R0. Hey, look: I've just
``evaluated'' b before testing cond, and in perfect safety!"

Generated code:

call f
store r0,a
call g
store r0,b
load r1,cond
jzero r1,label
load r0,a
label:
store r0,x
Possibly we are talking of different things. I am referring to it
accessing expression (2) when the condition is supposed to be triggering
(1). Possibly I overs implified it : there is no issue with HW if the
"result" of b=g() is used from a register. But clearly if expressions
(1) and (2) are of the form "*a" or "*b" then it would be madness for
the compiler to access *b if the condition is true. Or?
Aug 7 '06 #11
Christopher Benson-Manica <at***@ukato.fr eeshell.orgwrit es:
Richard <rg****@gmail.c omwrote:
>Is it handled any different from
>if(cond)
x=a;
else
x=b;

It is different, but in rather subtle ways. 6.5.15 of n869 places a
number of conditions on what a and b may be, as well as the type of
the result of (cond?a:b).
Thanks : I'll have a look.
Aug 7 '06 #12


Richard wrote On 08/07/06 11:05,:
Eric Sosman <Er*********@su n.comwrites:

>>Richard wrote On 08/07/06 10:24,:
>>>la********** **@ugs.com writes:

Udo A. Steinberg <st*******@doma in.invalidwrote :
>In a ternary statement such as: x = (cond ? a : b); it is obviously guaranteed
>that "x" will be equal to "a" only if the condition "cond" holds. Assuming that
>"a" is a memory location, is it also guaranteed that "a" will not be accessed
>in memory if the condition does not hold?

Yes. The ?: operator is defined to only evaluate one of a and b, it is
not permitted to evaluate both. On the other hand, compilers are free
to do whatever they want, as long as a strictly conforming program can't
tell any difference. So a particular implementation *could*
speculative ly evaluate both a and b as long as it ensures that nothing
bad (like a trap) happens when evaluating something it shouldn't be
evaluatin g.
And how would a compiler determine that at compile time? It cant as far
as I can see in the case of variable memory references. So it shouldnt
access the non matching expression.

int a = f();
int b = g();
int x = cond ? (1) a : b (2);

"Hmmm. As the compiler, I happen to know that register
R0 still contains the value returned by g(), the thing I just
stored into b a moment ago. So if cond turns out to be false,
I don't need to fetch anything from memory; I've already got
exactly what's needed right here in R0. Hey, look: I've just
``evaluated '' b before testing cond, and in perfect safety!"

Generated code:

call f
store r0,a
call g
store r0,b
load r1,cond
jzero r1,label
load r0,a
label:
store r0,x


Possibly we are talking of different things. I am referring to it
accessing expression (2) when the condition is supposed to be triggering
(1).
Same code, different execution path. The compiler
has "evaluated" b before testing cond, even if the test
says that a's value is chosen instead.
Possibly I overs implified it : there is no issue with HW if the
"result" of b=g() is used from a register. But clearly if expressions
(1) and (2) are of the form "*a" or "*b" then it would be madness for
the compiler to access *b if the condition is true. Or?
The compiler might not know whether *a,*b are or aren't
safe, but it might be able to tell that it makes no difference.

int *a = ...;
int *b = ...;
*a = 42; /* die here if *a unsafe */
*b = 56; /* die here if *b unsafe */
x = cond ? *a : *b;

The compiler might conclude that if *a,*b are unsafe the final
line won't be executed anyhow, hence a speculative fetch adds
no new failure mode to the program.

I don't know how commonly compilers "reason" this way, but
I've certainly seen compilers generate speculative fetches and
pre-fetches, sometimes far in advance of the use of the datum.
On modern machines there's a lot of incentive to do so, what
with memory being so much slower than CPUs.

--
Er*********@sun .com

Aug 7 '06 #13
Eric Sosman <Er*********@su n.comwrites:
Richard wrote On 08/07/06 11:05,:
>Eric Sosman <Er*********@su n.comwrites:

>>>Richard wrote On 08/07/06 10:24,:

la********* ***@ugs.com writes:

>Udo A. Steinberg <st*******@doma in.invalidwrote :
>
>
>>In a ternary statement such as: x = (cond ? a : b); it is obviously guaranteed
>>that "x" will be equal to "a" only if the condition "cond" holds. Assuming that
>>"a" is a memory location, is it also guaranteed that "a" will not be accessed
>>in memory if the condition does not hold?
>
>Yes. The ?: operator is defined to only evaluate one of a and b, it is
>not permitted to evaluate both. On the other hand, compilers are free
>to do whatever they want, as long as a strictly conforming program can't
>tell any difference. So a particular implementation *could*
>speculativ ely evaluate both a and b as long as it ensures that nothing
>bad (like a trap) happens when evaluating something it shouldn't be
>evaluating .
And how would a compiler determine that at compile time? It cant as far
as I can see in the case of variable memory references. So it shouldnt
access the non matching expression.

int a = f();
int b = g();
int x = cond ? (1) a : b (2);

"Hmmm. As the compiler, I happen to know that register
R0 still contains the value returned by g(), the thing I just
stored into b a moment ago. So if cond turns out to be false,
I don't need to fetch anything from memory; I've already got
exactly what's needed right here in R0. Hey, look: I've just
``evaluated' ' b before testing cond, and in perfect safety!"

Generated code:

call f
store r0,a
call g
store r0,b
load r1,cond
jzero r1,label
load r0,a
label:
store r0,x


Possibly we are talking of different things. I am referring to it
accessing expression (2) when the condition is supposed to be triggering
(1).

Same code, different execution path. The compiler
has "evaluated" b before testing cond, even if the test
says that a's value is chosen instead.
>Possibly I overs implified it : there is no issue with HW if the
"result" of b=g() is used from a register. But clearly if expressions
(1) and (2) are of the form "*a" or "*b" then it would be madness for
the compiler to access *b if the condition is true. Or?

The compiler might not know whether *a,*b are or aren't
safe, but it might be able to tell that it makes no difference.

int *a = ...;
int *b = ...;
*a = 42; /* die here if *a unsafe */
*b = 56; /* die here if *b unsafe */
x = cond ? *a : *b;

The compiler might conclude that if *a,*b are unsafe the final
line won't be executed anyhow, hence a speculative fetch adds
no new failure mode to the program.

I don't know how commonly compilers "reason" this way, but
I've certainly seen compilers generate speculative fetches and
pre-fetches, sometimes far in advance of the use of the datum.
On modern machines there's a lot of incentive to do so, what
with memory being so much slower than CPUs.
true : and I guess the old "volatile" can protect any "dodgy" memory locations?
Aug 7 '06 #14


Richard wrote On 08/07/06 12:11,:
Eric Sosman <Er*********@su n.comwrites:
>[...]

I don't know how commonly compilers "reason" this way, but
I've certainly seen compilers generate speculative fetches and
pre-fetches, sometimes far in advance of the use of the datum.
On modern machines there's a lot of incentive to do so, what
with memory being so much slower than CPUs.


true : and I guess the old "volatile" can protect any "dodgy" memory locations?
That's the intent. `volatile' says (roughly) that the
access to the variable has side-effects. This prevents the
compiler from eliminating "unnecessar y" accesses; even if
the value is known, the side-effect of the access itself
may be required. Also, the access cannot be moved outside
its bracketing sequence points: containment of side-effects
is what sequence points are all about.

Unfortunately, there's a huge loophole: The implementation
gets to define what an "access" is, and the definition may or
may not match the programmer's intent. Most effective uses of
`volatile' thus require some intimacy with the implementation' s
documentation suite.

--
Er*********@sun .com

Aug 7 '06 #15

Eric Sosman wrote:

Unfortunately, there's a huge loophole: The implementation
gets to define what an "access" is, and the definition may or
may not match the programmer's intent. Most effective uses of
`volatile' thus require some intimacy with the implementation' s
documentation suite.

Yes, there can be very very touchy variables, where something that
seems innocuous, like just evaluating their address can cause
side-effects. For example on machines with many segment registers,
just loading up an address into an address register can cause "seg
fault"-like traps. Best example, the x86 in 16-bit protected mode.
Peeking at any segment value that hasnt been explicitly allocated to
your program will trap out. You're typically handed just 4 out of 8192
possible segments, so the odds arent good if the goods are odd.

So compilers, when in that code-generating mode, have to be very
conservative. No loading up of arbitrary addresses, no stuffing extra
info into the top bits of pointers.

Aug 7 '06 #16
Udo A. Steinberg wrote:
On Mon, 07 Aug 2006 14:43:47 +0100 Chris Dollin (CD) wrote:

CDUdo A. Steinberg wrote:
CD>
CD Or, in other words, is a compiler allowed to speculatively fetch a and b
CD from memory and then assign one of them to x based on the condition?
CD>
CDYes, if you can't tell the difference [with conforming C code]; this is the
CD"as if" rule. The standard specifies the semantics, and the implementation
CDcan do anything that provides the same result so long as its sneakiness
CDis invisible.

How well defined is "invisible sneakiness"?
Almost exactly, since it's fully defined by the language specification. Any
two pieces of behavior that have equal semantics according to the standard
are interchangeable , even if they are observably different. The key is that
"observatio n" happens on the concrete machine, while the standard only
defines semantics in terms of an abstract machine.
In my case "a" is only mapped in virtual memory if the condition is true.
Otherwise access to "a" causes a page fault. Here the compiler sneakiness
becomes visible to the user. However, if the compiler can always assume
that all memory is mapped, then the sneakiness is indeed invisible.
The compiler is allowed to do this, according to the standard, even if the
page fault involved releasing a carrier pigeon that flies to Mount
Kilimanjaro to retrieve the information you requested -- the standard does
not say how memory retrieval is implemented, in particular not what its
performance characteristics are. Of course, implementations are expected to
be "reasonable " to give the poor programmer a fighting chance.

The sort of guarantees you're looking for require intimate knowledge of the
platform(s) you're compiling on (which includes the compiler). Aside from
"volatile", you have little to no way to reliably influence the compiler's
behavior with regards to memory access, and even "volatile" has its fuzzy areas.

You can try to make prefetching the values as difficult or unattractive as
possible, you can try disabling optimization for this particular piece of
code, you can try compiler-specific extensions, or you could write the parts
you don't want the compiler to ever optimize in assembler. All of these
approaches require an amount of nonportable code, but since you're
specifically dealing with virtual memory that you have some sort of
interface to, this shouldn't be a big problem. Just make sure you document
clearly what you're trying to achieve in each instance, so your code won't
mysteriously break when the platform changes and human beings won't undo
your carefully crafted compiler conning.

S.
Aug 7 '06 #17
Skarmander <in*****@dontma ilme.comwrites:
>
You can try to make prefetching the values as difficult or
unattractive as possible, you can try disabling optimization for this
particular piece of code, you can try compiler-specific extensions, or
you could write the parts you don't want the compiler to ever optimize
in assembler. All of these approaches require an amount of nonportable
code, but since you're specifically dealing with virtual memory that
you have some sort of interface to, this shouldn't be a big
problem. Just make sure you document clearly what you're trying to
achieve in each instance, so your code won't mysteriously break when
the platform changes and human beings won't undo your carefully
crafted compiler conning.

S.
Surely its as simple as just replacing variables with function calls to
retrieve them? get() calls if you will.

There is no way the compiler will generate a call to the function
outside of the condition being matched.

Or? ...
Aug 7 '06 #18
Richard wrote:
Skarmander <in*****@dontma ilme.comwrites:
>You can try to make prefetching the values as difficult or
unattractive as possible, you can try disabling optimization for this
particular piece of code, you can try compiler-specific extensions, or
you could write the parts you don't want the compiler to ever optimize
in assembler. All of these approaches require an amount of nonportable
code, but since you're specifically dealing with virtual memory that
you have some sort of interface to, this shouldn't be a big
problem. Just make sure you document clearly what you're trying to
achieve in each instance, so your code won't mysteriously break when
the platform changes and human beings won't undo your carefully
crafted compiler conning.

Surely its as simple as just replacing variables with function calls to
retrieve them? get() calls if you will.

There is no way the compiler will generate a call to the function
outside of the condition being matched.
Provided that the compiler does not (partially) inline the functions and the
functions produce an observable side effect, and assuming of course that
we're not running on a DS9K.

Tricking a compiler can be arbitrarily complicated, depending on how smart
the compiler is. There is no language construct that will guarantee that no
virtual memory access will be generated to an object; a compiler would in
principle be free to do this "whenever it felt like it", provided it could
guarantee this would not cause the program to abort or invoke other
nonconforming behavior. If the only penalty is speed, though, there are no
standards-imposed limits to what the compiler can or can't do, just
considerations of reasonability and (conservative) practicality.

S.
Aug 7 '06 #19
>Richard wrote On 08/07/06 11:05,:
>Possibly I overs implified it : there is no issue with HW if the
"result" of b=g() is used from a register. But clearly if expressions
(1) and (2) are of the form "*a" or "*b" then it would be madness for
the compiler to access *b if the condition is true. Or?
Or, more specifically, suppose we have:

int f(int x, int *ap, int *bp) {
return x ? *ap : *bp;
}

(which is of course just the conditional operator itself, written in
function form, with type restricted to "int" and pointers for the
values involved).

In article <1154965455.873 251@news1nwk>
Eric Sosman <Er*********@su n.comwrote:
The compiler might not know whether *a,*b are or aren't
safe, but it might be able to tell that it makes no difference.

int *a = ...;
int *b = ...;
*a = 42; /* die here if *a unsafe */
*b = 56; /* die here if *b unsafe */
x = cond ? *a : *b;

The compiler might conclude that if *a,*b are unsafe the final
line won't be executed anyhow, hence a speculative fetch adds
no new failure mode to the program.
Or, the machine may have a "load from memory, but if there is a
fault during loading, ignore it" instruction -- often actually
spelled "prefetch" and having no target register -- in which case,
it can generate:

f_: .global f_
# inputs: r1 = x, r2 = ap, r3 = bp
pref (r2) # prefetch from *ap
pref (r3) # prefetch from *bp
tst r1 # which one should we use?
bz L1
ld r0,(r2) # x != 0, so fetch from *ap
ret
L1:
ld r0,(r3) # fetch from *bp
ret

The two "extra" instructions start RAM -cache transfers, which
typically take dozens of CPU cycles, if needed. Meanwhile the CPU
can still execute instructions. This means that the during the
delay caused by testing r1 (i.e., x), something useful is still
going on.

(These "prefetch" instructions would be more useful if they were
placed further back in the instruction stream, which is of course
only possible if the routine f() is expanded in line.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Aug 7 '06 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
3836
by: praba kar | last post by:
Dear All, I am new to Python. I want to know how to work with ternary operator in Python. I cannot find any ternary operator in Python. So Kindly clear my doubt regarding this __________________________________ Yahoo! Messenger
6
2768
by: glongword | last post by:
As the assert macro should evaluate to a void expression, it should not have an 'if statement' in its definition. Does this necessitate the existence of a ternary conditional operator? Is there a way assert.h can be implemented without using it? Are these decisions related in anyway?
6
2990
by: Robert Zurer | last post by:
In his paper on Coding Standard found on http://www.idesign.net/idesign/DesktopDefault.aspx Juval Lowy discourages the use of the ternary conditional operator with no specific reason given. I can understand that complicated code would be much less readable using nested operators, but aside from that is there another reason? -- something going on under the hood perhaps which make it inadvisable to use?
48
2768
by: Daniel Crespo | last post by:
Hi! I would like to know how can I do the PHP ternary operator/statement (... ? ... : ...) in Python... I want to something like: a = {'Huge': (quantity>90) ? True : False} Any suggestions?
15
12727
by: Arthur Dent | last post by:
Hi all, im just curious if anyone knows..... With .NET 2, VB didnt happen to get a true ternary operator, did it? Stuck away in a corner somewhere? By ternary, i mean something like C's a?b:c syntax. IIf works in most cases, but in some instances you want to use expressions which may fail if they are evaluated when they arent supposed to be, and it would be nice to have a concise way of writing this instead of using a whole If-Then-Else...
5
3570
by: PerlPhi | last post by:
hi,,, while ago i was wondering why do some programmers rarely uses the ternary operator. wherein it is less typing indeed. i believe in the classic virtue of Perl which is laziness. well let me show you something first before i go to my delimma. codes as follows using Mrs. If Else: #!perl/bin/perl use strict; print "Are you sure you want to quit ('yes' or any key for 'no'): "; chomp($_ = <STDIN>);
4
2390
by: raiderdav | last post by:
I understand how the ternary operator (question mark - ?) works in an if/else setting, but what does it mean when used as a type? For instance, I'm trying to add a get/set in some existing code, but the return type doesn't match: Rectangle? m_textArea = null; public Rectangle TextArea { set { m_textArea = value; } get { return m_textArea; }
9
2953
by: lawpoop | last post by:
I'm trying to write some simple code, but I might be simplifying it too much. I have a function that either returns a string that I want, or FALSE. In the code that I'm working on, I would like to default to another string if the function returns false. Here's the long way to do it: $string = myFunction(2);
0
9721
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9600
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10633
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10375
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
1
7651
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6880
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5686
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4331
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
3011
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.