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].