Bug 1160986 - gcc9 -fPIC creates unreproducible assembler code
gcc9 -fPIC creates unreproducible assembler code
Classification: openSUSE
Product: openSUSE Tumbleweed
Classification: openSUSE
Component: Development
x86-64 All
: P5 - None : Normal (vote)
: ---
Assigned To: Michael Matz
E-mail List
Depends on:
  Show dependency treegraph
Reported: 2020-01-15 10:27 UTC by Bernhard Wiedemann
Modified: 2021-04-06 03:08 UTC (History)
1 user (show)

See Also:
Found By: Development
Services Priority:
Business Priority:
Blocker: ---
Marketing QA Status: ---
IT Deployment: ---

test1.c (3.71 MB, text/plain)
2020-01-15 10:27 UTC, Bernhard Wiedemann

Note You need to log in before you can comment on or make changes to this bug.
Description Bernhard Wiedemann 2020-01-15 10:27:26 UTC
Created attachment 827567 [details]

While working on reproducible builds for openSUSE, I found that
our darktables package had multiple unreproducible .o files that resulted in unreproducible .so output.

I used gcc -E $MANYARGS introspection_toneequal.c
to produce the attached test1.c reproducer.

Steps to Reproduce:
for i in 1 2 ; do gcc-9 -fPIC -S test1.c && md5sum test1.s ; done

Actual Result:
produces a different md5sum output for every run.

Expected Result:
output should be fully deterministic.

same for gcc
Comment 1 Richard Biener 2020-01-15 11:17:20 UTC
Confirmed.  Differences are all in ifunc resolver calls:

-       call    dt_simd_memcpy._GLOBAL___t.i_3D085019_0x561944bc33c36f7b.ifunc@PLT
+       call    dt_simd_memcpy._GLOBAL___t.i_3D085019_0x2106691e4ac81b0a.ifunc@PLT

where without -fPIC we don't "mangle" the symbols this way:

        call    dt_simd_memcpy._GLOBAL___dt_module_dt_version.ifunc

the testcase uses

__attribute__((target_clones("default", "sse2", "sse3", "sse4.1", "sse4.2", "popcnt", "avx", "avx2", "avx512f", "fma4")))
static inline void dt_simd_memcpy(const float *const __restrict__ in,
                                  float *const __restrict__ out,
                                  const size_t num_elem)

that the function is static is important, the following is a reduced testcase:

__attribute__((target_clones("default", "sse3")))
static void dt_simd_memcpy (const float *const __restrict__ in,
                     float *const __restrict__ out,
                     const int num_elem)
  for(int k = 0; k < num_elem; k++)
    out[k] = in[k];

void bar(float *in, float *out, int num_elem)
  dt_simd_memcpy (in, out, num_elem);
Comment 2 Richard Biener 2020-01-15 11:31:00 UTC
A workaround is to avoind making dt_simd_memcpy and friends 'static'.  GCC has
to make the ifunc resolver globally visible and has to choose a "unique" name
for this purpose.  Which is of course hard, so it tries with randomness.
Comment 3 Bernhard Wiedemann 2020-03-26 08:42:13 UTC
should be fixed in gcc10
Comment 4 Bernhard Wiedemann 2021-04-06 03:08:59 UTC
indeed, darktable builds reproducibly since gcc10