This page covers the basic structure of while loops in RISC-V. The main idea is to use a label as an anchor point at the start of the loop, and we branch/jump to it to continue looping. There are two approaches to implement a while loop in assembly.
Consider the following while loop:
while (count < total) {
count = count + count;
}
The control flow for this loop for both approaches is shown in the figure below. we could take and both are valid.
The idea is to first test the condition to check if the first iteration of the while loop has to be executed. If the condition is not met, the loop is skipped entirely.
The assembly code with a loop guard branch first tests if the condition is true:
# Register Usage:
# t0: count
# t1: total
bge t0, t1, _JoinPoint # If count >= total is not < 7 then skip loop entirely
_doubleCount:
add t0, t0, t0 # count = count + count
blt t0, t1, _doubleCount # If count < total go back to double count
_JoinPoint:
# Code after the while loop
The advantage of the guard branch is that there is no need for a jump instruction at the end of the loop.
The condition to continue the execution of the loop appears only inside the loop. The implementation for the same loop above with this approach is as follows:
# Register Usage:
# t0: count
# t1: total
_checkCount:
bge t0, t1, _JoinPoint # If count >= total is not < 7 then skip loop entirely
add t0, t0, t0 # count = count + count
j _checkCount # If count < total go back to double count
_JoinPoint:
# Code after the while loop
The disadvantage of this approach is that there is both a jump and a branch instruction inside the while loop. If the loop has many interactions, the additional jump could cause noticeable performance degradation.