Topic: Must we evaluate parameters?


Author: kanze@alex.gabi-soft.fr (James Kanze)
Date: Tue, 8 Apr 2003 08:35:00 +0000 (UTC)
Raw View
allan_w@my-dejanews.com (Allan W) writes:

|>  v.Abazarov@attAbi.com ("Victor Bazarov") wrote
|>  > > allan_w@my-dejanews.com (Allan W) wrote
|>  > > >     // Version C
|>  > > >     #include <iostream>
|>  > > >     extern int foo();
|>  > > >     inline int first(int a, int) { return a; }
|>  > > >     int main() { std::cout << first(2,foo()) << std::endl; }

|>  > > > Assume the program knows nothing about foo (it could be in a
|>  > > > third- party library). Must the program call it, even though
|>  > > > the result will not be used?

|>  > Yes.  Imagine the situation when the definition of 'first' is
|>  > not visible to the compiler.  There would be no way for it to
|>  > know that the second argument is unused in the function.  So,
|>  > the code is generated to evaluate all arguments and let the
|>  > function sort them out.  So, should the presence of the function
|>  > definition cause differently generated code?  I don't think so.

|>  I'm talking specifically about inline functions. Since 'first' is
|>  inline, the definition MUST be known at the call point, and the
|>  compiler MUST have enough information to see if the second
|>  argument is used.

And that is at any rate irrelevant.

|>  For the code above, I would expect the compiler to (in essence)
|>  replace
|>      cout << first(2,foo()) << endl;
|>  with
|>      cout << 2 << endl;
|>  But is it also forced to call foo() before the sequence point?
|>  Part of me wants it to -- after all, it's obvious by reading the
|>  source code that this function *is* called. But another part of me
|>  wants it to be legal to skip it -- after all, it's obviously not
|>  needed.

The semantics (or the observable behavior, if you prefer) of a program
are defined in terms of an abstract machine which doesn't optimise
anything.  After that, a compiler is allowed to optimize according to
the as-if rule (the optimization doesn't change any observable
behavior), and in a very few, explicitly specified other cases,
generally involving unnamed temporaries.  This isn't one of the other
cases, so the compiler can suppress the call to foo if and only if it
can verify that the observable behavior would be unchanged compared to
that of calling foo.

|>  > I presume you are asking here because you wanted to know the
|>  > rationale behind 5.2.2/4, not its contents (you can read its
|>  > contents in your own copy of the Standard already).

|>  Sort of. 5.2.2/4 isn't exactly vague, but I think there is "wiggle
|>  room" for interpretation. It starts with
|>      each parameter shall be initialized with its corresponding argume=
nt
|>  but then it goes on to
|>      an implementation may avoid the construction of extra temporaries
|>      by combining the conversions on the associated argument and/or th=
e
|>      construction of temporaries with the initialization of the parame=
ter.
|>  For that second point, how far can it go? Can it avoid the
|>  construction of ALL extra temporaries by noting that the parameter
|>  isn't used?

It can avoid the construction of all extra temporaries, but it must
construct any actually named variables, like the function parameters.

It can never avoid calling an explicitly invoked function.

|>  I'm not asking if any compiler currently does this... just asking
|>  if it would be legal.

It's not.

--=20
James Kanze                                  mailto:kanze@gabi-soft.fr
Conseils en informatique orient=E9e objet/
                      Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France  Tel. +33 1 41 89 80 93

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: loic.actarus.joly@wanadoo.fr (=?ISO-8859-1?Q?Lo=EFc_Joly?=)
Date: Tue, 8 Apr 2003 18:33:37 +0000 (UTC)
Raw View
James Kanze wrote:

> The semantics (or the observable behavior, if you prefer) of a program
> are defined in terms of an abstract machine which doesn't optimise
> anything.  After that, a compiler is allowed to optimize according to
> the as-if rule (the optimization doesn't change any observable
> behavior), and in a very few, explicitly specified other cases,
> generally involving unnamed temporaries.  This isn't one of the other
> cases, so the compiler can suppress the call to foo if and only if it
> can verify that the observable behavior would be unchanged compared to
> that of calling foo.

Do you have a definition of "observable behaviour" ?

I read in the standard draft :
> The observable behavior of the abstract machine  is  its  sequence  of
>   reads   and   writes  to  volatile  data  and  calls  to  library  I/=
O
>   functions.


