为什么编译器不能最佳地调度或消除指令?

时间:2013-04-22 15:05:48

标签: c++ gcc compiler-optimization

我想知道编译器在优化结构分配方面做得有多好,我做了一些测试,结果令人惊讶。 (我想向GCC提出这个问题。)

特别是我正在查看汇编程序GCC 4.6.3(-O3)(编辑:我还包括GCC 4.8.0的输出)产生以下代码:

template<class T>
struct C
{
  T F[3];
  C(){}
  C(const T& t0,const T& t1,const T& t2): F{{t0},{t1},{t2}} {}
};

template<class T>
__attribute__((always_inline))
C<T>
operator+( const C<T>& l , const C<T>& r )
{
  return C<T>( l.F[0] + r.F[0] , 
           l.F[1] + r.F[1] , 
           l.F[2] + r.F[2] );
}

int main() 
{
  C<C<C<float> > > a,b,c;

  a=b+c;

  printf("%s",(const char*)&a);
}

这里是汇编程序:

movss   264(%rsp), %xmm0
leaq    48(%rsp), %rbx
leaq    156(%rsp), %rbp
addss   376(%rsp), %xmm0
movss   %xmm0, 4(%rsp)

movss   260(%rsp), %xmm0
addss   372(%rsp), %xmm0
movss   %xmm0, 8(%rsp)

movss   256(%rsp), %xmm0
addss   368(%rsp), %xmm0
movss   %xmm0, 12(%rsp)

movss   252(%rsp), %xmm0
addss   364(%rsp), %xmm0
movss   %xmm0, 16(%rsp)

movss   248(%rsp), %xmm0
addss   360(%rsp), %xmm0
movss   %xmm0, 20(%rsp)

movss   244(%rsp), %xmm0
addss   356(%rsp), %xmm0
movss   %xmm0, 24(%rsp)

movss   240(%rsp), %xmm0
addss   352(%rsp), %xmm0
movss   %xmm0, 28(%rsp)

movss   236(%rsp), %xmm0
addss   348(%rsp), %xmm0
movss   %xmm0, 32(%rsp)

movss   232(%rsp), %xmm0
addss   344(%rsp), %xmm0
movss   %xmm0, 36(%rsp)

movss   228(%rsp), %xmm0
addss   340(%rsp), %xmm0
movss   %xmm0, 40(%rsp)

movss   224(%rsp), %xmm0
addss   336(%rsp), %xmm0
movss   %xmm0, 44(%rsp)    // 11-th

movss   220(%rsp), %xmm0
movss   164(%rsp), %xmm14
movss   160(%rsp), %xmm15
addss   332(%rsp), %xmm0
addss   272(%rsp), %xmm15
movss   216(%rsp), %xmm1
addss   276(%rsp), %xmm14
movss   212(%rsp), %xmm2
movss   208(%rsp), %xmm3
addss   328(%rsp), %xmm1
movss   204(%rsp), %xmm4
addss   324(%rsp), %xmm2
movss   200(%rsp), %xmm5
addss   320(%rsp), %xmm3
movss   196(%rsp), %xmm6
addss   316(%rsp), %xmm4
movss   192(%rsp), %xmm7
addss   312(%rsp), %xmm5
movss   188(%rsp), %xmm8
addss   308(%rsp), %xmm6
movss   184(%rsp), %xmm9
addss   304(%rsp), %xmm7
movss   180(%rsp), %xmm10
addss   300(%rsp), %xmm8
movss   176(%rsp), %xmm11
addss   296(%rsp), %xmm9
movss   172(%rsp), %xmm12
addss   292(%rsp), %xmm10
movss   168(%rsp), %xmm13
addss   288(%rsp), %xmm11
addss   284(%rsp), %xmm12
movss   %xmm15, 384(%rsp)
addss   280(%rsp), %xmm13  // all 27 floats added
movss   %xmm14, 388(%rsp)
movss   %xmm0, 444(%rsp)
movss   44(%rsp), %xmm0
movss   %xmm0, 448(%rsp)
movss   40(%rsp), %xmm0
movss   %xmm0, 452(%rsp)
movss   36(%rsp), %xmm0
movss   %xmm0, 456(%rsp)
movss   32(%rsp), %xmm0
movss   %xmm0, 460(%rsp)
movss   28(%rsp), %xmm0
movss   %xmm0, 464(%rsp)
movss   24(%rsp), %xmm0
movss   %xmm0, 468(%rsp)
movss   20(%rsp), %xmm0
movss   %xmm0, 472(%rsp)
movss   16(%rsp), %xmm0
movss   %xmm0, 476(%rsp)
movss   12(%rsp), %xmm0
movss   %xmm0, 480(%rsp)
movss   8(%rsp), %xmm0
movss   %xmm13, 392(%rsp)
movss   %xmm12, 396(%rsp)
movss   %xmm11, 400(%rsp)
movss   %xmm10, 404(%rsp)
movss   %xmm9, 408(%rsp)
movss   %xmm8, 412(%rsp)
movss   %xmm7, 416(%rsp)
movss   %xmm6, 420(%rsp)
movss   %xmm5, 424(%rsp)
movss   %xmm4, 428(%rsp)
movss   %xmm3, 432(%rsp)
movss   %xmm2, 436(%rsp)
movss   %xmm1, 440(%rsp)
movss   %xmm0, 484(%rsp)  // Storing of temporary finished
movq    384(%rsp), %rax   // Now begin copy temporary to destination
movss   4(%rsp), %xmm0
movss   %xmm0, 488(%rsp)
movq    %rax, 48(%rsp)
movq    392(%rsp), %rax
movq    %rax, 56(%rsp)
movq    400(%rsp), %rax
movq    %rax, 64(%rsp)
movq    408(%rsp), %rax
movq    %rax, 72(%rsp)
movq    416(%rsp), %rax
movq    %rax, 80(%rsp)
movq    424(%rsp), %rax
movq    %rax, 88(%rsp)
movq    432(%rsp), %rax
movq    %rax, 96(%rsp)
movq    440(%rsp), %rax
movq    %rax, 104(%rsp)
movq    448(%rsp), %rax
movq    %rax, 112(%rsp)
movq    456(%rsp), %rax
movq    %rax, 120(%rsp)
movq    464(%rsp), %rax
movq    %rax, 128(%rsp)
movq    472(%rsp), %rax
movq    %rax, 136(%rsp)
movq    480(%rsp), %rax
movq    %rax, 144(%rsp)
movl    488(%rsp), %eax
movl    %eax, 152(%rsp)  // Whole struct copied
.p2align 4,,10

