Topic: Optimizing function return values


Author: andrewfg@dai.ed.ac.uk (Andrew Fitzgibbon)
Date: 1995/06/15
Raw View
Fergus Henderson (fjh@munta.cs.mu.OZ.AU) wrote:
< kanze@gabi-soft.fr (J. Kanze) writes:

< >See
< >section 12.2 for a discussion of temporaries.  (In the case in question,
< >the implementation has a right to elide the temporary, and of course, as
< >a result, whether the constructor/destructor is called or not is not
< >defined.)

< The question is not whether or not a destructor is called for unnamed
< temporaries.  The question is whether the destructor for a named
< local variable must be executed on exit from its scope, or whether that
< destruction can be delayed until after other side effects.
< I think the answer according to the current draft is no.

Could we not define the concept of an object "move" in addition to an
object copy?  A "move" is a "copy-of-X" followed by "destruction-of-X", and
would allow eliding.

Defining "copy-of-X" is a bit tricky, but one attempt might be "is the sole
argument of an (assignment operator or copy constructor) of another
object".

A function return example is
   X f()
   {
      X a;
      return a; // Expands to "X tmp = a; ~a();", elidation allowed for move
   }

This might also allow elidation in some other potentially useful cases, and
includes the current elidation rules as a subset, implied by the lifetime
rules.

Just a thought....

A.

--
Andrew Fitzgibbon (Research Associate),                     andrewfg@ed.ac.uk
Artificial Intelligence, Edinburgh University.               +44 031 650 4504
<a href=http://www.dai.ed.ac.uk/staff/personal_pages/andrewfg> Home Page </a>
                         "Never say there is no way" -- me.





Author: steve@spokane.ia-us.com (Stephen Williams)
Date: 1995/06/07
Raw View
In article <JASON.95Jun3234057@phydeaux.cygnus.com> jason@cygnus.com (Jason Merrill) writes:


   >>>>> eddy Gorsuch <eddy@clipper.robadome.com> writes:

   > In article <JASON.95Jun2190800@phydeaux.cygnus.com>,
   > Jason Merrill <jason@cygnus.com> wrote:
   > [...]
   >>> |>    Matrix operator+(const Matrix& a1, const Matrix& a2)
   >>> |>    {
   >>> |>      Matrix sum;
   >>> |>      ...
   >>> |>      return sum;
   >>> |>    }
   > [...]


   > Hmmm, then what is the proper way for me to write code where my compiler is
   > allowed to optimize away an extra copy for a function return value? From
   > your description, it is only possible to optimize away when the object is
   > created on the return statement (but I sometimes need to do more complex
   > operations on an object before returning it).

   There appears to be no portable way.  In g++, you can use named return
   values:

   Matrix operator+(const Matrix& a1, const Matrix& a2) return sum
   {
     ...;
   }

   Jason


How 'bout:

Matrix operator+(const Matrix& a1, const Matrix& a2)
{
  ...;
  return Matrix(stuff);
}

(Of course, this presumes the presence of helpful constructors.) Would
this not be an unnamed return value, with all the advantages of the
g++ named return value?

--

Stephen 2. Williams
steve@icarus.com

    Fight License Managers! Buy from
    vendors who use honor system!





Author: jason@cygnus.com (Jason Merrill)
Date: 1995/06/07
Raw View
>>>>> Stephen Williams <steve@spokane.ia-us.com> writes:

> How 'bout:

> Matrix operator+(const Matrix& a1, const Matrix& a2)
> {
>   ...;
>   return Matrix(stuff);
> }

> (Of course, this presumes the presence of helpful constructors.) Would
> this not be an unnamed return value, with all the advantages of the
> g++ named return value?

All but one -- the ability to refer to the Matrix object which will be
returned during the '...'.  This is important; how else are you going to
write operator+ for a Matrix?

Jason






Author: doug@monet.ads.com (Doug Morgan)
Date: 1995/06/08
Raw View
In article <JASON.95Jun7161824@phydeaux.cygnus.com> jason@cygnus.com (Jason Merrill) writes:
> >>>>> Stephen Williams <steve@spokane.ia-us.com> writes:
>
> > How 'bout:
>
> > Matrix operator+(const Matrix& a1, const Matrix& a2)
> > {
> >   ...;
> >   return Matrix(stuff);
> > }
>
> > (Of course, this presumes the presence of helpful constructors.) Would
> > this not be an unnamed return value, with all the advantages of the
> > g++ named return value?
>
> All but one -- the ability to refer to the Matrix object which will be
> returned during the '...'.  This is important; how else are you going to
> write operator+ for a Matrix?