If the program runs 10 time faster after an optimisation, is the=20
"observable behaviour" modified ? What if the program makes use of=20
std::time ?

--=20
Lo=EFc, just wondering...

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Tue, 8 Apr 2003 20:31:21 +0000 (UTC)
Raw View
Lo=EFc Joly wrote:
> If the program runs 10 time faster after an optimisation, is the=20
> "observable behaviour" modified ? What if the program makes use of=20
> std::time ?

No. As you quoted, it's the sequence that counts, not the rate at
which it is made.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: loic.actarus.joly@wanadoo.fr (=?ISO-8859-1?Q?Lo=EFc_Joly?=)
Date: Wed, 9 Apr 2003 05:06:22 +0000 (UTC)
Raw View
Hyman Rosen wrote:
> Lo=EFc Joly wrote:
>=20
>> If the program runs 10 time faster after an optimisation, is the=20
>> "observable behaviour" modified ? What if the program makes use of=20
>> std::time ?
>=20
>=20
> No. As you quoted, it's the sequence that counts, not the rate at
> which it is made.

Yes, but imagine that, depending on the result of std::time(), the=20
program takes diffent branches of a if, that have make totally different=20
outputs ?

--=20
Lo=EFc

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: Thu, 10 Apr 2003 05:49:40 +0000 (UTC)
Raw View
loic.actarus.joly@wanadoo.fr (Lo   c Joly) wrote in message news:<b6v40f$7c9$1@news-reader11.wanadoo.fr>...
> James Kanze wrote:

> > The semantics (or the observable behavior, if you prefer) of a
> > program are defined in terms of an abstract machine which doesn't
> > optimise anything.  After that, a compiler is allowed to optimize
> > according to the as-if rule (the optimization doesn't change any
> > observable behavior), and in a very few, explicitly specified other
> > cases, generally involving unnamed temporaries.  This isn't one of
> > the other cases, so the compiler can suppress the call to foo if and
> > only if it can verify that the observable behavior would be
> > unchanged compared to that of calling foo.

> Do you have a definition of "observable behaviour" ?

> I read in the standard draft :
> > The observable behavior of the abstract machine is its sequence of
> > reads and writes to volatile data and calls to library I/O
> > functions.

> If the program runs 10 time faster after an optimisation, is the
> "observable behaviour" modified ?

No.  See the text you quoted: what is guaranteed is the *sequence*, not
any specific timings.

> What if the program makes use of std::time ?

Makes no difference.  No more than running it on a machine which was 10
times faster would.

The standard requires only that the *sequence* of operations be the same
as on some implementation of the abstract machine.  How fast the
abstract machine runs, or even whether it pauses at random times, is
unspecified by the standard.

--
James Kanze             GABI Software             mailto:kanze@gabi-soft.fr
Conseils en informatique orient   e objet/
                           Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, T   l. : +33 (0)1 30 23 45 16

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: Thu, 10 Apr 2003 05:49:45 +0000 (UTC)
Raw View
loic.actarus.joly@wanadoo.fr (Lo   c Joly) wrote in message
news:<b6vlu8$p5p$1@news-reader11.wanadoo.fr>...
> Hyman Rosen wrote:
> > Lo c Joly wrote:

> >> If the program runs 10 time faster after an optimisation, is the
> >> "observable behaviour" modified ? What if the program makes use of
> >> std::time ?

> > No. As you quoted, it's the sequence that counts, not the rate at
> > which it is made.

> Yes, but imagine that, depending on the result of std::time(), the
> program takes diffent branches of a if, that have make totally
> different outputs ?

Since the speed of the abstract machine is unspecified, some
incarnations of the abstract machine will take one branch, some the
other.  All the standard requires is that the output correspond to that
of at least one incarnation of the abstract machine.

--
James Kanze             GABI Software             mailto:kanze@gabi-soft.fr
Conseils en informatique orient   e objet/
                           Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, T   l. : +33 (0)1 30 23 45 16

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 10 Apr 2003 19:13:26 +0000 (UTC)
Raw View
Lo=EFc Joly wrote:
> Yes, but imagine that, depending on the result of std::time()

Per 1.9/5, same observable behavior requires same input.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Fri, 4 Apr 2003 11:32:07 +0000 (UTC)
Raw View
I actually meant to post this in comp.std.c++.
I put it in comp.lang.c++.moderated by mistake.

