Skip to content

copied().min() performance regression on nightly #140207

Closed

Description

@DaniPopes

Code

I tried this code (godbolt, from this video):

#[no_mangle]
pub fn f(a: &[u16; 8]) -> u16 {
    a.iter().copied().min().unwrap()
}

I expected to see this happen: compiles to vphminposuw x86 instruction (+avx feature)

Instead, this happened: compiles to unrolled cmp + cmov

Note that a manual min loop is unaffected, even with the slice iterator:

#[no_mangle]
pub fn f(a: &[u16; 8]) -> u16 {
    let mut min = u16::MAX;
    for &x in a {
        if x < min {
            min = x;
        }
    }
    min
}

Version it worked on

It most recently worked on: 1.86

Version with regression

rustc --version --verbose:

rustc 1.88.0-nightly (6bc57c6bf 2025-04-22)
binary: rustc
commit-hash: 6bc57c6bf7d0024ad9ea5a2c112f3fc9c383c8a4
commit-date: 2025-04-22
host: x86_64-unknown-linux-gnu
release: 1.88.0-nightly
LLVM version: 20.1.2

@rustbot modify labels: +regression-from-stable-to-nightly -regression-untriaged


searched nightlies: from nightly-2025-02-15 to nightly-2025-04-23
regressed nightly: nightly-2025-04-16
searched commit range: 2da29db...38c560a
regressed commit: 58c2dd9

Weirdly: #139745 cc @thaliaarchi

bisected with cargo-bisect-rustc v0.6.9

Host triple: x86_64-unknown-linux-gnu
Reproduce with:

cargo bisect-rustc --start 1.86.0 -vv --without-cargo --script ./asm.sh 

Activity

  1. added
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    and removed
    regression-untriagedUntriaged performance or correctness regression.
    on Apr 23, 2025
  2. thaliaarchi commented on Apr 23, 2025

    @thaliaarchi
    Contributor

    Thanks for the bisect. It indeed looks to be caused by my patch. As the linked video indicates, this instruction is limited to min of [u16; 8] and not generalizable. Are there other affected cases?

    This case is the oppose of what I was attempting to optimize Copied<T> for—where the iterated data is smaller than a pointer.

    For Cloned<T>, perhaps we should specialize on T: TrivialClone (#135634, cc @joboet) to match whatever Copied<T> is changed to do.

  3. added
    I-slowIssue: Problems and improvements with respect to performance of generated code.
    T-libsRelevant to the library team, which will review and decide on the PR/issue.
    and removed
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Apr 23, 2025
  4. the8472 commented on Apr 23, 2025

    @the8472
    Member

    Are there other affected cases?

    u8, u32, usize no longer vectorize either, probably others too. They just use(ed) different vector instructions.

    It's strange that #139745 got merged considering that my similar proposal to elide side-effects in #90209 got rejected.

  5. joboet commented on Apr 24, 2025

    @joboet
    Member

    @rustbot label +I-libs-nominated

    I merged #139745 assuming that the precise behaviour around side-effects of the iterator methods was an implementation detail, but that should probably have been discussed beforehand. Also, it was the cause of this performance regression. T-libs, do you want to revert this change?

  6. Amanieu commented on Apr 30, 2025

    @Amanieu
    Member

    We discussed this in the @rust-lang/libs meeting. We would like #139745 to be reverted for now and re-submitted with a libs-api nomination so that we can properly discuss the exact implications.

    I believe the reason this optimizes differently is that before #139745 the compare closure was passed references to copies of the values yielded by the iterator, whereas #139745 changes this to pass the original references yielded by the iterator instead.

  7. removed
    I-libs-nominatedNominated for discussion during a libs team meeting.
    on Apr 30, 2025
  8. 2 remaining items

  9. thaliaarchi commented on May 1, 2025

    @thaliaarchi
    Contributor

    By the way, I am not planning to submit the PRs for the revert or selective reintroduction, even though it's my bug. Sorry. The revert should be easy, though. I'm currently not looking to add any more PRs to my current stack.

  10. added a commit that references this issue on May 5, 2025
  11. added a commit that references this issue on May 5, 2025
  12. added a commit that references this issue on May 11, 2025
  13. added a commit that references this issue on May 12, 2025
  14. added
    regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.
    and removed on Aug 8, 2025
  15. TheElectronWill commented on Aug 13, 2025

    @TheElectronWill

    This seems fixed in 1.89.0 (godbolt): both iter-based and loop-based versions compile to vphminposuw with -C opt-level=3 -C target-feature=+avx.

  16. added
    E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.
    on Aug 13, 2025
  17. clubby789 commented on Aug 13, 2025

    @clubby789
    Contributor

    Adding needs-test since I think it would be useful to make sure issues like this are caught if we re-land something like the original patch

  18. DaniPopes commented on Aug 13, 2025

    @DaniPopes
    ContributorAuthor

    Adding needs-test since I think it would be useful to make sure issues like this are caught if we re-land something like the original patch

    Is this not #140925 ?

  19. clubby789 commented on Aug 13, 2025

    @clubby789
    Contributor

    Looks correct - closed by #140925

  20. removed
    E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.
    on Aug 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.I-slowIssue: Problems and improvements with respect to performance of generated code.P-highHigh priorityT-libsRelevant to the library team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions