Parentheses and compiler optimzation

S

spasmous

If a compiler see's the following statement

c = (a+b)-b

will it optimize it to c=a? I want to force the compiler to evaluate (a
+b) first. Do the parentheses ensure an ANSI conforming compiler HAS
to do that? If not, is there a way?
 
W

Willem

spasmous wrote:
) If a compiler see's the following statement
)
) c = (a+b)-b
)
) will it optimize it to c=a?

It could, yes.

) I want to force the compiler to evaluate (a+b) first.

Why would you want to do that ?

) Do the parentheses ensure an ANSI conforming compiler HAS to do that?

No, I don't think so. The as-if rule and such, you know.

) If not, is there a way?

That depends. What *exactly* do you want to do ?
The result will be the same no matter if the (a+b) is evaluated or not.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
W

Walter Roberson

spasmous wrote:
) If a compiler see's the following statement
) c = (a+b)-b
) will it optimize it to c=a?
That depends. What *exactly* do you want to do ?
The result will be the same no matter if the (a+b) is evaluated or not.

Think floating point. If a has a much smaller magnitude than b,
then a+b would evaluate to b; b - b would then evaluate to 0, not a.
Thus for floating point, optimizing (a+b)-b to simply a would give
the "wrong" answer relative to floating point characteristics.
 
K

Keith Thompson

spasmous said:
If a compiler see's the following statement

c = (a+b)-b

will it optimize it to c=a?

It's likely to to so, though there's no requirement to perform such an
optimization.

What types are a, b, and c? It might make a difference.

I want to force the compiler to evaluate (a
+b) first.

Why? What problem are you really trying to solve? Ordinarily,
replacing (a+b)-b by a will give you the same result.
Do the parentheses ensure an ANSI conforming compiler HAS
to do that?

No, parentheses merely specify which operands are associated with
which operators; they don't force any order of evaluation.
If not, is there a way?

One obvious way is:

tmp = a + b;
c = tmp - b;

but the compiler is still free to optimize it down to "c = a;".

Judicious use of "volatile" might be a solution -- but again, without
knowing the underlying problem, I hesitate to make suggestions.
 
K

Kenneth Brody

Morris said:
If a compiler see's the following statement

c = (a+b)-b

will it optimize it to c=a? I want to force the compiler to evaluate (a
+b) first. Do the parentheses ensure an ANSI conforming compiler HAS
to do that? If not, is there a way?

AFAICT, section 6.5[3] and footnote 71 assure that the
parenthesized expression (a+b) is evaluated first, then b is
subtracted from the result.

AFAIK, unless b is volatile, no such requirement exists, just as
there is no such requirement in

c = ( printf("one") + printf("two") ) - printf("three");

that the output be "onetwothree".

And, AFAIK, even if b is volatile, there is no requirement that the
one inside the parentheses is evaluated before the one outside.

You could do something like

c = a + b;
c = c - b;

but even then, a compiler could still optimize out the b's (unless
it's volatile).

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
R

Richard Tobin

spasmous said:
If a compiler see's the following statement

c = (a+b)-b

will it optimize it to c=a? I want to force the compiler to evaluate (a
+b) first. Do the parentheses ensure an ANSI conforming compiler HAS
to do that?

No.

I seem to recall there was some dispute about this during the original
C standardisation - you might be able to find it with Google.
If not, is there a way?

Assigning the intermediate result to a volatile variable should
ensure it.

But you need to tell us what you are really trying to achieve.

-- Richard
 
C

christian.bau

If a compiler see's the following statement

c = (a+b)-b

will it optimize it to c=a? I want to force the compiler to evaluate (a
+b) first. Do the parentheses ensure an ANSI conforming compiler HAS
to do that? If not, is there a way?

The compiler will add a and b, then subtract b. Whether you use
parentheses or not doesn't make any difference at all.

However, there is the "as if" rule: The compiler is allowed to do
_anything_ that is guaranteed to give exactly the same result. For
example, if a and b are both of type unsigned int then it is
guaranteed that (a + b) - b and a give the same result. On the other
hand, if there _is_ a difference between (a + b) - b and a, then the
compiler will _not_ produce a.
 
L

lawrence.jones

Morris Dovey said:
AFAICT, section 6.5[3] and footnote 71 assure that the
parenthesized expression (a+b) is evaluated first, then b is
subtracted from the result.

In the abstract machine, but the as-if rule allows the compiler to
optimize as long as it gets the same answer.

-Larry Jones

See if we can sell Mom and Dad into slavery for a star cruiser. -- Calvin
 
P

Peter Nilsson

Keith Thompson said:
It's likely to to so,

Maybe, maybe not.
though there's no requirement to
perform such an optimization.

There _is_ a requirement that no optimisation
should change the behaviour from the virtual
machine [if there is no unspecified or
undefined behaviour.]

Consider...

int a = -1;
unsigned b = 0;

The expression (a + b) - b has neither the
type nor value of a.

Even if a and b have the same type there can
be problems. See Walter's floating point
example.
 
W

Willem

Walter wrote:
) In article <[email protected]>,
)>spasmous wrote:
)>) If a compiler see's the following statement
)
)>) c = (a+b)-b
)
)>) will it optimize it to c=a?
)
)>That depends. What *exactly* do you want to do ?
)>The result will be the same no matter if the (a+b) is evaluated or not.
)
) Think floating point. If a has a much smaller magnitude than b,
) then a+b would evaluate to b; b - b would then evaluate to 0, not a.
) Thus for floating point, optimizing (a+b)-b to simply a would give
) the "wrong" answer relative to floating point characteristics.

Oh, sorry. I assumed integer.

If it's floating point, then no, the compiler is not allowed
to optimize it away.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
P

Peter Nilsson