allan_w@my-dejanews.com (Allan W) wrote
> Start with this code:
>
>     // Version A
>     #include <iostream>
>     int main() { std::cout << 2 << std::endl; }
>
> We can add an inline function, and the results would be identical:
>
>     // Version B
>     #include <iostream>
>     inline int first(int a, int) { return a; }
>     int main() { std::cout << first(2,5) << std::endl; }
>
> We don't literally have to call first; instead, we can simply evaluate
> the first argument and ignore the second argument.
>
> But what if the second argument had side-effects? Does the unnamed
> parameter have to be evaluated?
>
>     // Version C
>     #include <iostream>
>     extern int foo();
>     inline int first(int a, int) { return a; }
>     int main() { std::cout << first(2,foo()) << std::endl; }
>
> Assume the program knows nothing about foo (it could be in a third-
> party library). Must the program call it, even though the result
> will not be used?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: v.Abazarov@attAbi.com ("Victor Bazarov")
Date: Fri, 4 Apr 2003 15:38:17 +0000 (UTC)
Raw View
"Allan W" <allan_w@my-dejanews.com> wrote...
> I actually meant to post this in comp.std.c++.
> I put it in comp.lang.c++.moderated by mistake.
>
> allan_w@my-dejanews.com (Allan W) wrote
> > Start with this code:
> >
> >     // Version A
> >     #include <iostream>
> >     int main() { std::cout << 2 << std::endl; }
> >
> > We can add an inline function, and the results would be identical:
> >
> >     // Version B
> >     #include <iostream>
> >     inline int first(int a, int) { return a; }
> >     int main() { std::cout << first(2,5) << std::endl; }
> >
> > We don't literally have to call first; instead, we can simply evaluate
> > the first argument and ignore the second argument.
> >
> > But what if the second argument had side-effects? Does the unnamed
> > parameter have to be evaluated?
> >
> >     // Version C
> >     #include <iostream>
> >     extern int foo();
> >     inline int first(int a, int) { return a; }
> >     int main() { std::cout << first(2,foo()) << std::endl; }
> >
> > Assume the program knows nothing about foo (it could be in a third-
> > party library). Must the program call it, even though the result
> > will not be used?


Yes.  Imagine the situation when the definition of 'first' is not
visible to the compiler.  There would be no way for it to know that
the second argument is unused in the function.  So, the code is
generated to evaluate all arguments and let the function sort them
out.  So, should the presence of the function definition cause
differently generated code?  I don't think so.

I presume you are asking here because you wanted to know the rationale
behind 5.2.2/4, not its contents (you can read its contents in your own
copy of the Standard already).

Victor
--
Please remove capital A's from my address when replying by mail


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Sat, 5 Apr 2003 04:18:09 +0000 (UTC)
Raw View
v.Abazarov@attAbi.com ("Victor Bazarov") wrote
> > allan_w@my-dejanews.com (Allan W) wrote
> > >     // Version C
> > >     #include <iostream>
> > >     extern int foo();
> > >     inline int first(int a, int) { return a; }
> > >     int main() { std::cout << first(2,foo()) << std::endl; }
> > >
> > > Assume the program knows nothing about foo (it could be in a third-
> > > party library). Must the program call it, even though the result
> > > will not be used?
>
> Yes.  Imagine the situation when the definition of 'first' is not
> visible to the compiler.  There would be no way for it to know that
> the second argument is unused in the function.  So, the code is
> generated to evaluate all arguments and let the function sort them
> out.  So, should the presence of the function definition cause
> differently generated code?  I don't think so.

I'm talking specifically about inline functions. Since 'first' is
inline, the definition MUST be known at the call point, and the
compiler MUST have enough information to see if the second argument
is used.

For the code above, I would expect the compiler to (in essence) replace
    cout << first(2,foo()) << endl;
with
    cout << 2 << endl;
But is it also forced to call foo() before the sequence point?
Part of me wants it to -- after all, it's obvious by reading the
source code that this function *is* called. But another part of me
wants it to be legal to skip it -- after all, it's obviously not needed.

> I presume you are asking here because you wanted to know the rationale
> behind 5.2.2/4, not its contents (you can read its contents in your own
> copy of the Standard already).

