<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/139995>139995</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Cannot reproduce object on one architecture by cross-compiling on another with -flto=thin
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          iskunk
      </td>
    </tr>
</table>

<pre>
    This is an issue discovered in the course of cross-compiling Chromium. I am attempting to reproduce, bit-for-bit, a native x86-64 Linux build of Chromium by cross-compiling it from a different Linux architecture. If I do not use LTO, then this works as intended: all the resulting x86-64 objects, libraries, and executables match exactly on both systems. If I specify `-flto=thin`, however, then I get different outputs on the two architectures, starting with `.o` files. The output is still deterministic within each architecture, but of course I want to see output that is the same irrespective of the build system.

I have verified this issue using the project's pre-compiled binaries of LLVM 20.1.5 for X64 and ARM64. I don't have an ARM hardware system, so I used a Docker ARM64 container running via QEMU. My test environment was Ubuntu 25.04/plucky, one instance on amd64, another on arm64. The latter has appropriate cross-compilation packages installed, e.g. `libstdc++-14-dev-amd64-cross`. (Note that I originally encountered this issue in a cross build from ppc64el, but no upstream LLVM binaries are available for that platform.)

Here is a small "kit" to reproduce the problem:

[cross-test.zip](https://github.com/user-attachments/files/20219132/cross-test.zip)

It uses a cut-down source file `spinlock.cc` (plus its dependencies) taken from Chromium, since the issue does not occur with a trivial "hello world"-type program. This file was chosen as it is relatively simple, and was among the first ones to come out differently between the two builds. There is a makefile with a small set of compiler flags that allow the preprocessed source output to match exactly regardless of whether the source is being compiled natively on x86-64, or cross-compiled from ARM64. Running `make CXX=/path/to/clang++` will show the MD5-hashed results of compiling the source file.

Here is the output I see on the amd64 system:
```
$ make clean; make CXX=/opt/llvm/bin/clang++ 
rm -f spinlock spinlock.dep spinlock.ii spinlock.o
/opt/llvm/bin/clang++ --target=x86_64-unknown-linux-gnu -I. --no-line-commands -ffile-prefix-map=/usr/bin/../lib/gcc-cross/=/usr/bin/../lib/gcc/ -ffile-prefix-map=/usr/bin/../lib/gcc-cross/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/=/usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../ -flto=thin -c spinlock.cc
/opt/llvm/bin/clang++ --target=x86_64-unknown-linux-gnu -I. --no-line-commands -ffile-prefix-map=/usr/bin/../lib/gcc-cross/=/usr/bin/../lib/gcc/ -ffile-prefix-map=/usr/bin/../lib/gcc-cross/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/=/usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../ -flto=thin -E spinlock.cc >spinlock.ii
ls -l spinlock.o
-rw-r--r-- 1 build users 4276 May 15 03:06 spinlock.o
7eee0e28d709caf76f71a2b249eef3b8 spinlock.cc
3120df26bdad524adbb170fa4c635be7 spinlock.cc.orig
3737b72697300f721ef4c52ebfe109ed spinlock.ii
2f2cc887fc8dee159ed401da301d387c  spinlock.o
```

And then on arm64:
```
$ make clean; make CXX=/opt/llvm/bin/clang++ 
rm -f spinlock spinlock.dep spinlock.ii spinlock.o
/opt/llvm/bin/clang++ --target=x86_64-unknown-linux-gnu -I. --no-line-commands -ffile-prefix-map=/usr/bin/../lib/gcc-cross/=/usr/bin/../lib/gcc/ -ffile-prefix-map=/usr/bin/../lib/gcc-cross/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/=/usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../ -flto=thin -c spinlock.cc
/opt/llvm/bin/clang++ --target=x86_64-unknown-linux-gnu -I. --no-line-commands -ffile-prefix-map=/usr/bin/../lib/gcc-cross/=/usr/bin/../lib/gcc/ -ffile-prefix-map=/usr/bin/../lib/gcc-cross/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/=/usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../ -flto=thin -E spinlock.cc >spinlock.ii
ls -l spinlock.o
-rw-r--r-- 1 build users 4276 May 15 03:03 spinlock.o
7eee0e28d709caf76f71a2b249eef3b8 spinlock.cc
3120df26bdad524adbb170fa4c635be7 spinlock.cc.orig
3737b72697300f721ef4c52ebfe109ed spinlock.ii
af549dab0aa1daafdfcec288defc4a72  spinlock.o
```

Notice how the preprocessed output (`.ii`) is identical on both systems, yet the compiled object (`.o`) is not. For inspection purposes, I've placed both object files in this archive:

[spinlock-objects.zip](https://github.com/user-attachments/files/20219174/spinlock-objects.zip)

And in case it is needed, here is the preprocessed source:

[spinlock.ii.txt](https://github.com/user-attachments/files/20219239/spinlock.ii.txt)
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzsWN9v47gR_muYl4EEmZIs-8EP2c0aNbC5ooe9Yt-KETmy2FCkQFJ23L--ICUnThrctbgWuAILBEEcS_Pr--YjZ9B7dTREO1Z_YvXDHU6ht26n_NNknu5aKy-7b73yoDygAeX9RCCVF_ZEjiQoA6EnEHZynsB2IJz1PhN2GJVW5gife2cHNQ05HAAHwBBoGEP8JlhwNDorJ0GMf4ZWhayzLmtViB8RDAZ1InjerLN1BV-VmZ6hnZSW0c_VLrSXf_GpAnTODoAgVdeRIxOW19GJXgUSYXKUw6GDA0gLxgaYPMHXb3-OnkNPMSvl4Wzdkwf0oEwgI0my8h5Q65SzIz_plMkSoW3_TiL4aEKr1qFTlD6gkUDPJKaArSYPAwbRAz2jCPoC1kBrQw_-4gMNfonKjyRUdwG2LrJOB8vKh9Arw9ZFtNjbM53IvQR7gCOFm2TtFMYp-Gg7RhrO9k3mKSof0KXozyr00U9u2bqATmnyOXzrabESkfdBaQ2SArlBGeWDEuk1ZYBQ9G-MJyinkLgws-IAZzQh4u3pxWroMZmO8XkcCJRzFLNOmNsufTGjPVcmZ8U9K-4P0OOJ4EROdYrkjNNMy8knWvUEo7MRCsYbD6OjhRokoVUmwRIdfP3610fgRb7Ka-isg-_rKkF1__PjusoTMwzjTZgdoolfQI9OntHRElQqpIVDpI8EhAcrnsjNJkBYE1AZcuAmY2JsJ4Xwly-Pv-TweIFAPgCZk3LWDBG1M3r4pZ1MmIDXeVExvh_1JJ4u0Ys1BMr4gEZQxBUHua5mdtnQk0v_c0OMPGKnY6M56NEDjqOzo1MY6E2nYFDWwIjiCY_kZ-Nak4xGKT_mkRNatT5Iwfgnxj9lqyqTdMqS6yyZirQBxjc_2UAzpAewTh2VQa0vQEbYyYSkFDdAKQM4h7IgnLp1HMW6In3lj7EwjT44wmGG6gW7WH48odKxnRJ0yfOoMXTWDTnj25krfyJHSbjAD7FrGedPUVz4G-25MqbVNLDyfn6V1Z_mWkWU8n-okdUPjG_6EEYfH-J7xvdHFfqpzYUdGN9PnlyGIaDoI5qe8X3qJcb3vOCr7arkjO_fGb1GekgCFCMVU8ikPRvwdnKCUj9GJPyojLbiKRcitinjm1FPHlTwIGmM4mRE0pstBHwiM9f0qpKJp8osyS4qbskn6bNCTG6WAYTg1ElhqlVPWtuogVoyzrNwGVOdjg6HSDLl5-AibUVvPZmklKmrHekk3voCXg2jpqsOxodxsEufdsr5EKntIyLCDkkeXoVMX6ClcCZ61bFEmFmgruAO-ERzJHMKM9ieFg1Kre-g03j0M1NQa3teYI8sEORj-y4VvwqUfSfUjo7opCaf1OPcU2q7pF_zi8pDS7HNX-TGXItgzXJIpFZ2b_qQFv4vuvPzohVsXcTE4PP376x8iFqAoWd8H2ykkUZznLsysuEc5dn3S1KPD3XWo-9JLmeUfy3EVSFv2JW_bZbwqvyHWbDn4qeuv8re3CbrYvkp7hmvEg4gNKFh5Sd4G7wdA-N7rU-xVVpl3uYArLh3A2QdXGn-8kcuaXz9oNTr3za5_S3LWRbQHSmw8uF5s_7busom82Ts2WQ63giyo5kgO-SQZcbGf6XDYkAjPWRdLE82OurUczbgOKcyeffiKc-jb9VGMRBi0US-_60HGd__DutLHi_xM75fVdfH3_364Nl_I7j_xAPc3k8gE3CrVD8Q-uMh9OUWIWDll5vuYsW99pDpt12WuXPmsvgDq-XEjqedh4o3a3jEC6xqKEpW3hfrt282RFQQ38im2ArsmnXXrJC3vNoSdWW7eUeWcsUL2fF1K1HWvELZtqum6LAS67Juqbl9PI_3jPhOUzZtw9fbpiyKruEr6ipRc2o7WhXbKOtv0uMdF2KzaTqxkUSrekuyKlYSy2Ily00j4J3A3GpccX9v5Hzjvt62fijhjz77oYT_pwj9T5Ww_KMrIXZ1tZXYFogridjJTpDgm42kTlTY8F9Xwp9sUIKg_-givVwfGd_E-VCptLXYxsulkmSCEqjfrz3ivfhCYVkmLdfieaFytWNfzRgbcthbF4fWtDKIg-zkRuvn3caB8eZEcSIUceiPfhZbaSSbt1ZxdnCiVye6nfquOWfLNue_M_s1kZEfmr5OgPFkUQYEelpmKEMk52m8v7mafzCxfBR-rlQensPvjpyX25vIr1b59k7uSrktt3hHu1VTNXxTrAt-1-8kUVvwRlSbGpst1bKS66aqq7aR2DZc3KkdL3hd1Ku6KKuS81yWmw0vm7bCsqamq1lV0IBK51Enc-uOd2le3a3K7XZb32lsSfu0ruTc0HmeZhnnrH64c7v4UtZOR8-qQisf_KuZoIKm3Wc0ceh9Hf8XZliTdiy3q6yPdovx4F82LmncvFWUu8np3a8UexH-FOLLimqf4o8FXxI87fg_AwAA__8BNfmi">