https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98981
Bug ID: 98981
Summary: gcc-10.2 for RISC-V has extraneous register moves
Product: gcc
Version: 10.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: brian.grayson at sifive dot com
Target Milestone: ---
gcc is inserting an unnecessary register-register move for a simple max-style
operation:
int a[256], b[256];
int32_t find_max_i32() {
int32_t xme = 0, sc=0;
for (int32_t i = 0; i < 100; i++) {
if ((sc=a[i]+b[i]) > xme) xme=sc;
}
return xme;
}
This is from the SPECint2006 benchmark HMMER, in P7Viterbi(), hence the
variable names sc and xme from the original source.
Under these flags:
-march=rv64imafdc -mcmodel=medany -mabi=lp64d -O3
I get this disassembly for the loop:
.L5:
lw a5,0(a4)
lw a2,0(a3)
addi a4,a4,4
addi a3,a3,4
addw a2,a5,a2
mv a5,a2 <--- unnecessary move
bge a2,a0,.L4
mv a5,a0
.L4:
sext.w a0,a5
bne a4,a1,.L5
If the addw targets a5, and the bge compares a5 to a0, the mv could be removed.
In fact, if the variable types are changed to int64_t, that's exactly what
happens:
.L13:
ld a5,0(a4)
ld a2,0(a3)
addi a4,a4,8
addi a3,a3,8
add a5,a5,a2
bgeu a0,a5,.L12
mv a0,a5
.L12:
bne a4,a1,.L13