www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - calling convention optimisation & const/immutable ref

reply John Colvin <john.loughran.colvin gmail.com> writes:
Some people use ref for performance to prevent the copying that 
must occur when passing by value. I propose a small optimisation 
to make this unnecessary in a bunch of cases.

At the ABI level (no change in language semantics), if a given 
parameter would otherwise be copied and passed on the stack:
1) immutable parameters to all functions are passed by reference
2) const parameters to pure functions are passed by reference, if 
and only if all other parameters - including any implicit this 
parameter - contain no mutable references (otherwise "weakly" 
pure functions could modify the data we are now referring to 
instead of having copied, changing semantics).

The main benefit from this would be:

class C
{
   void doSomething(const float[16] m0) const pure
   {
     // ...
   }

   void doSomethingElse(immutable float[16] m1)
   {
     // ...
   }
}

void foo(C c, float[16] m0, immutable float[16] m1)
{
   // ...
   c.doSomething(m0); // no copying of m0 here
   c.doSomethingElse(m1); // or m1 here
   // ...
}

I presume this has been thought of before, is there a reason why 
we don't do it already? I guess 2) is a bit complicated, but 1) 
is easy.
Nov 07 2016
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2016-11-07 17:48, John Colvin wrote:
 Some people use ref for performance to prevent the copying that must
 occur when passing by value. I propose a small optimisation to make this
 unnecessary in a bunch of cases.

 At the ABI level (no change in language semantics), if a given parameter
 would otherwise be copied and passed on the stack:
 1) immutable parameters to all functions are passed by reference
 2) const parameters to pure functions are passed by reference, if and
 only if all other parameters - including any implicit this parameter -
 contain no mutable references (otherwise "weakly" pure functions could
 modify the data we are now referring to instead of having copied,
 changing semantics).

 The main benefit from this would be:

 class C
 {
   void doSomething(const float[16] m0) const pure
   {
     // ...
   }

   void doSomethingElse(immutable float[16] m1)
   {
     // ...
   }
 }

 void foo(C c, float[16] m0, immutable float[16] m1)
 {
   // ...
   c.doSomething(m0); // no copying of m0 here
   c.doSomethingElse(m1); // or m1 here
   // ...
 }

 I presume this has been thought of before, is there a reason why we
 don't do it already? I guess 2) is a bit complicated, but 1) is easy.
Since D is a systems programming language, wouldn't the user want to have control over this? -- /Jacob Carlborg
Nov 07 2016
parent reply John Colvin <john.loughran.colvin gmail.com> writes:
On Monday, 7 November 2016 at 20:23:37 UTC, Jacob Carlborg wrote:
 Since D is a systems programming language, wouldn't the user 
 want to have control over this?
It's just another optimisation in a long list of optimisations that can be performed without changing semantics. What about this one is less "systems language" worthy than - for example - constant folding or dead code elimination?
Nov 07 2016
parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Monday, 7 November 2016 at 21:45:42 UTC, John Colvin wrote:
 On Monday, 7 November 2016 at 20:23:37 UTC, Jacob Carlborg 
 wrote:
 Since D is a systems programming language, wouldn't the user 
 want to have control over this?
It's just another optimisation in a long list of optimisations that can be performed without changing semantics. What about this one is less "systems language" worthy than - for example - constant folding or dead code elimination?
What about ABI compatibility ?
Nov 07 2016
parent reply John Colvin <john.loughran.colvin gmail.com> writes:
On Monday, 7 November 2016 at 22:46:57 UTC, Stefan Koch wrote:
 On Monday, 7 November 2016 at 21:45:42 UTC, John Colvin wrote:
 On Monday, 7 November 2016 at 20:23:37 UTC, Jacob Carlborg 
 wrote:
 Since D is a systems programming language, wouldn't the user 
 want to have control over this?
It's just another optimisation in a long list of optimisations that can be performed without changing semantics. What about this one is less "systems language" worthy than - for example - constant folding or dead code elimination?
What about ABI compatibility ?
Yeah, I guess it's not a traditional optimisation. I'm suggesting a change to the D ABI to let it use some of the extra information that D has in function signatures.
Nov 07 2016
parent Stefan Koch <uplink.coder googlemail.com> writes:
On Monday, 7 November 2016 at 23:19:18 UTC, John Colvin wrote:
 On Monday, 7 November 2016 at 22:46:57 UTC, Stefan Koch wrote:
 On Monday, 7 November 2016 at 21:45:42 UTC, John Colvin wrote:
 On Monday, 7 November 2016 at 20:23:37 UTC, Jacob Carlborg 
 wrote:
 Since D is a systems programming language, wouldn't the user 
 want to have control over this?
It's just another optimisation in a long list of optimisations that can be performed without changing semantics. What about this one is less "systems language" worthy than - for example - constant folding or dead code elimination?
What about ABI compatibility ?
Yeah, I guess it's not a traditional optimisation. I'm suggesting a change to the D ABI to let it use some of the extra information that D has in function signatures.
This is not a good idea. Also changing to references is not always a performance win, It introduces another point where caches can stall.
Nov 07 2016
prev sibling next sibling parent Marc =?UTF-8?B?U2Now7x0eg==?= <schuetzm gmx.net> writes:
On Monday, 7 November 2016 at 16:48:55 UTC, John Colvin wrote:
 Some people use ref for performance to prevent the copying that 
 must occur when passing by value. I propose a small 
 optimisation to make this unnecessary in a bunch of cases.

 At the ABI level (no change in language semantics), if a given 
 parameter would otherwise be copied and passed on the stack:
 1) immutable parameters to all functions are passed by reference
 2) const parameters to pure functions are passed by reference, 
 if and only if all other parameters - including any implicit 
 this parameter - contain no mutable references (otherwise 
 "weakly" pure functions could modify the data we are now 
 referring to instead of having copied, changing semantics).
If this is done, it should only apply to parameters larger than a certain size, say 2 words. Indirect memory access comes with its own cost that is often larger than that of copying.
Nov 08 2016
prev sibling parent reply Johan Engelen <j j.nl> writes:
On Monday, 7 November 2016 at 16:48:55 UTC, John Colvin wrote:
 Some people use ref for performance to prevent the copying that 
 must occur when passing by value.
This reminds me of an LLVM presentation by Chandler, mentioning that passing by reference may hamper the optimization of code (because memory becomes involved). I don't think he gave a clear example, but one thing I can think of is potential aliasing: void foo(ref LargeThing a, ref LargeThing b), where a and b may alias partly. To do the "ref" optimization for _all_ large function parameters per default sounds like a bad idea. Also, how would I turn the optimization off (I guess extern(C++) would do that?)? What if my function needs a local copy (say, in multithreaded stuff), and I want that copy to be const? -Johan
Nov 08 2016
parent Matthias Bentrup <matthias.bentrup googlemail.com> writes:
On Tuesday, 8 November 2016 at 12:56:10 UTC, Johan Engelen wrote:
 On Monday, 7 November 2016 at 16:48:55 UTC, John Colvin wrote:
 [...]
This reminds me of an LLVM presentation by Chandler, mentioning that passing by reference may hamper the optimization of code (because memory becomes involved). I don't think he gave a clear example, but one thing I can think of is potential aliasing: void foo(ref LargeThing a, ref LargeThing b), where a and b may alias partly. To do the "ref" optimization for _all_ large function parameters per default sounds like a bad idea. Also, how would I turn the optimization off (I guess extern(C++) would do that?)? What if my function needs a local copy (say, in multithreaded stuff), and I want that copy to be const? -Johan
Aliasing is not an issue when LargeThing is immutable, is it ?
Nov 08 2016