Can we fix reverse operator overloading (opSub_r et. al.)?

Jarrett Billingsley jarrett.billingsley at gmail.com
Fri Jul 10 19:58:44 PDT 2009


On Fri, Jul 10, 2009 at 10:18 PM, Rainer Deyke<rainerd at eldwood.com> wrote:
> BCS wrote:
>> Reply to Rainer,
>>
>>> 2. Expression-level optimization is the compiler's job, not the
>>> programmer's.
>>>
>>
>> Some (many?) of the interesting optimizations that can be applied to
>> expressions with overloaded operators are not algebraic in nature.
>
> I'm not sure what you mean by "algebraic" here, but...
>
>> Many of the use cases for operator overloading don't work if the
>> compiler is allowed to assume all the same identities it can for scalars
>> (e.g. the transitive identity doesn't hold for matrix math).
>
> The compiler shouldn't make any assumptions.  The compiler doesn't
> /need/ to make any assumptions, since the compiler has access to the
> actual code.  For example, take a simple vector expression, with
> 3-element vectors:
>
>  a = cross_product(b, c + d + e)
>
> First the compiler rewrites this to use a temporary variable:
>
>  tmp = c + d
>  tmp = tmp + e
>  a = cross_product(b, tmp)
>
> Then the compiler inlines both functions and unrolls the loops:
>
>  tmp[0] = c[0] + d[0]
>  tmp[1] = c[1] + d[1]
>  tmp[2] = c[2] + d[2]
>  tmp[0] = tmp[0] + e[0]
>  tmp[1] = tmp[1] + e[1]
>  tmp[2] = tmp[2] + e[2]
>  a[0] = b[1] * tmp[2] - b[2] - tmp[1]
>  a[1] = b[2] * tmp[0] - b[0] - tmp[2]
>  a[2] = b[0] * tmp[1] - b[1] - tmp[0]
>
> The compiler then reduces the temporary vector to a set of temporary
> scalars, probably stored in registers:
>
>  tmp0 = c[0] + d[0] + e[0]
>  tmp1 = c[1] + d[1] + e[1]
>  tmp2 = c[2] + d[2] + e[2]
>  a[0] = b[1] * tmp2 - b[2] - tmp1
>  a[1] = b[2] * tmp0 - b[0] - tmp2
>  a[2] = b[0] * tmp1 - b[1] - tmp0
>
> The compiler sees no further optimizations, so it leaves the code as is.
>  This as about as good as a human optimizer could have done.  If the CPU
> has built-in support for vector cross-multiplication, the compiler can
> use this at the code generation stage.
>
>> Unless you wan to make a way for the programmer to both add and remove
>> expression level optimizations, and require an optimization engine
>> powerful enough to use them, you can't do optimization of expressions
>> with overloaded operators purely in the compiler.
>
> Why should the programmer need to give hints to the compiler when the
> compiler already has enough information to figure out how to optimize
> properly?

You're somewhat wrong on two points:

1) The compiler doesn't always have the code.  If you're linking
against a library, where the operator overloads are not given in the
headers, the compiler doesn't have their code.  Link-time optimization
might be able to help here, but without the original syntax tree to
work with, it's probably not going to be able to do the same things.

2) The compiler doesn't necessarily have enough information to
optimize properly.  Virtual calls destroy any guarantees.  OK, sure,
you could say "vector and matrix types really should be structs and
therefore not use virtual calls," but in the general case, the
compiler can't figure these things out.

You're right, however, that in the vast majority of cases, the
compiler *could* optimize calls to these functions.  But you still
might need some way of informing the compiler "hey!  I really _really_
would like you to inline this."



More information about the Digitalmars-d mailing list