This contrived example is miscompiled by gcc:

struct node {
  struct node* next, *prev;
};

void foo(struct node* n) {
  n->next->next->prev=n;
  n->next->prev->next=n;
}

This is not from real code, but I wrote it to demonstrate aliasing issues for a
talk I'm preparing now.  gcc -O2 -fno-strict-aliasing generates this code:

        movq    (%rdi), %rdx
        movq    (%rdx), %rax
        movq    %rdi, 8(%rax)
        movq    8(%rdx), %rax
        movq    %rdi, (%rax)

Note how rdx is used to cache the value of n->next.  Since we write through
some pointer that might alias other memory, gcc can not assume n still points
to the same value and n->next is unchanged after the first assignment.

Interestingly enough, changing assignments to

  n->next->next->next=n;
  n->next->prev->next=n;

properly reloads n->next.  I'm guessing that's because ->next has offset 0
relative to the pointer.


-- 
           Summary: Invalid optimization in the face of aliasing
           Product: gcc
           Version: 4.2.1
            Status: UNCONFIRMED
          Severity: major
          Priority: P3
         Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: felix-gcc at fefe dot de
 GCC build triplet: x86_64-unknown-linux-gnu
  GCC host triplet: x86_64-unknown-linux-gnu
GCC target triplet: x86_64-unknown-linux-gnu


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

Reply via email to