[llvm-bugs] [Bug 42605] New: GVN-PRE miscompilation

via llvm-bugs llvm-bugs at lists.llvm.org
Fri Jul 12 11:17:21 PDT 2019


https://bugs.llvm.org/show_bug.cgi?id=42605

            Bug ID: 42605
           Summary: GVN-PRE miscompilation
           Product: new-bugs
           Version: 8.0
          Hardware: Macintosh
                OS: MacOS X
            Status: NEW
          Severity: normal
          Priority: P
         Component: new bugs
          Assignee: unassignedbugs at nondot.org
          Reporter: kostas.eleftheriou at gmail.com
                CC: htmldeveloper at gmail.com, llvm-bugs at lists.llvm.org

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.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20190712/9103f78d/attachment.html>


More information about the llvm-bugs mailing list