This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c/46357] New: Unnecessary movzx instruction


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46357

           Summary: Unnecessary movzx instruction
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
        AssignedTo: unassigned@gcc.gnu.org
        ReportedBy: justin.lebar+bug@gmail.com


Originally reported to the gcc-help list.

Tested with gcc Ubuntu/Linaro 4.5.1-7ubuntu2, but I get the same code with gcc
4.4.

The following C code generates assembly code with what appears to be an
unnecessary call to movzx:

  char skip[] = { /* ... */ };

  int foo(const unsigned char *str, int len)
  {
    int result = 0;
    int i = 7;

    while (i < len) {
      if (str[i] == '_' && str[i-1] == 'D') {
        result |= 2;
      }
      i += skip[str[i]];
    }

    return result;
  }

0000000000000000 <foo>:
  0:   31 c0                   xor    eax,eax
  2:   83 fe 07                cmp    esi,0x7
  5:   ba 07 00 00 00          mov    edx,0x7
  a:   7f 14                   jg     20 <foo+0x20>
  c:   eb 32                   jmp    40 <foo+0x40>
  e:   66 90                   xchg   ax,ax

// Beginning of loop

 10:   0f b6 c9                movzx  ecx,cl
 13:   0f be 89 00 00 00 00    movsx  ecx,BYTE PTR [rcx+0x0]
 1a:   01 ca                   add    edx,ecx
 1c:   39 d6                   cmp    esi,edx
 1e:   7e 20                   jle    40 <foo+0x40>
 20:   4c 63 c2                movsxd r8,edx
 23:   42 0f b6 0c 07          movzx  ecx,BYTE PTR [rdi+r8*1]
 28:   80 f9 5f                cmp    cl,0x5f
 2b:   75 e3                   jne    10 <foo+0x10>

// Likely end of loop (i.e. branch above is likely taken)

 2d:   41 89 c1                mov    r9d,eax
 30:   41 83 c9 02             or     r9d,0x2
 34:   41 80 7c 38 ff 44       cmp    BYTE PTR [r8+rdi*1-0x1],0x44
 3a:   41 0f 44 c1             cmove  eax,r9d
 3e:   eb d0                   jmp    10 <foo+0x10>
 40:   f3 c3                   repz ret


The movzx on line 10 sets everything except the least-significant bit of ecx to
zero.  This is unnecessary since line 23 dominates line 10, so we're guaranteed
that ecx contains zeros everywhere except in its least-significant bit by the
time we get to line 10.

If I change |str| in the C code to a signed char, then line 10 becomes movsx
(now a necessary instruction). Perhaps this gives a hint as to where the errant
instruction is coming from.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]