#include <stdio.h>
void test50() { unsigned int b = 0x7d40d133; unsigned int m = 0x22e5bbf; unsigned int r = 64; b += (((m) << ((int)(r))) | ((m) >> (32 - (int)(r)))); // expect b = 0x7f6f2cf2, however in opt bigger than O1, b = 0x819d88b1 printf("%#x\n", b); }
int main() { test50(); return 0; }
Compiling with -O0 and -O1 produces different results. There appears to be a compiler optimization bug that is triggered when r % 32 == 0,This feature works correctly in Xcode 26.0.
First up, it’s hard to read your post because of the formatting. See tip 5 in Quinn’s Top Ten DevForums Tips for some advice on that front.
Here’s a copy of what I think your program should look like:
#include <stdio.h>
static void test50(void) {
unsigned int b = 0x7d40d133;
unsigned int m = 0x22e5bbf;
unsigned int r = 64;
b += (((m) << ((int)(r))) | ((m) >> (32 - (int)(r))));
// expect b = 0x7f6f2cf2, however in opt bigger than O1, b = 0x819d88b1
printf("%#x\n", b);
}
int main(int argc, char ** argv) {
#pragma unused(argc)
#pragma unused(argv)
test50();
return 0;
}
Note that I’ve made some tweaks so that it compiles without warnings in my standard Xcode setup. Please check my code to make sure I didn’t mess up something important.
Looking at this code I’m concerned about r being 64. In C, the shift factor must be less than the bit width. Anything else is undefined behaviour. And seeing as m is an unsigned int, which is 32 bits, shifting by 64 bits seems like an issue.
To confirm this I put your code into an Xcode test project and turned on UBSan (Product > Scheme > Edit Scheme > Run > Diagnostics > Undefined Behavior Sanitizer [1]). And when I ran that, I saw this output:
…/main.c:7:16: runtime error: shift exponent 64 is too large for 32-bit type 'unsigned int'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior …/main.c:7:16
…/main.c:7:38: runtime error: shift exponent -32 is negative
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior …/main.c:7:38
0x7f6f2cf2
If your program relies on undefined behaviour than the compiler is allowed to produce different output based on any criteria, including the optimisation level.
When programming in a C-based language it’s important to test with all the sanitisers. C is full of nasty traps like this.
This is one of the many reasons I avoid programming in C whenever I can. Life is so much better in ‘modern’ languages. Obviously, as an Apple person, I use Swift, but there are lots of nice modern language out there that can help you avoid problems like this.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] Two American spellings in one phrase. Yuck!