Thread overview
[Issue 7353] New: NRVO not properly working with inferred return type
Jan 23, 2012
Trass3r
Jan 23, 2012
Trass3r
Feb 12, 2012
Lionello Lunesu
Feb 15, 2012
Kenji Hara
Feb 15, 2012
Trass3r
Feb 15, 2012
Kenji Hara
Feb 15, 2012
Trass3r
Feb 18, 2012
Walter Bright
January 23, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7353

           Summary: NRVO not properly working with inferred return type
           Product: D
           Version: D1 & D2
          Platform: All
        OS/Version: All
            Status: NEW
          Keywords: performance
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody@puremagic.com
        ReportedBy: mrmocool@gmx.de


--- Comment #0 from Trass3r <mrmocool@gmx.de> 2012-01-23 16:27:36 CET ---
import std.stdio;
struct S
{
    static uint ci = 0;
    uint i;

    this(int x)
    {
        i = ci++;
        writeln("new: ", i);
    }

    this(this)
    {
        i = ci++;
        writeln("copy ", i);
    }

    ~this()
    {
        writeln("del ", i);
    }

    S save1() // produces 2 copies in total
    {
        S s = this;
        return s;
    }

    auto save2() // produces 3 copies in total
    {
        S s = this;
        return s;
        pragma(msg, typeof(return));
    }

    S save3()
    {
        return this;
    }
}

void main()
{
    {
    S s = S(1);
    S t = S(1);

    t = s.save1();
    }

    writeln("-");
    S.ci = 0;
    {
    S s = S(1);
    S t = S(1);
    t = s.save2();
    }

    writeln("-");
    S.ci = 0;
    {
    S s = S(1);
    S t = S(1);
    t = s.save3();
    }
}


$ dmd -run test.d
//or dmd -release -run test.d
//or dmd -release -O -run test.d
S
new: 0
new: 1
copy 2
del 1
del 2
del 0
-
new: 0
new: 1
copy 2
copy 3
del 2
del 1
del 3
del 0
-
new: 0
new: 1
copy 2
del 1
del 2
del 0

$ dmd -release -O -inline -run test.d
S
new: 0
new: 1
copy 2
del 1
del 2
del 0
-
new: 0
new: 1
copy 2
copy 3
del 2
del 1
del 3
del 0
-
new: 0
new: 1
del 1
del 0
del 0

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 23, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7353


Trass3r <mrmocool@gmx.de> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |wrong-code


--- Comment #1 from Trass3r <mrmocool@gmx.de> 2012-01-23 16:32:24 CET ---
Hmm that last one even looks like a wrong-code bug, 0 is deleted twice.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 12, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7353


Lionello Lunesu <lio+bugzilla@lunesu.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |lio+bugzilla@lunesu.com
           Severity|normal                      |critical


-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 15, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7353


Kenji Hara <k.hara.pg@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|wrong-code                  |pull
            Version|D1 & D2                     |D2


--- Comment #2 from Kenji Hara <k.hara.pg@gmail.com> 2012-02-15 06:39:48 PST ---
Postblit is only in D2 spec, so this is not 'D1 & d2' issue.

I think save3() is inlining problem, then I've separated it as bug 7506. Therefore I remove 'wrong-code' keyword.

----

Current compiler implementation disables nrvo with auto function. I've post a pull to fix it.

https://github.com/D-Programming-Language/dmd/pull/722

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 15, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7353



--- Comment #3 from Trass3r <mrmocool@gmx.de> 2012-02-15 17:48:44 CET ---
You're right. The third one is an inlining problem.

But there's a different thing I'm now confused about. Why is postblit called
after all?
It's assignment to t, not construction.

See the docs:
struct S { ... }
S s;      // default construction of s
S t = s;  // t is copy-constructed from s => this(this)
t = s;    // t is assigned from s => opAssign

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 15, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7353



--- Comment #4 from Kenji Hara <k.hara.pg@gmail.com> 2012-02-15 09:16:26 PST ---
(In reply to comment #3)
> You're right. The third one is an inlining problem.
> 
> But there's a different thing I'm now confused about. Why is postblit called
> after all?
> It's assignment to t, not construction.
> 
> See the docs:
> struct S { ... }
> S s;      // default construction of s
> S t = s;  // t is copy-constructed from s => this(this)
> t = s;    // t is assigned from s => opAssign

The assignment to t does not call postblit. Because the built-in opAssign is implemented as 'swap and destroy' due to never create any unnecessary copy on assignment.

First of all, S has postblit, then dmd creates implicit built-in opAssing like
follows:
ref S opAssign(S rhs) {  // rhs receives rvalue, not lvalue
  swap(this, rhs);
  return this;
  // rhs is destroyed the end of opAssign function scope
}

Next, the code sequence with explanation:
{
    S s = S(1);   // prints new: 0
    S t = S(1);   // prints new: 1
    t = s.save1();
    // is translated to t.opAssign(s.save1())
    // inside save1():
        S s = this;   // prints copy 2
        return s;     // s is moved out by nrvo
    // t.opAssign receives moved value, so is never copied
    // inside t.opAssign():
        // this (this.i==1) is swapped with rhs, and destroyed
        // prints del 1
    // s.i == 0
    // t.i == 2
    // destroyed local variables in reverse order
    // prints del 2
    // prints el 1
}

Last, the postblit call runs only once.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 15, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7353



--- Comment #5 from Trass3r <mrmocool@gmx.de> 2012-02-15 20:39:08 CET ---
Ok, so in essence the postblit is the one called by 'S s = this;' in save1. But what about save3?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 18, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7353



--- Comment #6 from github-bugzilla@puremagic.com 2012-02-17 18:21:35 PST ---
Commit pushed to master at https://github.com/D-Programming-Language/dmd

https://github.com/D-Programming-Language/dmd/commit/02ecef1cea5dea4f78bafb7533c896d0d9b07816 Merge pull request #722 from 9rnsr/fix7353

Issue 7353 - NRVO not properly working with inferred return type

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 18, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7353


Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |bugzilla@digitalmars.com
         Resolution|                            |FIXED


-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------