<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>