You could do it just like the AT&T class library used to (still does?)
do it.  Make a special Matrix addition constructor.  So the "stuff"
inside of

   return Matrix(stuff);

expands like so:

   return Matrix(a1, a2, (OperatorPlusDummyClass *)0);

Then do all programming inside the constructor with "this" instead of
a variable like "sum".

Doug
----------
Doug Morgan, doug@ads.com
Booz-Allen & Hamilton
1500 Plymouth St.
Mountain View, CA 94043-1230
     (415) 960-7444
FAX: (415) 960-7500
----------





Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/06/03
Raw View
kanze@gabi-soft.fr (J. Kanze) writes:

>Doug Morgan (doug@monet.ads.com) wrote:
>|> smeyers@netcom.com (Scott Meyers) writes:
>
>|> [example from ARM of stack/copying optimization for Matrix, plus discussion]
>
>|> > If the Matrix destructor has as one of its side effects the printing of
>|> > a message, that message should be printed when sum is destroyed, which
>|> > would make it appear before "End of addition." If the optimization
>|> > described in the ARM is applied, however, sum's destructor will never be
>|> > called, because sum was optimized away in favor of result.  In that
>|> > case, the message will only appear when result is destroyed, and the
>|> > message will appear after "End of addition." I don't believe this is
>|> > supposed to be a valid change of semantics.

I agree with your analysis.  I'm not sure what Stroustrup intended, but
I don't think the optimization is legal according to the current draft.
Mind you, the current draft is extremely vague in the area of temporaries,
and in places is contradictory (12.2/6 is wrong, it contradicts 12.2/3-4),
so I expect (well... at least I hope) that it will undergo significant
rewording.

>|> WP Section 3.7.2 paragraph 3:
>
>|> If a named automatic object has initialization or a destructor with
>|> side effects, it shall not be destroyed before the end of its block,
>|> nor shall it be eliminated as an optimization even if it appears to be
>|> unused.
>
>The temporary in the initial example was *not* a *named* object.

Nevertheless, the current draft specifies that the local variable
is destroyed on exit from the function.  3.7.2/3 doesn't say that
the variable shall not be destroyed _after_ the end of its block,
but that is already specified in 12.4/9.

>See
>section 12.2 for a discussion of temporaries.  (In the case in question,
>the implementation has a right to elide the temporary, and of course, as
>a result, whether the constructor/destructor is called or not is not
>defined.)

The question is not whether or not a destructor is called for unnamed
temporaries.  The question is whether the destructor for a named
local variable must be executed on exit from its scope, or whether that
destruction can be delayed until after other side effects.
I think the answer according to the current draft is no.

--
Fergus Henderson
fjh@cs.mu.oz.au
http://www.cs.mu.oz.au/~fjh





Author: jason@cygnus.com (Jason Merrill)
Date: 1995/06/03
Raw View
>>>>> Stan Friesen <swf@elsegundoca.ncr.com> writes:

> In article <DOUG.95May26103523@monet.ads.com>, doug@monet.ads.com (Doug Morgan) writes:
> |> In article <3q4l8m$202@gabi.gabi-soft.fr> kanze@gabi-soft.fr (J. Kanze) writes:
> |> |> |> WP Section 3.7.2 paragraph 3:
> |> |>
> |> |> |> If a named automatic object has initialization or a destructor with
> |> |> |> side effects, it shall not be destroyed before the end of its block,
> |> |> |> nor shall it be eliminated as an optimization even if it appears to be
> |> |> |> unused.
> |> |>
> |> |> The temporary in the initial example was *not* a *named* object.  ...
> |>
> |> Here is the example brought back from Meyers' original message (and
> |> from pg 301 of the ARM):
> |>
> |>    Matrix operator+(const Matrix& a1, const Matrix& a2)
> |>    {
> |>      Matrix sum;
> |>      ...
> |>      return sum;
> |>    }
> |>
> |> Are you saying that the object associated with sum is "*not* a *named*
> |> object"?  ...

