www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Possible optimization opportunity when assigning to a member in the

reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
struct Inner below has an opAssign that gets called in Outer.this even 
with -O. That opAssign call seems unnecessary:

import std.stdio;

struct Inner
{
     int i;

     void opAssign(Inner rhs)
     {
         writeln("moving");
     }
}

struct Outer
{
     Inner inner;

     this(int i)
     {
         writeln("Assigning to this.inner");
         this.inner = Inner(i);
     }
}

void main()
{
     writeln("Constructing main.inner");
     auto inner = Inner(42);

     writeln("Constructing main.outer");
     auto outer = Outer(43);
}

The two lines in main are different from the point of view of two Inners 
in the program: The first one is the construction of an Inner variable. 
The second one is the construction of an Outer variable which happens to 
have an Inner member.

Here is the output of the program:

   Constructing main.inner
   Constructing main.outer
   Assigning to this.inner
   moving

I think the last line should not happen.

Naturally, there is no opAssign called when constructing main.inner. 
However, the assignment to this.inner in the constructor is treated as a 
"move" of the value Inner(i) on top of the value of Inner.init. Although 
there is nothing wrong with that, I think the compiler can simply blit 
Inner(i) to this.inner and doing so would be safe.

Does that make sense? Something like "If an rvalue is assigned to a 
member in a constructor, do not call opAssign() of the member".

Ali
Mar 14 2013
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Friday, 15 March 2013 at 04:09:25 UTC, Ali Çehreli wrote:
 struct Inner below has an opAssign that gets called in 
 Outer.this even with -O. That opAssign call seems unnecessary:

 import std.stdio;

 struct Inner
 {
     int i;

     void opAssign(Inner rhs)
     {
         writeln("moving");
     }
 }

 struct Outer
 {
     Inner inner;

     this(int i)
     {
         writeln("Assigning to this.inner");
         this.inner = Inner(i);
     }
 }

 void main()
 {
     writeln("Constructing main.inner");
     auto inner = Inner(42);

     writeln("Constructing main.outer");
     auto outer = Outer(43);
 }

 The two lines in main are different from the point of view of 
 two Inners in the program: The first one is the construction of 
 an Inner variable. The second one is the construction of an 
 Outer variable which happens to have an Inner member.

 Here is the output of the program:

   Constructing main.inner
   Constructing main.outer
   Assigning to this.inner
   moving

 I think the last line should not happen.

 Naturally, there is no opAssign called when constructing 
 main.inner. However, the assignment to this.inner in the 
 constructor is treated as a "move" of the value Inner(i) on top 
 of the value of Inner.init. Although there is nothing wrong 
 with that, I think the compiler can simply blit Inner(i) to 
 this.inner and doing so would be safe.

 Does that make sense? Something like "If an rvalue is assigned 
 to a member in a constructor, do not call opAssign() of the 
 member".

 Ali
Yes, in general, first assignment in a constructor should be considered as a declaration if the value is not read before. This allow for the mentioned optimization, but many very other important stuff as well, like the construction of immutable objects.
Mar 14 2013
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/14/2013 09:54 PM, deadalnix wrote:
 On Friday, 15 March 2013 at 04:09:25 UTC, Ali Çehreli wrote:
 Something like "If an rvalue is assigned to a
 member in a constructor, do not call opAssign() of the member".

 Ali
Yes, in general, first assignment in a constructor should be considered as a declaration if the value is not read before. This allow for the mentioned optimization, but many very other important stuff as well, like the construction of immutable objects.
Thank you! Opened an enhancement request: http://d.puremagic.com/issues/show_bug.cgi?id=9732 Ali
Mar 15 2013