For input 0xffffffff, the following c code works fine with no optimization, but produces wrong results when compiled with -O1. Other compilation options are -g -m32 -Wall. The code is tested with clang-900.0.39.2 in macOS 10.13.2.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
if (argc < 2) return 1;
char *endp;
int x = (int)strtoll(argv[1], &endp, 0);
int mask1 = 0x55555555;
int mask2 = 0x33333333;
int count = (x & mask1) + ((x >> 1) & mask1);
int v1 = count >> 2;
printf("v1 = %#010x\n", v1);
int v2 = v1 & mask2;
printf("v2 = %#010x\n", v2);
return 0;
}
Input: 0xffffffff
Outputs with -O0: (expected)
v1 = 0xeaaaaaaa
v2 = 0x22222222
Outputs with -O1: (wrong)
v1 = 0x2aaaaaaa
v2 = 0x02222222
Below are disassembled instructions for the line "int v1 = count >> 2;" with -O0 and -O1.
With -O0:
sarl $0x2, %esi
With -O1:
shrl $0x2, %esi
Below are disassembled instructions for the line "int v2 = v1 & mask2;" with -O0 and -O1.
With -O0:
andl -0x24(%ebp), %esi //-0x24(%ebp) stores 0x33333333
With -O1:
andl $0x13333333, %esi //why does the optimization changes 0x33333333 to 0x13333333?
In addition, if x is set to 0xffffffff locally instead of getting its value from arguments, the code will work as expected even with -O1.
P.S: The code is an experimental piece based on my solution to the Data Lab from the CS:APP course @ CMU. The lab asks the student to implement a function that counts the number of 1 bit of an int variable without using any type other than int.