rust-lang / rust-lang/rust

`Slice::contains` produces worse output than `.iter().any`

Open
#142,954 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-autovectorization C-optimization T-compiler T-libs
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Version: rustc 1.89.0-nightly (be19eda0d 2025-06-22)

Link to the Godbolt snippet.
https://godbolt.org/z/q3j8d567v

I tried this code:

// Generates properly optimized code.
pub fn iter_any(v: [u32; 8], x: u32) -> bool {
    v.iter().any(|v| *v == x)
}

// Generates branching code.
pub fn contains(v: [u32; 8], x: u32) -> bool {
    v.contains(&x)
}

I expected both to be the same, or the contains to be more optimal as it is more specialized.

Instead, this happened: the contains seems to generate worse code than iter().any.

Interestingly, if I copy the code directly from core:

pub fn core_impl(v: [u32; 8], x: u32) -> bool {
    // Make our LANE_COUNT 4x the normal lane count (aiming for 128 bit vectors).
    // The compiler will nicely unroll it.
    const LANE_COUNT: usize = 4 * (128 / (size_of::<u32>() * 8));
    // SIMD
    let mut chunks = v.chunks_exact(LANE_COUNT);
    for chunk in &mut chunks {
        if chunk.iter().fold(false, |acc, y| acc | (*y == x)) {
            return true;
        }
    }
    // Scalar remainder
    return chunks.remainder().iter().any(|y| *y == x);
}

This will again generate the better code: https://godbolt.org/z/389GW9c99.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the two Godbolt snippets and compare the generated code for Slice::contains and iter_any under the reported rustc version. Then inspect the Slice::contains entry point and the copied core_impl example to identify why their optimization differs. Done means the issue is explained and, if appropriate, the generated code is made comparably efficient with a regression test.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.