汇编程序显示从指定行开始的整个(嵌套)结构的附加副本。有人可能会说这是因为编译器必须发出作业(与可以省略的副本相反)。

我重复了实验,这次我没有使用3次嵌套结构而是使用2次嵌套结构。然后附加副本不会发生。这是第二个实验的代码:

int main() 
{
  C<C<float> > a,b,c;

  a=b+c;

  printf("%s",(const char*)&a);
}

汇编程序:

    movss   80(%rsp), %xmm0
    movq    %rsp, %rdx
    movss   76(%rsp), %xmm1
    addss   128(%rsp), %xmm0
    movss   72(%rsp), %xmm2
    addss   124(%rsp), %xmm1
    movss   68(%rsp), %xmm3
    addss   120(%rsp), %xmm2
    movss   64(%rsp), %xmm4
    addss   116(%rsp), %xmm3
    movss   60(%rsp), %xmm5
    addss   112(%rsp), %xmm4
    movss   56(%rsp), %xmm6
    addss   108(%rsp), %xmm5
    movss   52(%rsp), %xmm7
    addss   104(%rsp), %xmm6
    movss   48(%rsp), %xmm8
    addss   100(%rsp), %xmm7
    addss   96(%rsp), %xmm8
    xorl    %eax, %eax
    movss   %xmm2, 24(%rsp)
    movss   %xmm3, 20(%rsp)
    movss   %xmm4, 16(%rsp)
    movss   %xmm5, 12(%rsp)
    movss   %xmm6, 8(%rsp)
    movss   %xmm7, 4(%rsp)
    movss   %xmm8, (%rsp)
    movss   %xmm1, 28(%rsp)
    movss   %xmm0, 32(%rsp)

很明显,临时结构(保存b+c的结果)可以完全分配到寄存器文件(9寄存器,xmm0-xmm8)中,然后存储而不复制它。

但是,操作(添加+赋值)仅对在存储容器上运行的指令构成弱数据依赖性。我要问的问题是:在第一个实验中,由于数据依赖性将允许指令的最佳调度,为什么编译器不以不需要附加副本的方式调度指令,即直接存储结果进入最终的内存地址?是否存在编译器无法查看的依赖性或边界的某些方面,并且有效地阻碍了这种优化?

编辑:

这里的汇编程序是从GCC 4.8.0(-std = c ++ 0x -S -O3)生成的:

