https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91481

            Bug ID: 91481
           Summary: POWER9 "DARN" RNG intrinsic produces repeated output
           Product: gcc
           Version: 9.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: lloyd at randombit dot net
  Target Milestone: ---

The POWER9 ISA includes a hardware random number generator "DARN" which is
similar to x86 RDRAND/RDSEED. Using the GCC intrinsics and *any optimization
level* then `__builtin_darn()` and `__builtin_darn_raw()` produce repeated
output:

$ cat darn.c
#include <stdio.h>
#include <stdint.h>

int main()
{
  uint64_t darn[32];
  for(size_t i = 0; i != 32; ++i)
    darn[i] = __builtin_darn(); // or __builtin_darn_raw()

  for(size_t i = 0; i != 32; ++i)
    printf("%016lX\n", darn[i]);

}
$ $HOME/opt/bin/powerpc64le-unknown-linux-gnu-gcc -v
Using built-in specs.
COLLECT_GCC=/home/lloyd/opt/bin/powerpc64le-unknown-linux-gnu-gcc
COLLECT_LTO_WRAPPER=/home/lloyd/opt/libexec/gcc/powerpc64le-unknown-linux-gnu/9.2.0/lto-wrapper
Target: powerpc64le-unknown-linux-gnu
Configured with: ../gcc-9.2.0/configure --prefix=/home/lloyd/opt
--enable-languages=c,c++
Thread model: posix
gcc version 9.2.0 (GCC)
$ $HOME/opt/bin/powerpc64le-unknown-linux-gnu-gcc -mcpu=power9 -O -m64 darn.c
-o darn
$ ./darn
32A7727F89101CF3
32A7727F89101CF3
32A7727F89101CF3
32A7727F89101CF3
32A7727F89101CF3
32A7727F89101CF3
32A7727F89101CF3
32A7727F89101CF3
32A7727F89101CF3
32A7727F89101CF3
32A7727F89101CF3
32A7727F89101CF3
32A7727F89101CF3
32A7727F89101CF3
...


The binary produces a unique value each time it is executed, but the same value
repeats. If no optimization is used, then different values are produced. Since
these instructions are supposed to be used to seed cryptographic random number
generators, this is quite bad. I don't know PPC asm but my read of the
generated code when optimizations are enabled is that `darn` is invoked just
once and then the value is placed repeatedly into the array - maybe GCC has not
been taught that this instruction is volatile and produces a different output
each time it is used?

Originally observed with "gcc version 8.3.1 20190304 (Advance-Toolchain-at12.0)
[revision 269374] (GCC)" on gcc135, same behavior with stock GCC 9.2.0.

I don't think there is an issue with the hardware; if using inline asm instead
of the intrinsics, everything seems to work as expected.

Reply via email to