michi@ptcburp.ptcbu.oz.au (Michael Henning) (03/26/91)
In my copy of Harbison & Steele (1987) is a section about the unary plus
operator in ANSI-C.
It basically states that the unary plus operator may be used to force
a particular order of evaluation. H & S quote an example:
If x and y are floating point variables, the expressions
((x+y)-x)-y
and
(x+y)-(x+y)
do not necessarily give the same result (or zero, for that matter) because
the order of evaluation is undefined. The go on to say that to force
evaluation order as indicated by the brackets in the first expression,
one may write
+((+(x+y))-x)-y
In my copy of the ANSI-C standard (X3J11/90-013, Feb 14th, 1990), I could
not find any mention of this behaviour, so I assume that it was dropped from
the standard after H & S published the book. Is this correct ?
Which brings me to my next question...
If I want to enforce evaluation order by assigning to temporary variables, e.g.
tmp = x + y;
tmp -= x;
tmp -= y;
result = tmp;
is it necessary to declare tmp as volatile to prevent the optimizer from
optimizing tmp out of existence ? Or are there some rules that say that the
optimizer should not get rid of tmp in this case ?
Similar problems occur if union fields of different sizes and/or types
are to be assigned to each other. For example, given
union {
int i;
double d;
} u;
the behaviour of the assignment
u.i = (int) u.d;
is undefined, because the storage area for i and d overlap, and i and d have
different types. If I instead write
tmp = (int) u.d;
u.i = tmp;
is it necessary to declare tmp as volatile to tell the optimizer not to
get rid of it ?
Any help greatly appreciated,
Michi.
--
-m------- Michael Henning +61 75 950255
---mmm----- Pyramid Technology +61 75 522475 FAX
-----mmmmm--- Research Park, Bond University michi@ptcburp.ptcbu.oz.au
-------mmmmmmm- Gold Coast, Q 4229, AUSTRALIA uunet!munnari!ptcburp.oz!michi
henry@zoo.toronto.edu (Henry Spencer) (03/27/91)
In article <370@ptcburp.ptcbu.oz.au> michi@ptcburp.ptcbu.oz.au (Michael Henning) writes: >In my copy of Harbison & Steele (1987) is a section about the unary plus >operator in ANSI-C. >It basically states that the unary plus operator may be used to force >a particular order of evaluation... That was based on an obsolete ANSI draft. Unary plus no longer does any such thing. >If I want to enforce evaluation order by assigning to temporary variables... No longer necessary, actually. ANSI C says that order of evaluation is as written in the expression, unless the compiler can be sure that changing it will have no visible effect. > u.i = (int) u.d; Now, on this one you do have to go via a temporary. > tmp = (int) u.d; > u.i = tmp; > >is it necessary to declare tmp as volatile to tell the optimizer not to >get rid of it ? No need; you don't care whether the optimizer gets rid of it. You have satisfied the language rules, and the optimizer should not be making changes unless it knows it is safe. -- "[Some people] positively *wish* to | Henry Spencer @ U of Toronto Zoology believe ill of the modern world."-R.Peto| henry@zoo.toronto.edu utzoo!henry
keie@cs.vu.nl (Keizer E G) (03/27/91)
michi@ptcburp.ptcbu.oz.au (Michael Henning) writes: >In my copy of Harbison & Steele (1987) is a section about the unary plus >operator in ANSI-C. >It basically states that the unary plus operator may be used to force >a particular order of evaluation. H & S quote an example: >If x and y are floating point variables, the expressions > ((x+y)-x)-y >and > (x+y)-(x+y) >do not necessarily give the same result (or zero, for that matter) because >the order of evaluation is undefined. The go on to say that to force >evaluation order as indicated by the brackets in the first expression, >one may write > +((+(x+y))-x)-y >In my copy of the ANSI-C standard (X3J11/90-013, Feb 14th, 1990), I could >not find any mention of this behaviour, so I assume that it was dropped from >the standard after H & S published the book. Is this correct ? Yes. The `special' effect that a unary plus enforced evaluation order has disappeared. You have to make a difference between evaluation order and the re-ordering of the expression. The current Standard allows any evaluation order but restricts re-ordering with the as-if rule. To illustrate the point: ( x1 + y1 ) * ( x2 + y2 ) The Standard does not state in which order the additions "x1+y1" and "x2+y2" have to be done. The only way in which this could affect the result is when one of x1, x2, y1 and y2 produce side effects. The best way to see this is by viewing the expression as a tree. The compiler is allowed to compute the leaves and perform the operations in any order as long as the expression tree itself is not changed. That is you have to evaluate x1 and y1 before adding them, x2 and y2 before adding them and perform the multiplication only after the result from additions is known. To confuse the matter a bit I have to state that the compiler can actually use any which way to calculate the expression, as long as the result (including possible overflow) is a result that is possible under the rules stated above. The reason for this is that nobody could tell the difference (as long as they are not reading the code produced). For floating point expressions all this means that the programmer can assume the a conforming compiler will not fiddle with his expressions. >Which brings me to my next question... >If I want to enforce evaluation order by assigning to temporary variables, e.g. > tmp = x + y; > tmp -= x; > tmp -= y; > result = tmp; >is it necessary to declare tmp as volatile to prevent the optimizer from >optimizing tmp out of existence ? Or are there some rules that say that the >optimizer should not get rid of tmp in this case ? No, it is not necessary to declare tmp as volatile. In fact as stated above this way of calculating the result only makes sense if x or y produce side-effects. I refrain from giving an answer to your third question. Ed Keizer
bhoughto@hopi.intel.com (Blair P. Houghton) (03/27/91)
In article <370@ptcburp.ptcbu.oz.au> michi@ptcburp.ptcbu.oz.au (Michael Henning) writes: >If I want to enforce evaluation order by assigning to temporary variables, e.g. > > tmp = x + y; > tmp -= x; > tmp -= y; > result = tmp; > >is it necessary to declare tmp as volatile to prevent the optimizer from >optimizing tmp out of existence ? Or are there some rules that say that the >optimizer should not get rid of tmp in this case ? Yes. The result has to be the one expressed. The optimizer would be broken if it produced a result different from the one obtained with `tmp' intact. Optimization is moot, always, when the Standard is concerned. The only time things are undefined is when the Standard says they are undefined. If your optimizer produces code that operates otherwise, then your implementor is not telling you the truth about conforming to the Standard. --Blair "Moot." P.S. However, if it can guarantee, through correct order of evaluation, that this would give the same result: copy x to result; add y to result; subtract x from result; subtract y from result then it's free never to allocate storage for tmp. In fact, if it's capable of guaranteeing that the types you've selected for x, y, result, _and_ tmp mean that the result _is_ guaranteed to be zero (e.g., unsigned short x,y; signed long tmp,result; enough bits in long to hold short*short), then it may simply do result = 0; or even nothing, if it can further determine that result==0 produces no effect that just 0 couldn't produce. I.e., if you use the temporary variable, the answer has to be the one the syntax implies, not the one that possible optimizations might imply. Orders of evaluation are often undefined; so optimization is moot. It's the syntax which says you're not being explicit. I know this P.S. is longer than the body, but I like muddling around in the moot; you meet an interesting class of moot-monster in here...
gwyn@smoke.brl.mil (Doug Gwyn) (03/28/91)
In article <370@ptcburp.ptcbu.oz.au> michi@ptcburp.ptcbu.oz.au (Michael Henning) writes: >It basically states that the unary plus operator may be used to force >a particular order of evaluation. No, that was proposed in early drafts of the standard, but was dropped in favor of requiring "honoring of parentheses" (a la Fortran) instead. >If I want to enforce evaluation order by assigning to temporary variables, ... Don't do that, use parentheses instead. For finer-grained control you can use volatile, but that should not be used merely to control subexpression evaluation order.