Skip to content

step_by() on new ranges is less optimized than the old ranges. #157754

Description

@theemathas

I compiled the following code:

#[unsafe(no_mangle)]
fn a(n: u32, callback: fn(u32)) {
    let range = 0..n;
    for x in range.step_by(2) {
        callback(x);
    }
}

#[unsafe(no_mangle)]
fn b(n: u32, callback: fn(u32)) {
    let range = std::range::Range { start: 0, end: n }.into_iter();
    for x in range.step_by(2) {
        callback(x);
    }
}

Ideally, both functions should compile to the same or similar assembly. Instead, the inner loop of b is clearly worse than that of a:

Godbolt

Assembly code
a:
        push    rbp
        push    r14
        push    rbx
        mov     ebp, edi
        shr     ebp
        cmp     edi, ebp
        je      .LBB0_3
        mov     rbx, rsi
        sub     ebp, edi
        xor     edi, edi
.LBB0_2:
        lea     r14d, [rdi + 2]
        call    rbx
        mov     edi, r14d
        inc     ebp
        jne     .LBB0_2
.LBB0_3:
        pop     rbx
        pop     r14
        pop     rbp
        ret

b:
        test    edi, edi
        je      .LBB1_5
        push    rbp
        push    r14
        push    rbx
        mov     rbx, rsi
        mov     ebp, edi
        mov     r14d, 2
.LBB1_2:
        lea     edi, [r14 - 2]
        call    rbx
        test    r14d, r14d
        je      .LBB1_4
        cmp     r14d, ebp
        lea     eax, [r14 + 2]
        mov     r14d, eax
        jb      .LBB1_2
.LBB1_4:
        pop     rbx
        pop     r14
        pop     rbp
.LBB1_5:
        ret

I believe that this is because step_by has a specialized implementation for the old ranges, but not for the new ranges. See https://github.com/rust-lang/rust/blob/485ec3fbcc12fa14ef6596dabb125ad710499c9e/library/core/src/iter/adapters/step_by.rs

Meta

Reproducible on godbolt with version

rustc 1.98.0-nightly (485ec3fbc 2026-06-10)
binary: rustc
commit-hash: 485ec3fbcc12fa14ef6596dabb125ad710499c9e
commit-date: 2026-06-10
host: x86_64-unknown-linux-gnu
release: 1.98.0-nightly
LLVM version: 22.1.6
Internal compiler ID: nightly

Activity

  1. 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.
    C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing such
    F-new_range`#![feature(new_range)]`
    on Jun 11, 2026
  2. added
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Jun 11, 2026
  3. removed
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Jun 14, 2026
  4. added 2 commits that reference this issue on Jul 25, 2026
    da3ec25
    0dd4e5b
  5. added 2 commits that reference this issue on Jul 26, 2026
    8faaea1
    2993efb
  6. added a commit that references this issue on Jul 26, 2026
    2bde1f6
  7. added a commit that references this issue on Jul 27, 2026
    ca3b5ab
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

    A-iteratorsArea: IteratorsA-specializationArea: Trait impl specializationC-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchF-new_range`#![feature(new_range)]`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.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions