<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - GVN-PRE miscompilation"
   href="https://bugs.llvm.org/show_bug.cgi?id=42605">42605</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>GVN-PRE miscompilation
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>new-bugs
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>8.0
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>Macintosh
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>MacOS X
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>new bugs
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>kostas.eleftheriou@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>htmldeveloper@gmail.com, llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Hi,

I recently came across this bug while developing an application. I eventually
managed to produce the following test case, which is miscompiling for me using
llvm-8.0.0-x86_64-apple-darwin.

```
// gvnbug.c
#include <stdlib.h>
#include <stdio.h>

typedef struct MyStruct {
  void* pointer1;
  void* pointer2;
} MyStruct;

MyStruct entry(const int* pointer, int index) {
  MyStruct r;
  if (pointer[index] == 0) {
    r.pointer1 = 0;
    r.pointer2 = 0;
  } else {
    r.pointer1 = (void*)0x123;
    r.pointer2 = (void*)0x456;
  }
  return r;
}

int main() {
  int* pointer = (int*) calloc(1, sizeof(int));
  int index = 0;
  while (1) {
    MyStruct et = entry(pointer, index);
    if (et.pointer1 == NULL) break;
    index++;
    if (index == pointer[0]) {
      index = 0;
    }
  }
  pointer[index] = 1;
  MyStruct r = entry(pointer, index);
  printf("%p %p\n", r.pointer1, r.pointer2);
  return 0;
}

$ clang -c -O1 -emit-llvm gvnbug.c -isysroot
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk
-stdlib=libc++ -o - | opt -gvn | lli
0x0 0x456
```

The expected output is 0x123 0x456. Omitting the `-gvn` optimization produces
the expected output.

Analysis below by Juneyoung Lee:

If I understand correctly, it is more like a bug of PRE incorrectly assuming
that r.pointer1 is equivalent to et.pointer1 at the first iteration of the
loop.

After -O1, the bitcode looks like this:
```
pointer = calloc(1, 4)
et = entry(pointer, 0)
%1 = et.pointer1

if (%1 != null) { // Note that %1 is always null, so this is never taken.
  %2 = pointer[0] // always 0
  do {
    p = phi(0, %select)
    inc = p + 1
    select = (inc == %2) ? 0 : inc // always inc
    et2 = entry(pointer, select)
  } while(et2.pointer1 != null)
}

i2 = phi(0, select)
pointer[i2] = 1
r = entry(pointer, i2)
printf(.., r.pointer1, r.pointer2)
```

GVN-PRE replaces r.pointer1 with phi(et.pointer1, et2.pointer1), which is
incorrect because `pointer[i2] = 1` makes `r` and `et` different. The incorrect
replacement may have been fired due to the existence of the null comparison.</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>