现代编译器是否优化仅引用对象子集的局部变量?

时间:2018-07-12 22:15:48

标签: c++ performance compiler-optimization

大多数现代编译器最终是否会优化以下代码,从而使多余的指令不用于对象inner

func Test(TypeObject *object):
  InnerTypedObject *inner = object->inner
  print(inner->a)
  print(inner->b)
  print(inner->c)

我认为编译器将能够确定inner->aobject->inner.a指的是同一件事,因此它将避免完全分配inner。我认为局部变量可能保存在寄存器中,所以我并不真正在意性能。主要是想知道我们是否会获得相同的生成的机器代码。

1 个答案:

答案 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 -它存储一次指针,然后像原始代码一样使用它三次。无法更好地对其进行优化的原因是,指针中存储的内容极难跟踪,因此优化器必须假设它不确定是否知道其中的内容。

即使汇编的两个位具有相同数量的指令,在带有“内部”的指令中也存在额外的内存取消引用,因此如果数据不在缓存中,则可能会很昂贵。