> However, the object generated by the *return*, IS am unnamed temporary.
> And you can interpret the optimization as having deleted *that* object
> by simply returning the 'sum' object.  Then the 'sum' object is not
> destroyed *before* the end of its block, since it is destroyed in the
> *calling* context, after it is out of scope.

However, this passage also applies:

  6.7  Declaration statement                                  [stmt.dcl]

2 Variables  with automatic storage duration (_basic.stc.auto_) are ini-
  tialized each time their declaration-statement is executed.  Variables
  with automatic storage duration declared in the block are destroyed on
  exit from the block (_stmt.jump_).

The optimization causes 'sum' to not be destroyed on exit from the
containing block, which is invalid.

Jason





Author: jason@cygnus.com (Jason Merrill)
Date: 1995/06/04
Raw View
>>>>> eddy Gorsuch <eddy@clipper.robadome.com> writes:

> In article <JASON.95Jun2190800@phydeaux.cygnus.com>,
> Jason Merrill <jason@cygnus.com> wrote:
> [...]
>>> |>    Matrix operator+(const Matrix& a1, const Matrix& a2)
>>> |>    {
>>> |>      Matrix sum;
>>> |>      ...
>>> |>      return sum;
>>> |>    }
> [...]

>> 6.7  Declaration statement                                  [stmt.dcl]
>>
>> 2 Variables  with automatic storage duration (_basic.stc.auto_) are ini-
>> tialized each time their declaration-statement is executed.  Variables
>> with automatic storage duration declared in the block are destroyed on
>> exit from the block (_stmt.jump_).
>>
>> The optimization causes 'sum' to not be destroyed on exit from the
>> containing block, which is invalid.

> Hmmm, then what is the proper way for me to write code where my compiler is
> allowed to optimize away an extra copy for a function return value? From
> your description, it is only possible to optimize away when the object is
> created on the return statement (but I sometimes need to do more complex
> operations on an object before returning it).

There appears to be no portable way.  In g++, you can use named return
values:

Matrix operator+(const Matrix& a1, const Matrix& a2) return sum
{
  ...;
}

Jason





Author: swf@elsegundoca.ncr.com (Stan Friesen)
Date: 1995/06/01
Raw View
In article <DOUG.95May26103523@monet.ads.com>, doug@monet.ads.com (Doug Morgan) writes:
|> In article <3q4l8m$202@gabi.gabi-soft.fr> kanze@gabi-soft.fr (J. Kanze) writes:
|> |> |> WP Section 3.7.2 paragraph 3:
|> |>
|> |> |> If a named automatic object has initialization or a destructor with
|> |> |> side effects, it shall not be destroyed before the end of its block,
|> |> |> nor shall it be eliminated as an optimization even if it appears to be
|> |> |> unused.
|> |>
|> |> The temporary in the initial example was *not* a *named* object.  ...
|>
|> Here is the example brought back from Meyers' original message (and
|> from pg 301 of the ARM):
|>
|>    Matrix operator+(const Matrix& a1, const Matrix& a2)
|>    {
|>      Matrix sum;
|>      ...
|>      return sum;
|>    }
|>
|> Are you saying that the object associated with sum is "*not* a *named*
|> object"?  ...

However, the object generated by the *return*, IS am unnamed temporary.
And you can interpret the optimization as having deleted *that* object
by simply returning the 'sum' object.  Then the 'sum' object is not
destroyed *before* the end of its block, since it is destroyed in the
*calling* context, after it is out of scope.

Thus, the optimization is legal.

--
swf@elsegundoca.attgis.com  sarima@netcom.com

The peace of God be with you.





Author: eddy@clipper.robadome.com (eddy Gorsuch)
Date: 1995/06/02
Raw View
In article <JASON.95Jun2190800@phydeaux.cygnus.com>,
Jason Merrill <jason@cygnus.com> wrote:
[...]
>> |>    Matrix operator+(const Matrix& a1, const Matrix& a2)
>> |>    {
>> |>      Matrix sum;
>> |>      ...
>> |>      return sum;
>> |>    }
[...]

>  6.7  Declaration statement                                  [stmt.dcl]
>
>2 Variables  with automatic storage duration (_basic.stc.auto_) are ini-
>  tialized each time their declaration-statement is executed.  Variables
>  with automatic storage duration declared in the block are destroyed on
>  exit from the block (_stmt.jump_).
>
>The optimization causes 'sum' to not be destroyed on exit from the
>containing block, which is invalid.


