https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78037
Bug ID: 78037 Summary: Incorrect code generated at optimization level -O2 for tzcnt and binary and Product: gcc Version: 6.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: nlescoua at gmail dot com Target Milestone: --- System: Haswell (Linux 64bit) The following program compiles incorrectly on gcc 6.2.0 (and also gcc 5.3.1). ----------------------------------------------------------- #include <stdint.h> #include <stdio.h> #include <x86intrin.h> int main(int argc, char ** argv){ unsigned long l = atol(argv[1]); uint32_t t = _tzcnt_u64(l) & 63llu; printf("%u\n",t); } ------------------------------------------------------------ The tzcnt_u64 intrisic returns the number of trailing zero in the argument and 64 (the register width) if the argument is 0. Complete specification is available here: http://www.felixcloutier.com/x86/TZCNT.html Expected output: ~/g/d/gcc_bug ❯❯ gcc -mbmi -O0 toto.c && ./a.out 0 0 Erroneous output when using -O2 or -O3 (the binary and gets eliminated by the optimizer). ~/g/d/gcc_bug ❯❯ gcc -mbmi -O2 toto.c && ./a.out 0 64 The result must be 0 because 64&63 = 0 When looking at the assembly generated, the "and" instruction is missing at optimization level 2 or 3, as if the optimizer assumed that the values returned by tzcnt are in the range [0:63] whereas the effective range is [0:64].