GCC 会优化内联访问器吗?
Will GCC optimize away an inline accessor?
假设我有这个class
class Point
{
inline float x() const { return v[0]; }
inline float y() const { return v[1]; }
inline float z() const { return v[2]; }
float v[3];
};
我也是:
Point myPoint;
myPoint[0] = 5;
// unrelated code goes here
float myVal = myPoint.x() + 5;
-O2
或 -O3
上的 GCC 是否会优化掉对 x()
的任何调用而只获取 v[0]
?即:
float myVal = myPoint.v[0] + 5;
或者为什么这是不可能的?
更新:应该提到我确实意识到 inline
比其他任何东西都更像是对编译器的建议,但无论如何我都想知道。
作为附加问题,将此模板化 class 会对可以完成的优化产生任何影响吗?
您可以在此处观察差异:https://godbolt.org/
假设您有此代码(您的代码无法编译:缺少 ;
并且 Point
没有 []
):
struct Point
{
inline float x() const { return v[0]; }
inline float y() const { return v[1]; }
inline float z() const { return v[2]; }
float v[3];
};
int main() {
Point myPoint;
myPoint.v[0] = 5;
float myVal = myPoint.x() + 5;
return myVal;
}
Point::x() const:
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
mov rax, QWORD PTR [rbp-8]
movss xmm0, DWORD PTR [rax]
pop rbp
ret
main:
push rbp
mov rbp, rsp
sub rsp, 16
movss xmm0, DWORD PTR .LC0[rip]
movss DWORD PTR [rbp-16], xmm0
lea rax, [rbp-16]
mov rdi, rax
call Point::x() const
movss xmm1, DWORD PTR .LC0[rip]
addss xmm0, xmm1
movss DWORD PTR [rbp-4], xmm0
movss xmm0, DWORD PTR [rbp-4]
cvttss2si eax, xmm0
leave
ret
.LC0:
.long 1084227584
我不太精通汇编程序,但我认为将上面的内容与 the output with -O3
进行比较就足够有说服力了:
main:
mov eax, 10
ret
The generated code can vary dramatically depending on the context, I just wanted to know if there was any fundamental reasons it could never or would always happen.
上面的例子已经反驳了"never"。 "Always",却难求。您得到的保证是生成的代码的行为就像编译器在没有应用优化的情况下翻译您的代码一样。除了少数例外,通常不能保证优化。可以肯定的是,我只会依赖于查看现实场景中的编译器输出。
它可能内联也可能不内联。那里没有保证。但是,如果您希望它始终内联,请使用 [[gnu::always_inline]]
属性。请参阅文档 here。仅当您知道自己在做什么时才使用此属性。在大多数情况下,最好让编译器决定适合的优化。
Will GCC optimize away an inline accessor?
所有优化编译器都会这样做。与其他优化相比,这是一个微不足道的优化。
Or is there a reason why this is impossible?
没有理由不可能,但也没有保证。
As an additional question, will templating this class have any effect on the optimizations that can be done?
没有。但是,当然,编译器可能有不同的模板内联阈值。
假设我有这个class
class Point
{
inline float x() const { return v[0]; }
inline float y() const { return v[1]; }
inline float z() const { return v[2]; }
float v[3];
};
我也是:
Point myPoint;
myPoint[0] = 5;
// unrelated code goes here
float myVal = myPoint.x() + 5;
-O2
或 -O3
上的 GCC 是否会优化掉对 x()
的任何调用而只获取 v[0]
?即:
float myVal = myPoint.v[0] + 5;
或者为什么这是不可能的?
更新:应该提到我确实意识到 inline
比其他任何东西都更像是对编译器的建议,但无论如何我都想知道。
作为附加问题,将此模板化 class 会对可以完成的优化产生任何影响吗?
您可以在此处观察差异:https://godbolt.org/
假设您有此代码(您的代码无法编译:缺少 ;
并且 Point
没有 []
):
struct Point
{
inline float x() const { return v[0]; }
inline float y() const { return v[1]; }
inline float z() const { return v[2]; }
float v[3];
};
int main() {
Point myPoint;
myPoint.v[0] = 5;
float myVal = myPoint.x() + 5;
return myVal;
}
Point::x() const:
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
mov rax, QWORD PTR [rbp-8]
movss xmm0, DWORD PTR [rax]
pop rbp
ret
main:
push rbp
mov rbp, rsp
sub rsp, 16
movss xmm0, DWORD PTR .LC0[rip]
movss DWORD PTR [rbp-16], xmm0
lea rax, [rbp-16]
mov rdi, rax
call Point::x() const
movss xmm1, DWORD PTR .LC0[rip]
addss xmm0, xmm1
movss DWORD PTR [rbp-4], xmm0
movss xmm0, DWORD PTR [rbp-4]
cvttss2si eax, xmm0
leave
ret
.LC0:
.long 1084227584
我不太精通汇编程序,但我认为将上面的内容与 the output with -O3
进行比较就足够有说服力了:
main:
mov eax, 10
ret
The generated code can vary dramatically depending on the context, I just wanted to know if there was any fundamental reasons it could never or would always happen.
上面的例子已经反驳了"never"。 "Always",却难求。您得到的保证是生成的代码的行为就像编译器在没有应用优化的情况下翻译您的代码一样。除了少数例外,通常不能保证优化。可以肯定的是,我只会依赖于查看现实场景中的编译器输出。
它可能内联也可能不内联。那里没有保证。但是,如果您希望它始终内联,请使用 [[gnu::always_inline]]
属性。请参阅文档 here。仅当您知道自己在做什么时才使用此属性。在大多数情况下,最好让编译器决定适合的优化。
Will GCC optimize away an inline accessor?
所有优化编译器都会这样做。与其他优化相比,这是一个微不足道的优化。
Or is there a reason why this is impossible?
没有理由不可能,但也没有保证。
As an additional question, will templating this class have any effect on the optimizations that can be done?
没有。但是,当然,编译器可能有不同的模板内联阈值。