Hmmm, then what is the proper way for me to write code where my compiler is
allowed to optimize away an extra copy for a function return value? From
your description, it is only possible to optimize away when the object is
created on the return statement (but I sometimes need to do more complex
operations on an object before returning it).

eddy


--
ed.dy \'ed-e-\ n [ME (Sc dial.) ydy, prob. fr. ON itha; akin to OHG ith-
   again], L et and 1a: a current of water or air running contrary to the main
   current; esp)X : a small whirlpool 1b: a substance moving similarly  2: a
   contrary or circular current  - eddy vb





Author: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
Date: 1995/05/30
Raw View
In article <3q6qo1$b27@punchdown.zocalo.com> Kalyan Kolachala
<kal@chromatic.com> writes:

|> If there are no bugs in the compilers then there shouldn't
|> be any difference in functionality between optimized and
|> non-optimized code. But as the level of optimization increases
|> the possibility of errors increases for non-trivial code.

If there are no errors in the compiler *and* there are no errors in
your code, there shouldn't be any difference in functionality between
optimized and unoptimized code.

If your code contains undefined or unspecified behavior (modifying an
object twice between sequence points, or a dependency on order of
evaluation, for example), it is quite possible that the behavior be
different with and without optimization, even in the absense of a
compiler error.
--
James Kanze         Tel.: (+33) 88 14 49 00        email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
                              -- Beratung in industrieller Datenverarbeitung







Author: smeyers@netcom.com (Scott Meyers)
Date: 1995/05/25
Raw View
Concerning optimization of function return values, this example occurs
in section 12.1.1c of the ARM:

  Matrix operator+(const Matrix& a1, const Matrix& a2)
  {
    Matrix sum;
    ...
    return sum;
  }

Notes the ARM:

  A smarter implementation will note that the local variable sum is
  redundant and eliminate it by using the object pointed to by result
  instead.  In other words, the generated code will look something like
  this:

  void matrix_add(Matrix *__result, Matrix *arg1, Matrix *arg2)
  {
    // construct *__result;  add a1 and a2 and place result in *__result
    return;
  }

I don't think this is quite what is meant, at least I hope it's not.
Suppose the translation unit containing the definition of operator+
above has access to only the DECLARATION of the Matrix constructor and
destructor:

  class Matrix {
  public:
    Matrix();
    ~Matrix();
    ...
  };

When generating code for operator+, then, compilers have no idea of
what's happening inside these functions.  As I understand it, compilers
are required to preserve side effects of ctor/dtor calls for named
objects such as sum, so would the transformation described in the ARM be
legitimate?  In particular, consider:

  Matrix result = a + b;
  cout << "End of addition";

If the Matrix destructor has as one of its side effects the printing of
a message, that message should be printed when sum is destroyed, which
would make it appear before "End of addition." If the optimization
described in the ARM is applied, however, sum's destructor will never be
called, because sum was optimized away in favor of result.  In that
case, the message will only appear when result is destroyed, and the
message will appear after "End of addition." I don't believe this is
supposed to be a valid change of semantics.  Is it?  My belief is that
the transformation in the ARM is valid only when compilers can determine
that the ctor/dtor being eliminated are free of "side effects," though
I'm not sure what the definition of a "side effect" would be.

Comments on this?  Pointers to relevant WP sections appreciated.

Thanks,

Scott





Author: rac@intrigue.com (Robert Coie)
Date: 1995/05/25
Raw View
In article <smeyersD9565G.627@netcom.com>, smeyers@netcom.com (Scott
Meyers) wrote:

[dangerous? optimization from ARM]

: My belief is that
: the transformation in the ARM is valid only when compilers can determine
: that the ctor/dtor being eliminated are free of "side effects," though
: I'm not sure what the definition of a "side effect" would be.
:
: Comments on this?  Pointers to relevant WP sections appreciated.

The closest wording I found to your concept of "free of side effects" for
ctor/dtors was "trivial constructors" and "trivial destructors", defined
in 12.1 and 12.4.  12.2 verse 3 insures that constructors and destructors
must be called for compiler-generated temporaries of type with non-trivial
constructors or destructors.  Since no explicitly defined constructor or
destructor can be trivial, I think the draft agrees with you.  Now if only
someone could show that named objects have at least the same degree of
protection from overzealous optimizers as that afforded to
compiler-generated temporaries :)

