简体   繁体   中英

Why does RV32I include instructions like ADDI and XORI but not BLTI?

I'm not experienced in ISA design. I've been reading https://riscv.org/specifications/ chapter 2, page 21.

Could someone explain why RISC-V has arithmetic and logical instructions which use immediates, such as ADDI and XORI, but not similar conditional branch instructions, such as BLTI, BEQI, etc.

(Where B ranch L ess T han I mmediate would compare a register to a constant and branch if it were less.)

My uninformed opinion is that BLTI would be frequently used for fixed-length loops in C, such as:

for (int i = 0; i < 16; i++) {
    ...
}

Why are arithmetic and logic instructions more deserving of immediate variants than branch instructions?

Branches already need to encode the branch target offset as an immediate, fitting two immediate operands in there would be harder. Making them both much smaller would enable them to fit, but would also reduce the usefulness of the instruction.

Such a branch would be useful occasionally, but in my opinion you are overestimating its usefulness: in typical loops there is no need to directly compare the loop counter against its boundary value, indeed most loop variables do not even make it into the compiled code.

As a small example (using a higher count to avoid a full unroll of the loop),

int test(int *data) {
    int sum = 0;
    for (int i = 0; i < 255; i++)
        sum += data[i];
    return sum;
}

Is compiled by Clang into:

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

What Clang has done here is computing the final address and then looping until that address is reached, removing the loop counter from existence.

This is a somewhat special case, but there are other tricks too. For example, in many cases the loop exit test can be transformed to a loop that exits when a register is decremented to zero, which is easy to test since RISCV has bnez . The original loop counter can co-exist with that if necessary (without participating in the loop exit test), or it can again disappear if possible.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM