Optimizing delegates

Ary Borenszweig ary at esperanto.org.ar
Sun Dec 19 08:59:16 PST 2010


On 12/19/2010 01:57 PM, Ary Borenszweig wrote:
> On 12/19/2010 01:44 PM, Andrei Alexandrescu wrote:
>> On 12/19/10 10:35 AM, Ary Borenszweig wrote:
>>> On 12/19/2010 01:21 PM, Andrei Alexandrescu wrote:
>>>> On 12/19/10 9:32 AM, Ary Borenszweig wrote:
>>>>> I have this code:
>>>>>
>>>>> ---
>>>>> import std.stdio;
>>>>>
>>>>> int foobar(int delegate(int) f) {
>>>>> return f(1);
>>>>> }
>>>>>
>>>>> int foobar2(string s)() {
>>>>> int x = 1;
>>>>> mixin("return " ~ s ~ ";");
>>>>> }
>>>>>
>>>>> void main() {
>>>>> writefln("%d", foobar((int x) { return 2*x; }));
>>>>> writefln("%d", foobar2!("9876*x"));
>>>>> }
>>>>> ---
>>>>>
>>>>> When I compile it with -O -inline I can see with obj2asm that for the
>>>>> first writefln the delegate is being called. However, for the second
>>>>> it just passes
>>>>> 9876 to writefln.
>>>>>
>>>>> From this I can say many things:
>>>>> - It seems that if I want hyper-high performance in my code I must use
>>>>> string mixins because delegate calls, even if they are very simple and
>>>>> the
>>>>> functions that uses them are also very simple, are not inlined. This
>>>>> has the drawback that each call to foobar2 with a different string
>>>>> will generate a
>>>>> different method in the object file.
>>>>
>>>> You forgot:
>>>>
>>>> writefln("%d", foobar2!((x) { return 2*x; })());
>>>>
>>>> That's a real delegate, not a string, but it will be inlined.
>>>>
>>>>
>>>> Andrei
>>>
>>> Sorry, I don't understand. I tried these:
>>>
>>> 1.
>>> int foobar3(int delegate(int) f)() {
>>> return f(1);
>>> }
>>>
>>> writefln("%d", foobar3!((int x) { return 2*x; })());
>>>
>>> => foo.d(12): Error: arithmetic/string type expected for
>>> value-parameter, not int delegate(int)
>>>
>>> 2.
>>> int foobar3()(int delegate(int) f) {
>>> return f(1);
>>> }
>>>
>>> writefln("%d", foobar3!()((int x) { return 2*x; }));
>>>
>>> => Works, but it doesn't get inlined.
>>>
>>> And I tried that "(x) { ... }" syntax and it doesn't work.
>>>
>>> Sorry, it must be my fault I'm doing something wrong. What's the correct
>>> way of writing optimized code in D, code that I'm sure the compiler will
>>> know how to optimize?
>>
>> void foobar3(alias fun)() {
>> return fun(1);
>> }
>>
>>
>> Andrei
>
> foo.d
> ---
> import std.stdio;
>
> int foobar3(alias f)() {
> return f(1);
> }
>
> void main() {
> writefln("%d", foobar3!((x) { return 9876*x; })());
> }
>
> asterite at deep-water:~/dmd2/linux/bin$ ./dmd foo.d -O -inline
> asterite at deep-water:~/dmd2/linux/bin$ ./obj2asm foo.o | vi -
> (line 530)
> _Dmain:
> push EBP
> mov EBP,ESP
> mov EAX,offset FLAT:_D3std5stdio6stdoutS3std5stdio4File at SYM32
> push dword ptr _TMP0 at SYM32[0Eh]
> push dword ptr _TMP0 at SYM32[010h]
> push 02694h
> call _D3std5stdio4File19__T8writeflnTAyaTiZ8writeflnMFAyaiZv at PC32
> xor EAX,EAX
> pop EBP
> ret
> nop
> nop
>
> No, it doesn't seem to get inlined. Luckily. Because if it did get
> inlined then I would improve DMD by giving an error on this line:
>
> int foobar(int delegate(int) f) {
> ...
> }
>
> foo.d(3): Error: Hey man, what are you doing? Don't you know that if you
> pass delegates that way they don't get inlined? You should write it this
> way: "int foobar(alias f)()". That is, of course, if you want your code
> to be more performant.

Oops, sorry, it does get inlined, my mistake. I will submit a patch to 
DMD right now with the above error.


More information about the Digitalmars-d mailing list