Robert Coie                              rac@intrigue.com
Implementor, Intrigue Corporation     AppleLink: INTRIGUE





Author: doug@monet.ads.com (Doug Morgan)
Date: 1995/05/25
Raw View
In article <smeyersD9565G.627@netcom.com> smeyers@netcom.com (Scott Meyers) writes:

[example from ARM of stack/copying optimization for Matrix, plus discussion]

> If the Matrix destructor has as one of its side effects the printing of
> a message, that message should be printed when sum is destroyed, which
> would make it appear before "End of addition." If the optimization
> described in the ARM is applied, however, sum's destructor will never be
> called, because sum was optimized away in favor of result.  In that
> case, the message will only appear when result is destroyed, and the
> message will appear after "End of addition." I don't believe this is
> supposed to be a valid change of semantics.  Is it?  My belief is that
> the transformation in the ARM is valid only when compilers can determine
> that the ctor/dtor being eliminated are free of "side effects," though
> I'm not sure what the definition of a "side effect" would be.
>
> Comments on this?  Pointers to relevant WP sections appreciated.

WP Section 3.7.2 paragraph 3:

If a named automatic object has initialization or a destructor with
side effects, it shall not be destroyed before the end of its block,
nor shall it be eliminated as an optimization even if it appears to be
unused.

WP Section 1.8 paragraph 7 contains:

Accessing an object designated by a volatile lvalue, modifying an
object, modifying a file, or calling a function that does any of those
operations are all side effects....

So, looks like you are correct.  (Assuming that the WP
definition/discussion of side effects is either not exhaustive or that
your "printing a message" sort of falls under the WP's heading of
"modifying a file."  And assuming that you are allowed to do the
necessary things that the WP doesn't explicitly forbid.)

Doug
----------
Doug Morgan, doug@ads.com
Booz-Allen & Hamilton
1500 Plymouth St.
Mountain View, CA 94043-1230
     (415) 960-7444
FAX: (415) 960-7500
----------





Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1995/05/26
Raw View
Doug Morgan (doug@monet.ads.com) wrote:
|> In article <smeyersD9565G.627@netcom.com> smeyers@netcom.com (Scott Meyers) writes:

|> [example from ARM of stack/copying optimization for Matrix, plus discussion]

|> > If the Matrix destructor has as one of its side effects the printing of
|> > a message, that message should be printed when sum is destroyed, which
|> > would make it appear before "End of addition." If the optimization
|> > described in the ARM is applied, however, sum's destructor will never be
|> > called, because sum was optimized away in favor of result.  In that
|> > case, the message will only appear when result is destroyed, and the
|> > message will appear after "End of addition." I don't believe this is
|> > supposed to be a valid change of semantics.  Is it?  My belief is that
|> > the transformation in the ARM is valid only when compilers can determine
|> > that the ctor/dtor being eliminated are free of "side effects," though
|> > I'm not sure what the definition of a "side effect" would be.
|> >
|> > Comments on this?  Pointers to relevant WP sections appreciated.

|> WP Section 3.7.2 paragraph 3:

|> If a named automatic object has initialization or a destructor with
|> side effects, it shall not be destroyed before the end of its block,
|> nor shall it be eliminated as an optimization even if it appears to be
|> unused.

The temporary in the initial example was *not* a *named* object.  See
section 12.2 for a discussion of temporaries.  (In the case in question,
the implementation has a right to elide the temporary, and of course, as
a result, whether the constructor/destructor is called or not is not
defined.)
--
James Kanze           (+33) 88 14 49 00          email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils en informatique industrielle--
                             --Beratung in industrieller Datenverarbeitung





Author: doug@monet.ads.com (Doug Morgan)
Date: 1995/05/26
Raw View
In article <3q4l8m$202@gabi.gabi-soft.fr> kanze@gabi-soft.fr (J. Kanze) writes:
|> Doug Morgan (doug@monet.ads.com) wrote:
|> |> In article <smeyersD9565G.627@netcom.com> smeyers@netcom.com (Scott Meyers) writes:
|>
|> |> [example from ARM of stack/copying optimization for Matrix, plus discussion]
|>
|> |> > If the Matrix destructor has as one of its side effects the printing of
|> |> > a message, that message should be printed when sum is destroyed, which
|> |> > would make it appear before "End of addition." If the optimization
|> |> > described in the ARM is applied, however, sum's destructor will never be
|> |> > called, because sum was optimized away in favor of result.  In that
|> |> > case, the message will only appear when result is destroyed, and the
|> |> > message will appear after "End of addition." I don't believe this is
|> |> > supposed to be a valid change of semantics.  Is it?  My belief is that
|> |> > the transformation in the ARM is valid only when compilers can determine
|> |> > that the ctor/dtor being eliminated are free of "side effects," though
|> |> > I'm not sure what the definition of a "side effect" would be.
|> |> >
|> |> > Comments on this?  Pointers to relevant WP sections appreciated.
|>
|> |> WP Section 3.7.2 paragraph 3:
|>
|> |> If a named automatic object has initialization or a destructor with
|> |> side effects, it shall not be destroyed before the end of its block,
|> |> nor shall it be eliminated as an optimization even if it appears to be
|> |> unused.
|>
|> The temporary in the initial example was *not* a *named* object.  See
|> section 12.2 for a discussion of temporaries.  (In the case in question,
|> the implementation has a right to elide the temporary, and of course, as
|> a result, whether the constructor/destructor is called or not is not
|> defined.)

Here is the example brought back from Meyers' original message (and
from pg 301 of the ARM):

   Matrix operator+(const Matrix& a1, const Matrix& a2)
   {
     Matrix sum;
     ...
     return sum;
   }

