https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125765
--- Comment #6 from Jeffrey A. Law <law at gcc dot gnu.org> ---
Consider two arms where the constants differ by a single bit. That's a
conditional IOR/PLUS of a shifted condition code. And if the shift count is
small enough it turns into a shadd ;-) Consider:
int src(int c, int b, int a) {
int t = (a ? 0xff00 : 0xff08);
return t;
}
RIght now that generates something like this:
li a5,65536
li a4,65536
addi t0,a5,-248
addi t1,a4,-256
czero.nez t2,t0,a2
czero.eqz a2,t1,a2
add a0,t2,a2
Which is better than a branch, but otherwise awful. This would be clearly
better and isn't a major stretch for the shifted_store_flag routine
li a5,65536
seqz a0,a2
addi t0,a5,-256
sh3add a0,a0,t0
It's a cycle faster and 10 bytes shorter.
If I go back to Andrea's original testcase I get this with my hacks:
src:
seqz a2,a2
li a0,65536
slli t0,a2,4
addi t1,a0,-256
add a0,t1,t0
ret
Which is clearly better than what we're doing now.
So what I'm thinking is we carve this into two or more BZs. One for the case
where we're dealing with a single bit adjustment as that's going to be fairly
easy to implement in the shifted_store_flag routine (original case). A second
for cases where we differ by multiple bits, but it's still a simm12 we're
dealing with (case in c#1)