On Thu, Jul 15, 2010 at 1:34 PM, Stefan Behnel <[email protected]> wrote:
> Stefan Behnel, 15.07.2010 19:34:
>> In most cases,
>> nodes and their results have to be reused, and there isn't currently a good
>> way to do that, especially not before type inference and analysis, which
>> may end up wanting to assign different types to the same node result in the
>> different contexts.
>
> Let's exercise this a bit. The min/max transformation is a perfect example
> here. It expands this code
>
>     x = min(a,b,c)
>
> into this code
>
>     x = a
>     if x > b: x = b
>     if x > c: x = c
>
> Now, you have to evaluate each input parameter exactly once, and each
> evaluation can potentially throw an exception. How would you do this in a
> source-level transformation? The only way I see is to introduce temp nodes
> already at this point,

Yep, you have to anyway to preserve the semantics.

> i.e. you'd make it
>
>     x, _b, _c = a, b, c
>     if x > _b: x = _b
>     if x > _c: x = _c
>
> Next, to make the comparisons efficient if x has a Python type, _b and _c
> must have the same type as x.

The expanded code would be

res, _b, _c = a, b, c
if res > _b: res = _b
if res > _c: res = _c
# cleanup _b, _c
x = res

so the assignment (and type of the user-visible x) is orthogonal. Of
course, a could be an object too...One could even do

r1, _b, _c = a, b, c
r2 = r1 if r1 < _b else _b
r3 = r2 if r2 < _c else _c

so it stays in C land as long as possible, but that may not be worth it.

> Otherwise, both the comparison and the
> assignment would lead to redundant coercions. How would you assure that?
> Note that type inference will not work here, as it only impacts the type of
> x. All other type analysis steps are local.
>
> I can see us making it less local by injecting back-references to those
> nodes that depend on a node's type. That might allow us to minimise the
> number of neccessary coercions for a value. However, to do this right, we
> need flow analysis to even see which code paths actually lead to a coercion.

Hopefully a simple kind of common subexpression elimination could
remove the redundant coercions (as well as help out in a lot of other
places).


Also, the 1-value min/max could be optimized away, and the 2-value one could be

    x = a if a < b else b

in conjunction with another possible optimization

    (a if X else b).coerce_to(T)

becomes

    a.coerce_to(T) if X else b.coerce_to(T)

- Robert
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev

Reply via email to