Are you saying that the object associated with sum is "*not* a *named*
object"?  I thought a named object was an object that had been
associated with an identifer by a declaration.  The object referred to
by sum seems to me to fit that bill.  Where is the misunderstanding:
does "named object" actually mean something different than what I
thought, are we not talking about the same example (could you have
been looking at the later example on page 302 with complex numbers and
no named object) (also my version of the ARM looks to be first
printing), or what?

Doug
----------
Doug Morgan, doug@ads.com
Booz-Allen & Hamilton
1500 Plymouth St.
Mountain View, CA 94043-1230
     (415) 960-7444
FAX: (415) 960-7500
----------





Author: leblanck@austin.ibm.com (Karalee LeBlanc)
Date: 1995/05/26
Raw View
Mr. Meyers,
  Your note brought up a question I've always wanted to ask. Debugging
optimized code (when the problem occurs solely because the code was
optimized) is usually difficult and usually requires good guesswork.
  Is there a good source of information on the types of problems that
only occur when you optimize the code?  You had that one chapter in your
book concerning inlines, but I'm thinking more of a list of all the
possible problems that could occur when optimization is turned on.
Or is such a list impossible, since optimizing doesn't appear to be
part of the standard, meaning different compilers optimize differently.
--
-----------------------------------------------------
Karalee LeBlanc
Dept 908, Bld 008, Room 7D050
Austin, Tx.  Tie/Phone 678/838-3409





Author: Kalyan Kolachala <kal@chromatic.com>
Date: 1995/05/27
Raw View
leblanck@austin.ibm.com (Karalee LeBlanc) wrote:
>
>Mr. Meyers,
>  Your note brought up a question I've always wanted to ask.
Debugging
>optimized code (when the problem occurs solely because the
code was
>optimized) is usually difficult and usually requires good
guesswork.

With debugging on, optimizations are generally disabled.
I remember one such instance (with BC 4.5) when my code was
crashing normally but when debugging there was no problem at
all. It turned out to be a bug in BC 4.5 wrt inlining.
In the debug mode this optimization is turned off and all
is well.

If there are no bugs in the compilers then there shouldn't
be any difference in functionality between optimized and
non-optimized code. But as the level of optimization increases
the possibility of errors increases for non-trivial code.

In C++ most of the bugs have to do with side-effects.
At times compilers optimize even in the prescence of
side-effects. eg. performing CSE when the overloaded
operator has a side effect etc.

Hope this helps.

- Kalyan

>  Is there a good source of information on the types of
problems that
>only occur when you optimize the code?  You had that one
chapter in your
>book concerning inlines, but I'm thinking more of a list of
all the
>possible problems that could occur when optimization is turned
on.
>Or is such a list impossible, since optimizing doesn't appear
to be
>part of the standard, meaning different compilers optimize
differently.
>--
>-----------------------------------------------------
>Karalee LeBlanc
>Dept 908, Bld 008, Room 7D050
>Austin, Tx.  Tie/Phone 678/838-3409