https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79675

            Bug ID: 79675
           Summary: Pointless reg1 <- reg2; reg2 <- reg1 moves inside loop
           Product: gcc
           Version: 7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ktkachov at gcc dot gnu.org
  Target Milestone: ---

I'm looking at the code:
char *
foo (char *s1, char *s2, unsigned int n)
{
  char c1, c2;

  c2 = *(char *)s2++;

  do
    {
      do
        {
          c1 = *s1++;
          if (c1 == 0)
            return 0;
        }
      while (c1 != c2);
    }
  while (__builtin_strncmp (s1, (char *)s2, n) != 0);

  return --s1;
}

On aarch64 at -O2 this generates some bad code for the inner loop:
...
.L9:
        cmp     w21, w1
        beq     .L8
.L4:
        mov     x20, x19 // (1)
        mov     x19, x20 // (2)
        ldrb    w1, [x19], 1 (3)
        cbnz    w1, .L9
...
Note the moves between x20 and x19, (1) and (2)
Looking at the RTL dumps the two moves were in separate basic blocks but were
moved together at some point.

Instructions (2) and (3) were transformed by autoincdec from:
add x19, x20, #1
ldrb w1, [x19, #-1]

but nothing eliminated (2) because x19 is later used as an argument to strncmp
and in another basic block.

Doesn't the peephole2 pass try to eliminate such back-to-back copies?

Reply via email to