零/符号扩展是无操作,为什么然后为每种大小类型的指令?

yud*_*dre 2 assembly sign-extension riscv zero-extension

对于x86和x64编译器,生成类似的零/符号扩展MOVSX和MOVZX.扩展本身并不是免费的,但允许处理器执行无序魔术加速.

但是在RISC-V上:

因此,无符号和带符号的32位整数之间的转换是无操作,从有符号的32位整数到带符号的64位整数的转换也是如此.

添加和移位需要一些新指令(ADD [I] W/SUBW/SxxW)以确保32位值的合理性能.

(C)RISC-V Spec

但与此同时,新的现代RISC-V 64位处理器包含32位有符号整数的指令.为什么?提高性能?那么8位和16位呢?我已经什么都不懂了.

Mar*_*oom 6

完整的引用对我来说似乎很清楚:

编译器和调用约定保持一个不变量,即所有32位值都以64位寄存器中的符号扩展格式保存.甚至32位无符号整数也将位31扩展为位63到32.

因此,无符号和带符号的32位整数之间的转换是无操作,从有符号的32位整数到带符号的64位整数的转换也是如此.
现有的64位宽SLTU和无符号分支比较在此不变量下仍可在无符号32位整数上正确运行.
类似地,32位符号扩展整数上的现有64位宽逻辑运算保留了符号扩展属性.

添加和移位需要一些新指令(ADD [I] W/SUBW/SxxW)以确保32位值的合理性能.

它表示32位值存储在64位寄存器中,其MSb(最高有效位)通过位32-63重复.
这是针对符号和无符号整数完成的.

这允许一些优化,如引用中所述:

  • 未签名的< - >签名转换是免费的.
    将此与通常的算法进行比较,您必须将零或符号扩展为低32位值,以将其提升为不同"符号"的64位值(忽略溢出).
  • 有符号32位< - >有符号64位是免费的.
    这节省了标志扩展.
  • 分支和设置说明仍然有效.
    这是因为重复MSb不会改变比较结果.
  • 逻辑64位操作保留了这个属性
    在几个例子之后很容易看到这个.

但是,添加(名称为1)不会保留此不变量:0x000000007fffffff + 0x0000000000000001 = 0x0000000080000000,这违反了该假设.

因为a)经常使用32位值并且b)修复结果需要额外的工作(我可以想到使用slli/ sraipair)已经引入了新格式的指令.
这些指令在64位寄存器上运行,但仅使用其较低的32位值,并将对32位结果进行符号扩展.
这很容易在硬件中完成,所以值得拥有这种新的指令.

正如评论中所指出的那样,8位和16位算术很少见,因此没有花费任何工程努力为它寻找新的空间(无论是在所需的门数还是所使用的操作码空间方面).