I’m having a problem with __sync_fetch_and_and incorrectly performing. I wrote the following code to illustrate it:
bool equal;
int64_t mask = 0x01234567BEEFDEAD;
int64_t orig = 0xDEADBEEF01234567;
int64_t test1, test2;
test1 = test2 = orig;
equal = (test1 == test2);
printf("Before anding\n");
printf("test1:\t0x%016llX\n", test1);
printf("test2:\t0x%016llX\n", test2);
printf("equal:\t%d\n", equal);
// Try anding
test1 &= mask;
__sync_fetch_and_and(&test2, mask);
equal = (test1 == test2);
printf("After anding\n");
printf("test1:\t0x%016llX\n", test1);
printf("test2:\t0x%016llX\n", test2);
printf("equal:\t%d\n", equal);
The output from this is:
Before anding
test1: 0xDEADBEEF01234567
test2: 0xDEADBEEF01234567
equal: 1
After anding
test1: 0x0021046700234425
test2: 0xDFAFFFEFBFEFDFEF
equal: 0
…which is obviously not correct. I’ve tried replacing __sync_and_and_fetch but that doesn’t fix it. Or-ing with “__sync_fetch_and_or` works correctly. I’m using Xcode 4.2.1 and compiling with the default compiler Apple LLVM Compiler 3.0 (Clang). When I switch to using GCC 4.2, it works correctly.
This certainly seems like a compiler bug, but I’m not sure if I’m somehow doing this wrong on Clang. Are there some differences in Clang that I’m not accounting for, or is this indeed a bug?
EDIT: I haven’t tried the latest release of Clang (3.0) because I’m stuck using Xcode for now.
Yes, it’s a bug; it’s been fixed in newer versions of clang. As a workaround, you can add “-no-integrated-as” to your compiler flags.