(CVS sources from ~6AM today US/Eastern, i.e., about 16 hours before submission)

Compiling source below with -O9 -fomit-frame-pointer, there are cases where 
registers are assigned 
multiple times without any labels in between; a register assigned zero, used in 
an inclusive-or, then 
overwritten; another register assigned zero and never used.

This 64-bit byteswap routine also exhibits the problems I submitted in 23810, 
23811, 23812, but I 
think one or two of these might be separate problems from those.

typedef unsigned long long uint64_t;
typedef unsigned long uint32_t;
uint64_t bitreverse (uint64_t n) {
  /* Dr. Dobbs Journal 1983, reported in Sean Eron Anderson's "bit
     twiddling hacks" web site,
     http://graphics.stanford.edu/~seander/bithacks.html .  */
#define REV64_STEP(VAR, SHIFT, MASK) \
  VAR = (((VAR >> SHIFT) & MASK) | ((VAR << SHIFT) & (0xFFFFFFFFFFFFFFFFULL & 
~MASK)))

  REV64_STEP(n,  1, 0x5555555555555555ULL); /* odd/even bits */
  REV64_STEP(n,  2, 0x3333333333333333ULL); /* bitpairs */
  REV64_STEP(n,  4, 0x0F0F0F0F0F0F0F0FULL); /* nibbles */
  REV64_STEP(n,  8, 0x00FF00FF00FF00FFULL); /* bytes */
  REV64_STEP(n, 16, 0x0000FFFF0000FFFFULL); /* halfwords */
  REV64_STEP(n, 32, 0x00000000FFFFFFFFULL); /* full words */
  return n;
}

assembly generated:

bitreverse:
        pushl   %edi
        pushl   %esi
        pushl   %ebx
        movl    16(%esp), %eax
        movl    20(%esp), %edx
        movl    %eax, %ecx
        movl    %edx, %ebx
        shrdl   $1, %ebx, %ecx
        shldl   $1, %eax, %edx
        addl    %eax, %eax
        shrl    %ebx
        andl    $-1431655766, %eax
        andl    $-1431655766, %edx
        andl    $1431655765, %ecx
        andl    $1431655765, %ebx
        orl     %eax, %ecx
        orl     %edx, %ebx
        movl    %ecx, %eax
        movl    %ebx, %edi
        movl    %ecx, %esi
        movl    %ebx, %edx
        shrdl   $2, %edi, %esi
        shldl   $2, %eax, %edx
        andl    $858993459, %esi
        shrl    $2, %edi
        andl    $-858993460, %edx
        sall    $2, %eax
        andl    $858993459, %edi
        andl    $-858993460, %eax
        orl     %edx, %edi
        orl     %eax, %esi
        movl    %edi, %ebx
        movl    %esi, %eax
        movl    %esi, %ecx
        movl    %edi, %edx
        shrdl   $4, %ebx, %ecx
        shldl   $4, %eax, %edx
        andl    $252645135, %ecx
        shrl    $4, %ebx
        andl    $-252645136, %edx
        sall    $4, %eax
        andl    $252645135, %ebx
        andl    $-252645136, %eax
        orl     %edx, %ebx
        orl     %eax, %ecx
        movl    %ebx, %edi
        movl    %ecx, %esi
        movl    %ecx, %eax
        shrdl   $8, %edi, %esi
        movl    %ebx, %edx
        shrl    $8, %edi
        andl    $16711935, %esi
        andl    $16711935, %edi
        shldl   $8, %eax, %edx
        sall    $8, %eax
        andl    $-16711936, %edx
        andl    $-16711936, %eax
        orl     %edx, %edi
        orl     %eax, %esi
            # we're about to copy this from esi to eax then clear esi;
            # wouldn't putting output in eax be better?
        movl    %edi, %ebx
        movl    %esi, %eax
        movl    %esi, %ecx
        movl    %edi, %edx
        xorl    %esi, %esi # esi set to zero
        # PRs 23810, 23811 look at this code:
        shrdl   $16, %ebx, %ecx
        shldl   $16, %eax, %edx
        andl    $65535, %ecx
        shrl    $16, %ebx
        andl    $-65536, %edx
        andl    $65535, %ebx
        sall    $16, %eax
        orl     %edx, %ebx
        andl    $-65536, %eax
        movl    %ebx, %edx
        orl     %eax, %ecx # output to ecx then move to eax, instead of just 
output to eax?
        movl    %ecx, %ebx # ebx only used to ior into edx, while ecx value 
still live
        movl    %ecx, %eax # assign eax twice??
        movl    %edx, %eax
        xorl    %edx, %edx # clear edx twice??
        xorl    %edx, %edx
        orl     %esi, %eax # esi still zero
        orl     %ebx, %edx
        movl    $0, %ecx # why? insn note shows REG_UNUSED
        popl    %ebx
        popl    %esi
        popl    %edi
        ret

A version of this swap routine that splits the 64-bit value into two 32-bit 
chunks, performs bit-
reversals on the chunks, and puts the two chunks back together in reverse 
order, comes out shorter, 
despite still showing the PR23810/23811 problems, but it does the same work as 
this function should.

I suspect at least some of these come from preserving DImode operations until 
fairly late, e.g., 
assigning a DImode to eax/edx, then shifting right 32 (eax:=edx, edx:=0), stuff 
like that.  I haven't 
figured out the esi and ecx bits yet though.

-- 
           Summary: redundant register assignments not eliminated
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: rtl-optimization
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: raeburn at raeburn dot org
                CC: gcc-bugs at gcc dot gnu dot org
 GCC build triplet: i686-pc-linux-gnu
  GCC host triplet: i686-pc-linux-gnu
GCC target triplet: i686-pc-linux-gnu


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

Reply via email to