以下代码可以在amd64上使用gcc或clang进行编译:
作为按位
由于编译器对于所有操作都将
CPU的寄存器重命名功能是否没有成本,并且始终在amd64上可��,那么为什么编译器会像这样编译代码呢?
更新:
我发现如果向gcc传递更高的tree-assoc-width值,则它可以执行预期的依赖关系链断开。
// gcc -O2 file.c -c
int f(int a, int b, int c, int d)
{
return a & b & c & d;
}
生成以下汇编代码:
0000000000000000 <f>:
0: 89 d0 mov %edx,%eax
2: 21 c8 and %ecx,%eax
4: 21 f0 and %esi,%eax
6: 21 f8 and %edi,%eax
8: c3 retq
作为按位
and
应该是可结合的,我们可以假设将成对累加进两个寄存器中,然后and
这两个寄存器会更有效率。这将打破依赖关系,并允许在具有多个ALU的CPU上进行并行执行。由于编译器对于所有操作都将
and
放入相同的寄存器中,我认为它依赖于CPU能够进行寄存器重命名以自行打破依赖关系。CPU的寄存器重命名功能是否没有成本,并且始终在amd64上可��,那么为什么编译器会像这样编译代码呢?
更新:
我发现如果向gcc传递更高的tree-assoc-width值,则它可以执行预期的依赖关系链断开。
--param tree-reassoc-width=2
eax
的值取决于前一条指令。因此,无论CPU如何重命名变量,它都不能并行地执行这些指令。 - Mysticial