6 compiler-construction assembly compilation compiler-optimization
我知道编译器可以有很多前端.每个前端都将用编程语言编写的代码转换为内部数据结构.
然后在该数据结构内部,编译器进行一些优化.
然后,编译器的BACK-END将该数据结构转换为汇编代码,然后在汇编阶段将汇编代码转换为目标代码.
我的问题如下.
考虑到任何编程语言都被翻译成内部数据结构的事实,编译器输出的最终代码对于相同的程序逻辑是否相同,但对于不同的编程语言?
是的,这很可能.但语言之间的微妙差异可能会导致与看起来相似的来源不同.前端很少会为后端提供完全相同的输入.它最终可能会针对简单的功能进行优化,并且通常会使用相同类型的策略.(例如,在x86上,有多少LEA指令值得使用而不是乘法.)
例如,在C中,有符号溢出是未定义的行为,所以
void foo(int *p, int n) {
    for (int i = 0; i <= n ; i++) {
         p[i] = i/4;
     }
}
可以假设最终终止所有可能的n(包括INT_MAX),并且i为非负的.
对于语言的前端,i++定义为具有2的补语环绕(或gcc with -fwrapv -fno-strict-overflow),总是i会从==INT_MAX大的负数转变为<= INT_MAX.编译器需要使asm能够忠实地实现源代码的行为,即使对于传递的调用者来说也是如此n == INT_MAX,这使得这是一个无限循环,i可能是负面的.
但由于这是C和C++中的Undefined Behavior,编译器可以假设程序不包含任何UB,因此没有调用者可以通过INT_MAX.它可以假设i循环内部从不为负,并且循环行程计数适合于a int.另请参阅每个C程序员应该了解的未定义行为(clang blog).
非负假设允许它i / 4以简单的右移实现,而不是为负数实现C整数除法语义.
# the p[i] = i/4;  part of the inner loop from
# gcc -O3  -fno-tree-vectorize
    mov     edx, eax                        # copy the loop counter
    sar     edx, 2                          # i / 4 == i>>2
    mov     DWORD PTR [rdi+rax*4], edx      # store into the array
Godbolt编译器资源管理器上的 Source + asm输出.
但是如果签名环绕是定义的行为,则常量的带符号除法需要更多指令,并且数组索引必须考虑可能的包装:
# Again *just* the body of the inner loop, without the loop overhead
# gcc -fno-strict-overflow -fwrapv    -O3 -fno-tree-vectorize
    test    eax, eax           # set flags (including SF) according to i
    lea     edx, [rax+3]       # edx = i+3
    movsx   rcx, eax           # sign-extend for use in the addressing mode
    cmovns  edx, eax           # copy if !signbit_set(i)
    sar     edx, 2             # i/4 = i>=0 ? i>>2 : (i+3)>>2;
    mov     DWORD PTR [rdi+rcx*4], edx
C数组索引语法只是指针+整数的糖,并不要求索引是非负的.因此调用者将指针传递到4GB数组的中间是有效的,该函数最终必须写入该数组.(无限循环也是有问题的,但是NVM那个.)
如您所见,语言规则的微小差异要求编译器不进行优化.语言规则之间的差异通常大于ISO C++与g ++可以实现的C++的定义签名环绕风格之间的差异.
此外,如果"通常"类型在另一种语言中具有不同的宽度或签名,则后端很可能会获得不同的输入,并且在某些情况下这将很重要.
如果我已经使用过unsigned,那么回绕将是C和C++中定义的溢出行为.但是unsigned根据定义,类型是非负的,因此在不展开的情况下,环绕的可能性不会对优化产生如此明显的影响.如果循环从大于零开始,则环绕引入了返回的可能性0,以防重要(例如,x / i除以零).
| 归档时间: | 
 | 
| 查看次数: | 197 次 | 
| 最近记录: |