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

Reply via email to