ron*_*nag 1 c++ optimization visual-studio
我有一个简单的函数,它通过引用获取两个变量:
void foo(int*& it2,
bit_reader<big_endian_tag>& reader2)
{
for(/* ... */)
{
*it2++ = boo(reader2.next());
// it2++ => 0x14001d890 add qword ptr [r12], 0x4
}
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是for it2和reader2优化器使计算机在循环期间写入内存而不是寄存器.
但是,以下代码在循环期间将变量正确地放入寄存器中,但在循环之前和之后以不必要的副本的形式存在额外的开销:
void foo2(int*& it2,
bit_reader<big_endian_tag>& reader2)
{
auto reader = reader2;
auto it = it2;
for(/* ... */)
{
*it++ = boo(reader.next());
// it++ => 0x14001d890 add r15, 0x4
}
reader2 = reader;
it2 = it;
}
Run Code Online (Sandbox Code Playgroud)
例如
如何使第一个示例生成与第二个示例相同的代码但没有额外的副本?
问题是编译器无法证明it2函数内部没有变化.(嗯,它可以,但这远远超出普通C++编译器的预期功能.)
它如何知道boo(reader2.next());不会改变价值?考虑:
int* i = 0;
struct foo
{
int myInt;
int blah() { i = &myInt; return 5; }
};
void bar(int*& ptr, const foo& f)
{
*ptr = f.blah(); // changes value of ptr!
}
int otherInt;
i = &otherInt;
bar(i, foo());
Run Code Online (Sandbox Code Playgroud)
这不会分配任何内容otherInt,而在转换后它会:
void bar(int*& ptr, const foo& f)
{
int* ptrCopy = ptr;
*ptrCopy = f.blah(); // changes ptr, but not ptrCopy
}
Run Code Online (Sandbox Code Playgroud)
因此,除非编译器能够证明行为是相同的,否则它无法进行优化.
C99用restrict关键字解决了这个问题,但是C++没有等价物.但是,大多数C++编译器中都存在扩展,例如__restrict__或__restrict.
要在标准C++中执行此操作,您只需要明确并自己制作副本