Improve `load`, `store`, `gather`, `scatter` codegen for targets without masked load/store instructions
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 42/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Stale
- Tech stack
- rust
- Domain
- compilers, performance
Research direction
Start by comparing the generated output from the linked Godbolt example for load_or_default_simd and store_simd with the scalar versions on x86_64 sse2. Then trace how these operations lower to the mentioned LLVM masked load, store, gather, and scatter intrinsics. Done means improved load/store codegen matching the scalar loops, with gather/scatter addressed if feasible.
Written by the indexing model from the issue text.
Description
On at least the baseline x86_64 sse2 target, I'd like the code output to be more similar to the manual scalar implementation. I end up having to write out the manual loops and avoid the load/store functions for performance.
https://rust.godbolt.org/z/57hsoTPbd
portable_simd
#![feature(portable_simd)]
use std::simd::*;
const N: usize = 8;
#[inline(never)]
pub fn load_or_default_simd(slice: &[f32]) -> Simd<f32, N> {
Simd::load_or_default(slice)
}
#[inline(never)]
pub fn store_simd(data: Simd<f32, N>, slice: &mut [f32]) {
data.store_select(slice, Mask::splat(true))
}
#[inline(never)]
pub fn gather_or_default_simd(slice: &[f32], idxs: Simd<usize, N>) -> Simd<f32, N> {
Simd::gather_or_default(slice, idxs)
}
#[inline(never)]
pub fn scatter_simd(data: Simd<f32, N>, slice: &mut [f32], idxs: Simd<usize, N>) {
data.scatter(slice, idxs)
}
scalar
#![feature(portable_simd)]
use std::simd::*;
const N: usize = 8;
#[inline(never)]
pub fn load_or_default_scalar(slice: &[f32]) -> Simd<f32, N> {
let mut result = [0.0; N];
for (&s, r) in slice.iter().zip(result.iter_mut()) {
*r = s;
}
Simd::from(result)
}
#[inline(never)]
pub fn store_scalar(data: Simd<f32, N>, slice: &mut [f32]) {
for (s, &d) in slice.iter_mut().zip(data.as_array().iter()) {
*s = d;
}
}
#[inline(never)]
pub fn gather_or_default_scalar(slice: &[f32], idxs: Simd<usize, N>) -> Simd<f32, N> {
let mut result = [0.0; N];
for (&i, r) in idxs.as_array().iter().zip(result.iter_mut()) {
*r = *slice.get(i).unwrap_or(&0.0);
}
Simd::from(result)
}
#[inline(never)]
pub fn scatter_scalar(data: Simd<f32, N>, slice: &mut [f32], idxs: Simd<usize, N>) {
for (&d, &idx) in data.as_array().iter().zip(idxs.as_array().iter()) {
if let Some(s) = slice.get_mut(idx) {
*s = d;
}
}
}
I'm mainly concerned about load/store, I don't expect much from gather/scatter.
I'm not sure if this is something to be solved on the Rust side or LLVM for the intrinsics which are present in the IR
llvm.masked.load.*llvm.masked.store.*llvm.masked.gather.*llvm.masked.scatter.*
Meta
rustc 1.93.0-nightly (c86564c41 2025-11-27)
binary: rustc
commit-hash: c86564c412a5949088a53b665d8b9a47ec610a39
commit-date: 2025-11-27
host: x86_64-unknown-linux-gnu
release: 1.93.0-nightly
LLVM version: 21.1.5
- Dominant language
- Rust
- Stars
- 1.1k
- Forks
- 108
- Avg merge
- 22h 53m
- Merged PRs (30d)
- 3
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from rust-lang/portable-simd
-
C-bug
Difficulty 1/5 Under an hour Newbie friendliness 65/100
rust-lang/portable-simd#499 ·
-
C-bug
Difficulty 4/5 3-5 days Newbie friendliness 45/100
rust-lang/portable-simd#546 · 2 comments ·
-
C-feature-request
Difficulty 5/5 Over a week Newbie friendliness 40/100
rust-lang/portable-simd#539 ·
-
Difficulty 3/5 1-2 days Newbie friendliness 52/100
rust-lang/portable-simd#537 · 4 comments ·
-
C-bug
Difficulty 3/5 1-2 days Newbie friendliness 54/100
rust-lang/portable-simd#527 · 3 comments ·
All issues in rust-lang/portable-simd
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
kwakseongjae/auto-hwp#319 ·
-
area:cli bug filter-quality good first issue priority:medium
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
Difficulty 1/5 Under an hour Newbie friendliness 72/100
bevyengine/bevy#25861 ·
-
comp-datalake
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
ClickHouse/ClickHouse#121222 ·
-
enhancement remote
Difficulty 2/5 1-3 hours Newbie friendliness 68/100