c++ - C++ 编译器会消除赋值重复吗?

标签 c++ optimization compiler-construction compiler-optimization

如果我有一个示例函数,例如:

void func1(float a, float b, float c)
{
    setA(a);
    setB(b);
    setC(c);                                        
}

调用内联函数:

inline void setA(float a){ m_a = a; m_isValid = false; }
inline void setB(float b){ m_b = b; m_isValid = false; }
inline void setC(float c){ m_c = c; m_isValid = false; }

我应该关心“m_isValid = false”重复项还是编译器通过优化消除它们?

最佳答案

是的,这通常称为 Dead Store Elimination (用编译器的说法,读取 = 加载和写入 = 存储)。

一般来说,任何无用的操作都可以被编译器优化掉,前提是它可以证明你(用户)不会注意到它(在语言设置的范围内)。

特别是对于 Dead Store Elimination,它通常仅限于:

  • 单个函数的主体(然而,内联在这里有帮助)
  • 无需干预对不透明函数的调用

一些例子:

struct Foo { int a; int b; };

void opaque(Foo& x); // opaque, aka unknown definition

Foo foo() {
    Foo x{1, 2};
    x.a = 3;
    return x; // provably returns {3, 2}
              // thus equivalent to Foo foo() { return {3, 2}; }
}

Foo bar() {
    Foo x{1, 2};
    opaque(x); // may use x.a, so need to leave it at '1' for now
    x.a = 3;
    return x;
}

Foo baz() {
    Foo x{1, 2};
    opaque(x);
    x.a = 1;   // x.a may have been changed, cannot be optimized
    return x;
}

请注意,是否连续存储相同的值并不重要,只要编译器能够证明在两次存储操作之间没有读取一个变量,它就可以安全地消除第一个。

特殊情况:根据 C++ 规范,加载/存储到 volatile 无法优化。这是因为 volatile 被指定为允许与硬件交互,因此编译器无法先验地知道硬件是否会在程序背后读取或写入变量。

另一种特殊情况:出于优化的目的,在多线程程序中使用的内存同步操作(fences、barrier 等)也可以阻止这种优化。这是因为,与 volatile 情况非常相似,同步意味着另一个执行线程可能已经修改了该线程背后的变量。

最后,像所有优化一样,它的有效性在很大程度上取决于对上下文的了解。如果证明 opaque 不读取或不写入 x.a,则可以优化一些存储(如果编译器可以检查 的定义,则证明>不透明),所以一般来说它真的依赖于内联和常量传播。

关于c++ - C++ 编译器会消除赋值重复吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18430671/

相关文章:

并行任务中的 C++ OpenMP 变量可见性

c++ - C++ 类中的线程

python - 使用 Tensorflow 优化 python 中的函数

python - 如何有效地将 NumPy View 列表与相应的权重相乘?

optimization - 在 forall 循环中使用用户定义的函数

python - 为什么LLVM在创建数组时会抛出 "arguments of incompatible type"错误?

assembly - 在移动垃圾收集实现中,内存引用是如何定位的?

c++ - 如何从 C++ 中的文本文件的开头删除字符 ""?

linux - 我可以输入优化编译器进行功效研究的任何自定义任务吗?

c++ - 五子棋(5 合一行)计算机逻辑