代码之家  ›  专栏  ›  技术社区  ›  Erik Eidt

为什么clang使用这个长代码序列来构建一个64位常量?

  •  1
  • Erik Eidt  · 技术社区  · 6 年前

    来源:

    unsigned long div1000(unsigned long a)
    {
        return a/1000;
    }
    

    优化代码(-O3):

        srli    a0, a0, 3           # divide parameter by 8
    
        lui     a1, 4194            #
        addiw   a1, a1, 1245        #
        slli    a1, a1, 13          #
        addi    a1, a1, 1507        #  8 instruction sequence to assemble a rather large number
        slli    a1, a1, 12          #
        addi    a1, a1, 1343        #
        slli    a1, a1, 12          #
        addi    a1, a1, 1999        #
    
        mulhu   a0, a0, a1          # multiply by large number and fetch high portion
        srli    a0, a0, 4           # divide by 16
        ret
    

    参考: https://godbolt.org/z/mNNSM5

    我们可以使用 lui / addi pair,那么为什么不构建2个32位常量并将它们放在一起呢。这将需要另一个寄存器,但指令更少。

    lui  a1, ?              # 
    addi a1, a1, ?          #
    slli a1, a1, 32         #  6 instruction sequence to assemble a 64-bit number
    lui  a2, ?              #
    addi a2, a2, ?          #
    add  a1, a1, a2         #
    

    (注意,在32位低位常数设置高位(MSB)的情况下(如这里),我假设 路易斯 在64位RISC V上产生一个32位常数,该常数被符号扩展为32位。因此,我们必须使用正常的技巧来创建高阶常数 a1 减1以抵消中的负值 a2 .)

    0 回复  |  直到 6 年前
    推荐文章