Rust has aliasing guarantees. In theory, Rust code can pass noalias annotations to LLVM and become more optimized.
In practice, it took years for Rust access these optimizations because the noalias annotations kept hitting codegen bugs in LLVM. It was an area of the compiler that had not seen much active use before Rust, and they were causing a lot of dormant bugs to become issues.
The feedback cycle was also very long because LLVM didn't fix the problems quickly. I didn't pay close attention so I don't know if this is prioritization or because those fixes required major surgery, but Rust sometimes had to wait for major version bumps in LLVM before seeing if "this time was the last time."
Not just in theory. Rust does now mark almost all references as `noalias`, the exception being `&T` where `T` contains an `UnsafeCell`. The equivalent safe Rust function signature[1] would have all four references marked `noalias`, even though the `input` and `matrix` slices could alias.
How much the optimizer can take advantage of that is another matter, due to what you said. Doing a quick translation to more idiomatic Rust[2], it does hoist the accesses to `matrix` out of the hot loop, and does also seem to be a bit less moving stuff around compared to the C version, which I think is putting the `matrix` values in the right places, which Rust did before the loop.
That's interesting. It also looks like with the `__restrict` specifier (https://godbolt.org/z/cvaYoc6zh), the clang code is similar regarding the matrix multiplication. The body of the vectorized loop itself looks identical, `.LBB0_4` in clang and `.LBB1_8` in rustc.
Swift ran into similar difficulties with noalias. Happily the bad cases I was tracking that inhibited optimizations were resolved in the last year or so. There’s probably still some lurking corner cases, but the overall situation is pretty good now.
Yup. But it is true now though so hopefully they’ve added the test cases to LLVM to make sure things continue to work correctly in the face of more and more optimizations being thrown at code.
That was, for the most part, just a problem with LLVM governance and development priorities. When the bugs were found in LLVM, GCC was examined and found to have a few similar bugs. GCC fixed these issues relatively quickly, but LLVM sat on them for years.
Normal C/C++ developers doing normal C/C++ development in GCC probably never saw any of those bugs.