-
Notifications
You must be signed in to change notification settings - Fork 14.9k
Open
Description
In this code:
void __attribute__((naked)) f() {asm ("ret");}
void __attribute__((naked)) g() {asm ("ret");}
void h(int a) {
if (a == 15) {
f();
} else {
g();
}
}
clang trunk on godbolt produces the following at -Oz
:
h(int):
li a1, 15
bne a0, a1, .LBB2_2
tail f()
.LBB2_2:
tail g()
(Godbolt link: https://godbolt.org/z/srT6MhG5Y)
However the following is two bytes smaller (because bnez
compresses) and avoids a register clobber:
h(int):
addi a0, a0, -15
bnez a0, .LBB2_2
tail f()
.LBB2_2:
tail g()
This transform applies when the branch is the final use of the value, and the comparison constant is not -2048 or -32 (due to the sign change). It is useful when the branch is in compressible range, or when avoiding the clobber is profitable.
The same pattern applies to some sparse switch statements, like here in the RP2350 bootrom. That source file has several instances where this pattern saved static code size in handwritten code.