Willem said:
Walter wrote:
) In article <[email protected]>,
)>spasmous wrote:
)>) If a compiler see's the following statement
)
)>) c = (a+b)-b
)
)>) will it optimize it to c=a?
)
)>That depends. What *exactly* do you want to do ?
)>The result will be the same no matter if the (a+b) is evaluated or not.
)
) Think floating point. If a has a much smaller magnitude than b,
) then a+b would evaluate to b; b - b would then evaluate to 0, not a.
) Thus for floating point, optimizing (a+b)-b to simply a would give
) the "wrong" answer relative to floating point characteristics.

Oh, sorry. I assumed integer.

The expression (-1 + 0u) - 0u has neither the type nor value of -1.
 
K

Kenneth Brody

Willem said:
Walter wrote:
) In article <[email protected]>,
)>spasmous wrote:
)>) If a compiler see's the following statement
)
)>) c = (a+b)-b
)
)>) will it optimize it to c=a?
)
)>That depends. What *exactly* do you want to do ?
)>The result will be the same no matter if the (a+b) is evaluated or not.
)
) Think floating point. If a has a much smaller magnitude than b,
) then a+b would evaluate to b; b - b would then evaluate to 0, not a.
) Thus for floating point, optimizing (a+b)-b to simply a would give
) the "wrong" answer relative to floating point characteristics.

Oh, sorry. I assumed integer.

If it's floating point, then no, the compiler is not allowed
to optimize it away.

I see that my compiler will optimize it away for int, but not for
float. Where would one find this prohibition in the standard?

Mathematically, "(a+b)-b" is the same as "a". Of course, in this
case, there may be a loss of precision, but does the standard say
that you must preserve loss of precision? Why doesn't the "as if"
rule apply to floating point?

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
W

Walter Roberson

Kenneth Brody said:
Mathematically, "(a+b)-b" is the same as "a". Of course, in this
case, there may be a loss of precision, but does the standard say
that you must preserve loss of precision? Why doesn't the "as if"
rule apply to floating point?

Your error is in your first line.

Mathematically, "(a+b)-b" means whatever you want it to mean.
You can -choose- to interpret it as a statement involving
variables and operators, but there is no -inherent- meaning
in using an operator named "+" or "-", so the operators can be
given any interpretation. In logic, an "operator" is a function
in the mathematical sense of "function", which is to say an arbitrary
mapping from input tuples to output tuples. The mapping described
by any particular "function" (and thus by any particular operator)
need not make any -sense- -- it just *is*. Some mappings are amenable
to being described more easily than just the exhaustive list of
input and output tuples, but it is an error to -assume- that
when you see operators "+" or "-" that those operators are definitely being
used in the sense of a function mapping that has any kind of sensible
or compact description.

For example, it would be perfectly valid to use a mathematic model
in which (a+b)-b was to be interpreted as NAND(XOR(a,b),b) -- which
would, incidently, interpret "(a+b)-b" as mapping to "true" if a is false.

Thus, when you read "(a+b)-b" in a C program, you should not be
automatically interpreting this as algebraic addition and subtraction.
Operations on signed integers need not obey standard algebraic rules
in C (because a+b might overflow in signed integers, and the result
of overflowing signed integers is not specified in C.) Operations on
floating point numbers usually do not obey standard algebraic rules in C.
Even with unsigned integers, do not expect standard algebraic rules:
(a/b)*b is not a unless b is non-zero and a is an exact integral
multiple of b.
 
C

christian.bau

I see that my compiler will optimize it away for int, but not for
float.  Where would one find this prohibition in the standard?

Mathematically, "(a+b)-b" is the same as "a".  Of course, in this
case, there may be a loss of precision, but does the standard say
that you must preserve loss of precision?  Why doesn't the "as if"
rule apply to floating point?

The C Standard says that (a + b) - b means: Add a and b, subtract b
from the result. Same for integer and floating point. The C Standard
also says that the compiler is allowed to do absolutely anything it
likes, but only as long as the result is exactly what the C Standard
says. So the C Standard doesn't have to say "it's allowed for integer
and not allowed for floating-point". Instead, it is up to the compiler
writer to _prove_ that they produce exactly the same result.

And: "Mathematically" doesn't count. Actually, when you say
"mathematically" you mean "real numbers". Since the C Standard uses
floating-point numbers and not real numbers, it is irrelevant how real
numbers work.

Now an example: How could the compiler optimise this?

double f (int x) { double a = (double) x; double b = 1e300; return
(a + b) - b; }

(And no, it can't replace the return statement with "return a;" but
with something very different!)
 
H

Harald van Dijk

Now an example: How could the compiler optimise this?

double f (int x) { double a = (double) x; double b = 1e300; return
(a + b) - b; }

(And no, it can't replace the return statement with "return a;" but with
something very different!)

Yes, it can replace the return statement with "return a;", unless you
specifically tell it it can't.

6.5p8
"A floating expression may be /contracted/, that is, evaluated as though
it were an atomic operation, thereby omitting rounding errors implied by
the source code and the expression evaluation method. The FP_CONTRACT
pragma in <math.h> provides a way to disallow contracted expressions.
Otherwise, whether and how expressions are contracted is implementation-
defined."
7.12.2p2
"[...] The default state ("on" or "off") for the pragma is
implementation-defined."
 
A

Anonymous

One obvious way is:

tmp = a + b;
c = tmp - b;

but the compiler is still free to optimize it down to "c = a;".

Chances are, as soon as the compiler finishes parsing the code and starts
the first stage of compiling, this is already the form it's been reduced
to. As far as optimizations go, this change is most likely a no-op unless
tmp is volatile.
Judicious use of "volatile" might be a solution -- but again, without
knowing the underlying problem, I hesitate to make suggestions.

Correct.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top