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

Reply via email to