Repository navigation
Mark SimdInto/SimdFrom blanket impls #[inline(always)] - #417
Conversation
These impls sit on the return path of nearly every SIMD operation, converting the native register back into the vector type. Unlike every other conversion in the crate they had no inline attribute, so rustc treats them as ordinary generic functions that only get inlined when local ThinLTO runs across codegen units. That happens in a default release build, so the problem goes unnoticed there. It does not happen with lto = "off", or at opt-level 1, where generic instances are shared across crates. In those builds every operation makes an out-of-line call that is compiled without the caller's target features, so the vector is passed through memory. In an AVX-512 heavy workload this made those builds about 16x slower than a default release build. With the attributes all builds produce the same inlined code.
Shnatsel
left a comment
There was a problem hiding this comment.
The default release build uses thin crate-local LTO, unless -C codegen-units=1 is passed, in which case it isn't needed. This form of LTO is specifically compensating for multiple codegen units, and going to cause a lot of inlining issues if disabled. I don't think we should treat it as an optimization target in general.
But these annotations are simple and innocuous enough so I'm happy to merge this.
|
Not sure I understand, I was running into this problem without LTO but with opt-level=1. Things were like 20x slower because of the missing inlining here. This is often done in bigger projects because |
|
Ah, I see. I missed the |
|
Not sure what's up with CI, I will try merging again later in hopes that it's a transient issue with Github. |
These impls sit on the return path of nearly every SIMD operation, converting the native register back into the vector type. Unlike every other conversion in the crate they had no inline attribute, so rustc treats them as ordinary generic functions that only get inlined when local ThinLTO runs across codegen units.
That happens in a default release build, so the problem goes unnoticed there. It does not happen with lto = "off", or at opt-level 1, where generic instances are shared across crates. In those builds every operation makes an out-of-line call that is compiled without the caller's target features, so the vector is passed through memory.
In an AVX-512 heavy workload this made those builds about 16x slower than a default release build. With the attributes all builds produce the same inlined code.