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?