I was answering a question and recommending return by-value for a large type because I was confident the compiler would perform return-value optimization (RVO). But then it
If the code looks like it should be optimized, but is not getting optimized I would submit bug here http://connect.microsoft.com/VisualStudio or raise a support case with Microsoft. This article, although it is for VC++2005 (I couldn't find a current version of document) does explain some scenarios where it won't work. http://msdn.microsoft.com/en-us/library/ms364057(v=vs.80).aspx#nrvo_cpp05_topic3
If we want to be sure the optimization has occurred, one possibility is to check the assembly output. This could be automated as a build task if desired.
This requires generating .asm output using /FAs option like so:
cl test.cpp /FAs
Will generate test.asm.
A potential example in PowerShell below, which can be used in this way:
PS C:\test> .\Get-RVO.ps1 C:\test\test.asm test.cpp
NOT RVO test.cpp - ; 13 : return Foo(std::move(v));// Expecting RVO to happen here.
PS C:\test> .\Get-RVO.ps1 C:\test\test_v2.optimized.asm test.cpp
RVO OK test.cpp - ; 13 : return {std::move(v)}; // Expecting RVO to happen here.
PS C:\test>
The script:
# Usage Get-RVO.ps1 <input.asm file> <name of CPP file you want to check>
# Example .\Get-RVO.ps1 C:\test\test.asm test.cpp
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True,Position=1)]
[string]$assemblyFilename,
[Parameter(Mandatory=$True,Position=2)]
[string]$cppFilename
)
$sr=New-Object System.IO.StreamReader($assemblyFilename)
$IsInReturnSection=$false
$optimized=$true
$startLine=""
$inFile=$false
while (!$sr.EndOfStream)
{
$line=$sr.ReadLine();
# ignore any files that aren't our specified CPP file
if ($line.StartsWith("; File"))
{
if ($line.EndsWith($cppFilename))
{
$inFile=$true
}
else
{
$inFile=$false
}
}
# check if we are in code section for our CPP file...
if ($inFile)
{
if ($line.StartsWith(";"))
{
# mark start of "return" code
# assume optimized, unti proven otherwise
if ($line.Contains("return"))
{
$startLine=$line
$IsInReturnSection=$true
$optimized=$true
}
}
if ($IsInReturnSection)
{
# call in return section, not RVO
if ($line.Contains("call"))
{
$optimized=$false
}
# check if we reached end of return code section
if ($line.StartsWith("$") -or $line.StartsWith("?"))
{
$IsInReturnSection=$false
if ($optimized)
{
"RVO OK $cppfileName - $startLine"
}
else
{
"NOT RVO $cppfileName - $startLine"
}
}
}
}
}