Bug 33349 - Redundant zero-extension of registers
Summary: Redundant zero-extension of registers
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.3.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-09-08 03:07 UTC by Udo Steinberg
Modified: 2011-06-17 14:45 UTC (History)
4 users (show)

See Also:
Host: 686-pc-linux-gnu
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2009-02-06 21:45:16


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Udo Steinberg 2007-09-08 03:07:12 UTC
template <typename T>
__attribute__((always_inline))
static inline void out (unsigned port, T val)
{
    asm volatile ("out %0, %w1" : : "a" (val), "Nd" (port));
}
 
void func (unsigned bits, unsigned val)
{
    switch (bits) {
        case 8:
            out (0x80, static_cast<unsigned char>(val));
            return;                                     
        case 16:
            out (0x80, static_cast<unsigned short>(val));
            return;                                      
        case 32:
            out (0x80, static_cast<unsigned long>(val));
            return;                                     
    }
}

Above test program compiled with:
gcc -Os -fomit-frame-pointer -c x.cc
produces the following object code:

00000000 <func(unsigned int, unsigned int)>:
   0:   8b 54 24 04             mov    0x4(%esp),%edx
   4:   8b 44 24 08             mov    0x8(%esp),%eax
   8:   83 fa 10                cmp    $0x10,%edx
   b:   74 10                   je     1d <func(unsigned int, unsigned int)+0x1d>
   d:   83 fa 20                cmp    $0x20,%edx
  10:   74 12                   je     24 <func(unsigned int, unsigned int)+0x24>
  12:   83 fa 08                cmp    $0x8,%edx
  15:   75 0f                   jne    26 <func(unsigned int, unsigned int)+0x26>
  17:   0f b6 c0                movzbl %al,%eax
  1a:   e6 80                   out    %al,$0x80
  1c:   c3                      ret    
  1d:   0f b7 c0                movzwl %ax,%eax
  20:   66 e7 80                out    %ax,$0x80
  23:   c3                      ret    
  24:   e7 80                   out    %eax,$0x80
  26:   c3                      ret    

gcc unnecessarily zero-extends %eax before the out operations.

gcc -v
Using built-in specs.
Target: i686-pc-linux-gnu
Configured with: ../gcc-svn/configure --prefix=/usr --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-languages=c,c++ --disable-checking --with-gnu-ld --verbose
Thread model: posix
gcc version 4.3.0 20070903 (experimental) (GCC)
Comment 1 Steven Bosscher 2009-02-06 21:45:16 UTC
This would be fixed if someone would fix the Sign Extension Elimination pass (yes, it also handles zero extensions).  But that pass is probably broken beyond repair at this point, and likely needs a rewrite instead of just a fix.
Comment 2 Jeremy 2011-06-16 11:27:24 UTC
Another example I came across ...

  unsigned short sw;
  asm( "fnstsw %0" : "=a" (sw) );

  if( sw & FE_DIVBYZERO )
    ...   
  if( sw & FE_OVERFLOW )
    ...  
  if( sw & FE_UNDERFLOW )
    ...

generates:

    movzx   eax, ax # D.14460, sw

    test    al, 1   # D.14460,

    test    al, 4   # D.14460,

    test    al, 8   # D.14460,