大多数现代编译器最终是否会优化以下代码,从而使多余的指令不用于对象inner
?
func Test(TypeObject *object):
InnerTypedObject *inner = object->inner
print(inner->a)
print(inner->b)
print(inner->c)
我认为编译器将能够确定inner->a
和object->inner.a
指的是同一件事,因此它将避免完全分配inner
。我认为局部变量可能保存在寄存器中,所以我并不真正在意性能。主要是想知道我们是否会获得相同的生成的机器代码。
答案 0 :(得分:5)
感谢杰里·科芬(Jerry Coffin)的评论-我原来的回答实际上是错误的...
对于此代码:
struct TypeObject {
int a;
int b;
int c;
};
void print(int x);
void test(TypeObject *object) {
print(object->a);
print(object->b);
print(object->c);
}
https://godbolt.org/g/SrNWkp会产生以下内容:
test(TypeObject*):
push rbx // save the rbx register
mov rbx, rdi // copy the parameter (which is "object") to rbx
mov edi, DWORD PTR [rbx] // copy inner->a to edi
call print(int)
mov edi, DWORD PTR [rbx+4] // copy inner->b to edi
call print(int)
mov edi, DWORD PTR [rbx+8] // copy inner->c to edi
jmp print(int)
pop rbx // restore rbx
对于此代码:
struct InnerTypedObject {
int a;
int b;
int c;
};
struct TypeObject {
InnerTypedObject * inner;
};
void print(int x);
void test(TypeObject *object) {
InnerTypedObject *inner = object->inner;
print(inner->a);
print(inner->b);
print(inner->c);
}
https://godbolt.org/g/NC2pa3会产生以下内容:
test(TypeObject*):
push rbx // save the rbx register
mov rbx, QWORD PTR [rdi] // copy "*object" (which is "inner") to rbx
mov edi, DWORD PTR [rbx] // copy inner->a to edi
call print(int)
mov edi, DWORD PTR [rbx+4] // copy inner->b to edi
call print(int)
mov edi, DWORD PTR [rbx+8] // copy inner->c to edi
jmp print(int)
pop rbx // restore rbx
因此代码仍在取消引用object
-它存储一次指针,然后像原始代码一样使用它三次。无法更好地对其进行优化的原因是,指针中存储的内容极难跟踪,因此优化器必须假设它不确定是否知道其中的内容。
即使汇编的两个位具有相同数量的指令,在带有“内部”的指令中也存在额外的内存取消引用,因此如果数据不在缓存中,则可能会很昂贵。