我没有 ISA 设计经验。我一直在读https://riscv.org/specifications/第 2 章,第 21 页。
有人可以解释为什么 RISC-V 有使用立即数的算术和逻辑指令,例如 ADDI 和 XORI,但没有类似的条件分支指令,例如 BLTI、BEQI 等。
(其中B
ranch L
ess T
han I
mmediate会将寄存器与常量进行比较并分支如果更少的话。)
我不知情的观点是,BLTI 经常用于 C 中的固定长度循环,例如:
for (int i = 0; i < 16; i++) {
...
}
为什么算术和逻辑指令比分支指令更值得立即变体?
最佳答案
分支已经需要将分支目标偏移量编码为立即数,在其中安装两个立即操作数会更困难。将它们做得更小可以使它们更适合,但也会降低指令的实用性。
这样的分支偶尔会有用,但在我看来,您高估了它的用处:在典型的循环中,不需要直接将循环计数器与其边界值进行比较,实际上,大多数循环变量甚至都没有将其放入编译后的代码。作为一个小示例(使用更高的计数来避免循环的完全展开),
int test(int *data) {
int sum = 0;
for (int i = 0; i < 255; i++)
sum += data[i];
return sum;
}
由 Clang 编译为:
test(int*): # @test(int*)
addi a2, zero, 1020
mv a3, zero
mv a1, zero
.LBB0_1: # =>This Inner Loop Header: Depth=1
add a4, a0, a3
lw a4, 0(a4)
add a1, a4, a1
addi a3, a3, 4
bne a3, a2, .LBB0_1
mv a0, a1
ret
Clang 在这里所做的是计算最终的地址,然后循环直到到达该地址,从而删除循环计数器。
这是一个有点特殊的情况,但也有其他技巧。例如,在许多情况下,循环退出测试可以转换为当寄存器递减至零时退出的循环,这很容易测试,因为 RISCV 有 bnez。如果需要,原始循环计数器可以与循环计数器共存(不参与循环退出测试),或者如果可能的话它可以再次消失。
关于assembly - 为什么RV32I包含ADDI和XORI等指令而不包含BLTI?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51810450/