Description
This issue is referenced in stdarch here in missing_aarch64.txt. under "LLVM select error in debug builds".
Certain intrinsics in LLVM require a vector constant to be passed directly as an argument, one of the reasons for this might be that it needs to reduce that vector down to a duplicated scalar immediate that can be encoded in the generated instruction. Rust cannot pass vector constants directly and so relies on the CSE LLVM pass to propagate the loaded constant vector to the intrinsic call. This pass is not used at -O0
and so compilation fails with LLVM ERROR: Cannot select: intrinsic %llvm.aarch64.neon.sqshlu
for example.
This is an example snippet that fails to compile:
#![feature(repr_simd)]
#![allow(non_camel_case_types)]
#[cfg(target_arch = "aarch64")]
use core::arch::aarch64::*;
fn main() {
unsafe {
vqshlu_n_s8::<2>(vdup_n_s8(5));
}
}
There are a number of options to resolve this issue when it comes to Neon intrinsics specifically.
- Allow vectors to be constants in the compiler and thus passed directly to LLVM.
- I have attempted to do this here, though this requires bigger and more thorough changes.
- This may be easier to implement as a const generic.
- Always run the relevant LLVM pass at all rust optimization levels.
- This isn't very nice as it goes against the idea of -O0.
- Alter all relevant LLVM intrinsics to accept a scalar argument alternative where the vector contains only a single unique scalar.
- This may not be possible for all intrinsics that require a vector constant.
Meta
rustc --version --verbose
:
rustc 1.76.0-nightly (a6b8ae582 2023-11-22)