c++ - 如何让优化器正确地将变量放入寄存器?

标签 c++ visual-studio optimization

我有一个简单的函数,它通过引用获取两个变量:

void foo(int*& it2,
         bit_reader<big_endian_tag>& reader2)
{
    for(/* ... */)
    {
        *it2++ = boo(reader2.next());
        // it2++ => 0x14001d890 add qword ptr [r12], 0x4
    }
}

这里的问题是,对于 it2reader2,优化器使计算机在循环期间写入内存而不是寄存器。

但是,以下代码在循环期间将变量正确地放入寄存器,但在循环前后以不必要的拷贝形式存在额外开销:

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;
}

例如

如何让第一个示例生成与第二个示例相同的代码,但没有额外的拷贝?

最佳答案

问题是编译器无法证明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());

这不会为 otherInt 分配任何内容,而在转换之后它将:

void bar(int*& ptr, const foo& f)
{
    int* ptrCopy = ptr;
    *ptrCopy = f.blah(); // changes ptr, but not ptrCopy
}

因此,除非编译器能够证明行为相同,否则无法进行优化。

C99 使用 restrict 关键字解决了这个问题,但 C++ 没有等效项。不过,大多数 C++ 编译器中都存在一些扩展,例如 __restrict____restrict

要在标准 C++ 中执行此操作,您只需明确并自己制作拷贝

关于c++ - 如何让优化器正确地将变量放入寄存器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11977625/

相关文章:

r - 交叉何时以及为何对差异进化有益?

c++ - "atomic object"的定义

c# - 像扩展名为 .csproj 的项目文件可以有除 XML 之外的其他格式吗?

c++ - python中char *的问题

visual-studio - 如何在 Visual Studio 中更改偶数行背景颜色?

sql-server - SQL 编辑器窗口始终连接到 (localdb\ProjectsV13)。在哪里更改此默认值?

javascript - 如何在构建期间不创建 404/不匹配匿名模块的情况下在 amd 兼容性检查中声明依赖项?

list - Clojure 数据结构翻译

c++ - 如何将多个 vtkprop 或 vtkactor 组合成一个更大的 actor 或 prop?

c++ - 搜索具有多个匹配项的元素