[英]Do C++ compilers eliminate assignment duplications?
如果我有一个示例函数,如:
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,它通常仅限于:
一些例子:
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
指定允许与硬件交互,因此编译器无法先验地知道硬件是否会读取或写入程序后面的变量。
另一个特例:出于优化的目的,多线程程序中使用的内存同步操作(围栏,障碍等)也可以防止这种优化。 这是因为,就像在volatile
情况下一样,同步意味着另一个执行线程可能已经修改了该线程后面的变量。
最后,像所有优化一样,它的有效性在很大程度上取决于对环境的了解。 如果证明opaque
既不读取也不写入xa
,则可以优化一些存储(如果编译器可以检查opaque
的定义,则可证明),因此通常它实际上取决于内联和常量传播。
一个体面的编译器应该在这种特定情况下删除它们
完成完整的编译示例
struct Foo {
float m_a, m_b, m_c;
bool m_isValid;
void setA(float a){ m_a = a; m_isValid = false; }
void setB(float b){ m_b = b; m_isValid = false; }
void setC(float c){ m_c = c; m_isValid = false; }
void func1(float a, float b, float c);
};
Foo f;
void func1(float a, float b, float c)
{
f.setA(a);
f.setB(b);
f.setC(c);
}
在这种情况下,g ++将func1
编译为
_Z5func1fff:
.LFB3:
.cfi_startproc
movl 4(%esp), %eax ;; loads a
movb $0, f+12 ;; clears m_isValid
movl %eax, f ;; stores m_a
movl 8(%esp), %eax ;; loads b
movl %eax, f+4 ;; stores m_b
movl 12(%esp), %eax ;; loads c
movl %eax, f+8 ;; stores m_c
ret
.cfi_endproc
请注意,如果性能是一个问题,你应该留意如何设计一个程序,但在测量代码实际上在哪里失去时间后,最好在最后完成这种微观级别的优化。
大多数现代编译器(启用了优化选项)都应该成功!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.