movss   264(%rsp), %xmm0
leaq    48(%rsp), %rdx
movss   260(%rsp), %xmm1
addss   376(%rsp), %xmm0
movss   256(%rsp), %xmm2
addss   372(%rsp), %xmm1
movss   252(%rsp), %xmm3
addss   368(%rsp), %xmm2
movss   248(%rsp), %xmm4
addss   364(%rsp), %xmm3
movss   244(%rsp), %xmm5
addss   360(%rsp), %xmm4
addss   356(%rsp), %xmm5
movss   196(%rsp), %xmm11
addss   308(%rsp), %xmm11
movss   %xmm0, 4(%rsp)
movss   %xmm1, 8(%rsp)
movss   %xmm2, 12(%rsp)
movss   %xmm3, 16(%rsp)
movss   %xmm4, 20(%rsp)
movss   %xmm5, 24(%rsp)
movss   240(%rsp), %xmm0
movss   236(%rsp), %xmm1
movss   232(%rsp), %xmm2
addss   352(%rsp), %xmm0
movss   228(%rsp), %xmm3
addss   348(%rsp), %xmm1
movss   224(%rsp), %xmm4
addss   344(%rsp), %xmm2
movss   220(%rsp), %xmm5
addss   340(%rsp), %xmm3
movss   216(%rsp), %xmm6
addss   336(%rsp), %xmm4
movss   212(%rsp), %xmm7
addss   332(%rsp), %xmm5
movss   208(%rsp), %xmm8
addss   328(%rsp), %xmm6
movss   204(%rsp), %xmm9
addss   324(%rsp), %xmm7
movss   200(%rsp), %xmm10
addss   320(%rsp), %xmm8
addss   316(%rsp), %xmm9
addss   312(%rsp), %xmm10
movss   %xmm11, 28(%rsp)
movss   192(%rsp), %xmm12
movss   188(%rsp), %xmm13
movss   184(%rsp), %xmm14
addss   304(%rsp), %xmm12
movss   180(%rsp), %xmm15
addss   300(%rsp), %xmm13
addss   296(%rsp), %xmm14
movss   176(%rsp), %xmm11
addss   292(%rsp), %xmm15
addss   288(%rsp), %xmm11
movss   %xmm12, 32(%rsp)
movss   %xmm13, 36(%rsp)
movss   %xmm14, 40(%rsp)
movss   %xmm15, 44(%rsp)
movss   172(%rsp), %xmm12
movss   168(%rsp), %xmm13
movss   164(%rsp), %xmm14
addss   284(%rsp), %xmm12
movss   160(%rsp), %xmm15
addss   280(%rsp), %xmm13
addss   276(%rsp), %xmm14
movss   %xmm11, 400(%rsp)
addss   272(%rsp), %xmm15
movss   %xmm12, 396(%rsp)
movss   %xmm13, 392(%rsp)
movss   %xmm14, 388(%rsp)
movss   36(%rsp), %xmm13
movss   40(%rsp), %xmm14
movss   %xmm15, 384(%rsp)
movss   32(%rsp), %xmm12
movss   44(%rsp), %xmm15
movss   %xmm15, 404(%rsp)
movss   %xmm14, 408(%rsp)
movss   %xmm13, 412(%rsp)
movss   %xmm12, 416(%rsp)
movq    384(%rsp), %rax
movss   28(%rsp), %xmm11
movss   %xmm11, 420(%rsp)
movq    %rax, 48(%rsp)
movq    392(%rsp), %rax
movss   %xmm5, 444(%rsp)
movss   %xmm4, 448(%rsp)
movss   24(%rsp), %xmm5
movq    %rax, 56(%rsp)
movss   %xmm3, 452(%rsp)
movq    400(%rsp), %rax
movss   20(%rsp), %xmm4
movss   16(%rsp), %xmm3
movss   %xmm2, 456(%rsp)
movq    %rax, 64(%rsp)
movq    408(%rsp), %rax
movss   %xmm1, 460(%rsp)
movss   12(%rsp), %xmm2
movss   8(%rsp), %xmm1
movq    %rax, 72(%rsp)
movq    416(%rsp), %rax
movss   %xmm0, 464(%rsp)
movss   4(%rsp), %xmm0
movss   %xmm10, 424(%rsp)
movss   %xmm9, 428(%rsp)
movss   %xmm8, 432(%rsp)
movss   %xmm7, 436(%rsp)
movss   %xmm6, 440(%rsp)
movss   %xmm5, 468(%rsp)
movss   %xmm4, 472(%rsp)
movss   %xmm3, 476(%rsp)
movss   %xmm2, 480(%rsp)
movss   %xmm1, 484(%rsp)
movss   %xmm0, 488(%rsp)
movq    %rax, 80(%rsp)
movq    424(%rsp), %rax
movq    %rax, 88(%rsp)
movq    432(%rsp), %rax
movq    %rax, 96(%rsp)
movq    440(%rsp), %rax
movq    %rax, 104(%rsp)
movq    448(%rsp), %rax
movq    %rax, 112(%rsp)
movq    456(%rsp), %rax
movq    %rax, 120(%rsp)
movq    464(%rsp), %rax
movq    %rax, 128(%rsp)
movq    472(%rsp), %rax
movq    %rax, 136(%rsp)
movq    480(%rsp), %rax
movq    %rax, 144(%rsp)
movl    488(%rsp), %eax
movl    %eax, 152(%rsp)

附加副本仍在那里。

0 个答案:

没有答案