Sort of. 5.2.2/4 isn't exactly vague, but I think there is "wiggle room"
for interpretation. It starts with
    each parameter shall be initialized with its corresponding argument
but then it goes on to
    an implementation may avoid the construction of extra temporaries
    by combining the conversions on the associated argument and/or the
    construction of temporaries with the initialization of the parameter.
For that second point, how far can it go? Can it avoid the construction
of ALL extra temporaries by noting that the parameter isn't used?

I'm not asking if any compiler currently does this... just asking if it
would be legal.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Sat, 5 Apr 2003 06:23:03 +0000 (UTC)
Raw View
On Sat, 5 Apr 2003 04:18:09 +0000 (UTC), allan_w@my-dejanews.com (Allan W)
wrote:

> Sort of. 5.2.2/4 isn't exactly vague, but I think there is "wiggle room"
> for interpretation. It starts with
>     each parameter shall be initialized with its corresponding argument
> but then it goes on to
>     an implementation may avoid the construction of extra temporaries
------------------------------------------------------^^^^^^^^^^^^^^^^^
>     by combining the conversions on the associated argument and/or the
>     construction of temporaries with the initialization of the parameter.
> For that second point, how far can it go? Can it avoid the construction
> of ALL extra temporaries by noting that the parameter isn't used?

Note that parameters are neither temporaries nor extra.  They are
initialized from the arguments.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jdennett@acm.org (James Dennett)
Date: Tue, 8 Apr 2003 08:32:17 +0000 (UTC)
Raw View
Allan W wrote:
> v.Abazarov@attAbi.com ("Victor Bazarov") wrote
>
>>>allan_w@my-dejanews.com (Allan W) wrote
>>>
>>>>    // Version C
>>>>    #include <iostream>
>>>>    extern int foo();
>>>>    inline int first(int a, int) { return a; }
>>>>    int main() { std::cout << first(2,foo()) << std::endl; }
>>>>
>>>>Assume the program knows nothing about foo (it could be in a third-
>>>>party library). Must the program call it, even though the result
>>>>will not be used?
>>
>>Yes.  Imagine the situation when the definition of 'first' is not
>>visible to the compiler.  There would be no way for it to know that
>>the second argument is unused in the function.  So, the code is
>>generated to evaluate all arguments and let the function sort them
>>out.  So, should the presence of the function definition cause
>>differently generated code?  I don't think so.
>
>
> I'm talking specifically about inline functions.

The only way this makes a difference to what gets evaluated
is that it is more likely to allow a compiler to exploit the
"as if" rule.  The semantics of inline functions are only
different to others to the linker.

> Since 'first' is
> inline, the definition MUST be known at the call point, and the
> compiler MUST have enough information to see if the second argument
> is used.
>
> For the code above, I would expect the compiler to (in essence) replace
>     cout << first(2,foo()) << endl;
> with
>     cout << 2 << endl;
> But is it also forced to call foo() before the sequence point?

Yes, it is, unless it can show that foo() has no observable
behavior.

> Part of me wants it to -- after all, it's obvious by reading the
> source code that this function *is* called.

And the abstract C++ machine calls it, so it can only be
optimized away if that optimization is undetectable (by a
conforming program, yada yada).

> But another part of me
> wants it to be legal to skip it -- after all, it's obviously not needed.

Unless the call to foo was put there deliberately, because
of some side-effect.

>>I presume you are asking here because you wanted to know the rationale
>>behind 5.2.2/4, not its contents (you can read its contents in your own
>>copy of the Standard already).
>
>
> Sort of. 5.2.2/4 isn't exactly vague, but I think there is "wiggle room"
> for interpretation. It starts with
>     each parameter shall be initialized with its corresponding argument
> but then it goes on to
>     an implementation may avoid the construction of extra temporaries
>     by combining the conversions on the associated argument and/or the
>     construction of temporaries with the initialization of the parameter.
> For that second point, how far can it go? Can it avoid the construction
> of ALL extra temporaries by noting that the parameter isn't used?

Avoiding the construction of temporaries doesn't allow it
to skip the evaluation of expressions.  It merely allows
it to construct them in-place as the function arguments.

> I'm not asking if any compiler currently does this... just asking if it
> would be legal.

I think the standard is clear in showing that the abstract
C++ machine calls the function, so the only way the call can
be omitted by a compiler is under the "as if" rule.

-- James.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]