[LLVMdev] Miscompile by copying a C union via an x87 FP load+store
Mark Seaborn
mseaborn at chromium.org
Wed Mar 26 14:55:49 PDT 2014
I discovered a bug in which LLVM/Clang can miscompile C code that copies a
union. This occurs on x86 when using x87 instructions for floating point
operations.
The following program's assertion fails when compiled with "-O1 -mno-sse"
(or when passing "-mcpu=blah" to llc). do_copy() gets compiled using x87
load+store instructions, which don't preserve exact byte values:
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
union U {
double f;
unsigned long long i;
};
__attribute__((noinline))
void do_copy(union U *dest, union U *src) {
*dest = *src;
}
int main() {
unsigned long long test_val = 0xfff0000000000001;
union U val, dest;
val.i = test_val;
do_copy(&dest, &val);
printf("%llx\n", dest.i);
assert(dest.i == test_val);
return 0;
}
$ clang copy_union_bug.c -o copy_union_bug -O1 -mno-sse -m32
$ ./copy_union_bug
fff8000000000001
copy_union_bug: copy_union_bug.c:22: int main(): Assertion `dest.i ==
test_val' failed.
Initially I thought the bug was that Clang compiles the union type to
"%union.U = type { double }".
However, I think it's really the optimiser that's at fault. InstCombine
converts do_copy()'s llvm.memcpy call to a load+store of a double.
llvm.memcpy is meant to copy bytes faithfully. llvm.memcpy takes i8*
arguments, and it shouldn't really assume anything about the data it's
copying based on the pointer types that its i8* arguments were bitcast from.
This would be a problem for Emscripten, where double loads/stores are
compiled to operations on a Javascript typed array, which aren't required
to preserve bit patterns of NaNs (
https://www.khronos.org/registry/typedarray/specs/latest/#4) and which
sometimes get compiled to x87 FP. This could be a problem for PNaCl
depending on what guarantees PNaCl provides about double loads/stores (it's
currently not well-defined --
https://code.google.com/p/nativeclient/issues/detail?id=3822).
Should I change InstCombine to not convert the llvm.memcpy to a double
load+store?
Cheers,
Mark
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140326/0d25e9f8/attachment.html>
More information about the llvm-dev
mailing list