Topic: Concerns on specifying evaluation order of function


Author: Kazutoshi Satoda <k_satoda@f2.dion.ne.jp>
Date: Fri, 20 Nov 2015 05:24:39 +0900
Raw View
P0145R0: Refining Expression Evaluation Order for Idiomatic C++ (Revision 1)
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0145r0.pdf
> In summary, the following expressions are evaluated in the order
> a, then b, then c, then d:
....
>     3. a(b, c, d)

I have thought of a pattern where specifying evaluation order of
function arguments can result in general and noticeable prohibition
of some compiler optimizations.
(I'm afraid of that this is already discussed, or I'm just writing
 something silly. I'm not a compiler writer, and the paper should
 have been reviewed by some compiler writers...)

Consider the following transformation from g() to g_transformed():

  int f(int a1, int a2, int a3);
  int pure(int);
  int non_local;

  int g(int (*unknown)())
  {
    return f(pure(non_local), unknown(), pure(non_local));
  }

  int g_transformed(int (*unknown)())
  {
    int temp = pure(non_local);
    return f(temp, unknown(), temp);
  }

Assuming that the compiler can detect or be informed that pure() is a
pure function (it returns a value depending only on its arguments), this
transformation is valid as optimization because the compiler is allowed
to choose the evaluation order as (a1 -> a3 -> a2) so that it can be
proven that two evaluations of "pure(non_local)" produce a same value.

If evaluation order is specified as "left to right", this transformation
is no longer possible because unknown() can modify non_local and then
two evaluations of "pure(non_local)" can produce different values.

If the execution time of unknown() and f() are negligible compared to
the execution time of pure(), the total execution time of g() can be
essentially doubled by adoption of P0145R0.

While the above code looks a fiction, I think the pattern can be found
in real codes with some replacements:
  - pure(): complex math functions, inspection on a range (like strlen())
  - non_local: class non-static data members
  - unknown: class virtual functions
Also, the pattern can appear as a intermediate result of inlining.


I found only the following about performance concern of P0145R0:
https://isocpp.org/blog/2015/11/kona-standards-meeting-trip-report
>   Performance was a concern: will performance suffer? It will for some
>   older machine architectures (1% was mentioned), but there can be
>   backwards compatibility switches and performance-sensitive
>   applications have mostly moved to architectures where there is no
>   performance degradation years ago.
>
>   This proposal was accepted.
But I think the above mentioned prohibition of transformation is general
issue, not only on older machine architectures, and can be noticeable
performance difference.

Is these kind of concern already discussed?


P.S.
I found that the "formal wording" in P0145R0 is a bit informal:
  - "sequenced before/after" are used as a relation between two
    expressions. But it is defined as a relation between evaluations
    (value computations and side effects).
  - "sequenced from left to right" should be something like this?
    "value computations and side effects associated with an argument
    expression is sequenced before any of the next argument (if any)."

--
k_satoda

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.