In fact, it's even more wrong than that. The ability for managed runtimes to perform LTO across dynamic code loading means you're even able to get LTO across code your compiler has never witnessed - e.g. plugins written by 3rd parties.
https://devblogs.microsoft.com/dotnet/performance-improvemen...
Does anyone know of articles that go into a bit more on precisely the kinds of LTO they offer? I'll update the guide once I understand the situation a bit better.
Here is a 2015 paper for OpenJDK,
https://cr.openjdk.org/~vlivanov/talks/2015_JIT_Overview.pdf
Modern ART has a bit of everything, Assembly written interpreter for fast startup, followed by a JIT stage which PGO capabilities, followed by an AOT compiler that AOT compiles (with LTO) when the device is idle, and uploading PGO data into the Play Store, so that incrementally the same devices collaborate to the optimal PGO data set.
https://source.android.com/docs/core/runtime/jit-compiler
IBM and Azul JVMs have similar approaches with their cloud based JIT infrastructure.
https://developer.ibm.com/articles/jitserver-optimize-your-j...
https://www.azul.com/products/intelligence-cloud/cloud-nativ...
0) https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.ht...
JVM implementations (and ART), alongside CLR do such optimizations.
Furthermore, nowadays PGO is part of the process as well, so the information can be carried over across runs, used as means for the JIT to quickly achieve the optimal execution point, and carry over from there instead of starting over from scratch every time.