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

Assembly 为什么clang使用这个长代码序列来构建64位常量?,assembly,clang,64-bit,llvm,riscv,Assembly,Clang,64 Bit,Llvm,Riscv,来源: unsigned long div1000(unsigned long a) { return a/1000; } 优化代码(-O3): 参考: 我们可以使用lui/addi对构建一个32位常量,那么为什么不构建2 x 32位常量并将它们放在一起呢。这将需要另一个寄存器,但指令更少 lui a1, ? # addi a1, a1, ? # slli a1, a1, 32 # 6 instruction seque

来源:

unsigned long div1000(unsigned long a)
{
    return a/1000;
}
优化代码(-O3):

参考:

我们可以使用
lui
/
addi
对构建一个32位常量,那么为什么不构建2 x 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上的
lui
产生一个32位常量,该常量被符号扩展为32位。因此,我们必须使用正常的技巧,在
a1
中创建高阶常量,将其关闭1,以抵消
a2
中的负值。

听起来像是一个遗漏的优化错误,您应该对此进行报告。RISC-V足够新,LLVM没有实现代码来查找每个窥视孔优化也就不足为奇了;也许没人想到,或者那只是一个没有RISC-V窥视孔的通用LLVM模式。
lui
addi
slli 16
addi
slli 16
addi
也应该可以工作,并且在6条指令中不使用额外寄存器来完成。@Martinoseau,与MIPS不同,RISC V
addi
只有一个12位的立即数(
lui
有20位),因此这是一个更好的序列,但只适用于某些常量。@MartinRosenau:具有较少ILP的序列,是一个依赖链。如果你有备用寄存器,最好多用LUI,少用ADDI。对不起,我没有正确读取标签。出于某种原因,我认为这是关于MIPS-64的…听起来像是一个遗漏的优化错误,你应该报告。RISC-V足够新,LLVM没有实现代码来查找每个窥视孔优化也就不足为奇了;也许没人想到,或者那只是一个没有RISC-V窥视孔的通用LLVM模式。
lui
addi
slli 16
addi
slli 16
addi
也应该可以工作,并且在6条指令中不使用额外寄存器来完成。@Martinoseau,与MIPS不同,RISC V
addi
只有一个12位的立即数(
lui
有20位),因此这是一个更好的序列,但只适用于某些常量。@MartinRosenau:具有较少ILP的序列,是一个依赖链。如果你有备用寄存器,最好多用LUI,少用ADDI。对不起,我没有正确读取标签。出于某种原因,我想这是关于MIPS-64的。。。
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         #