https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123279
--- Comment #7 from Robin Dapp <rdapp at gcc dot gnu.org> --- After a lot of staring and experimenting my theory is that it's not LTO itself but a very general issue in how we serialize builtin functions in our backend. The streamed function code is current size of the array/vector "registered_functions". What (and when something) gets added to this array depends on the current -march string. The failing ncnn for example builds some objects with -march=rv64gc_xtheadvector, others with -march=rv64gcv or with -march=rv64gc. When specifying xtheadvector (which conflicts with the regular vector extension) we obviously register different and fewer builtins than we would with "v". This leads to inconsistent function codes between translation units that only become obvious in the final linking step. Always registering all functions is not easily possible as xtheadvector and vector conflict and are currently mutually exclusive. I think they don't need to be mutually exclusive at that level and I believe we could always register everything and make the distinction later at expand time. That's not a small fix, though, and I don't see it as in scope for this regression. My current idea is to use a different encoding for the builtin functions: As the function names are unique we can hash them and use the hash value as function code. This works for streaming out as well as in and ensures consistency. If functions names stop being unique in the future we can add discriminators to the hashing function. With my local proof of concept I managed to build ncnn. Going to do some more tests and post a patch later today.
