Skip to content

Iterator stack allocation is not split up #144306

@DaniPopes

Description

@DaniPopes

I tried this code (godbolt):

use std::hint::black_box;

type N = u8; // Doesn't matter

#[no_mangle]
pub fn f(n: &N, f: fn(u64)) {
    for x in (MyIter { n: *n, base: 999 }) {
        f(x);
    }
}

struct MyIter {
    base: u64,
    n: N,
}

impl Iterator for MyIter {
    type Item = u64;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        do_next(&mut self.n, self.base)
    }
}

#[inline(never)]
fn do_next(n: &mut N, base: u64) -> Option<u64> {
    // Doesn't matter 
    black_box(n);
    black_box(base);
    black_box(None)
}

I expected to see this happen: self.base is never modified, thus it gets constant-propagated at the f callsite and the only stack allocation that remains is for n

Instead, this happened: base is stored into the iterator allocation, and is loaded for every iteration of the loop even if never modified

This is to illustrate that even if only part of the iterator is ever mutated, LLVM won't recognize that and fail to constant propagate base inside of the loop body, which can have pretty drastic consequences for performance if it's used e.g. for integer division.

This is not specific to iterators, but this is how I noticed the missed optimization in real world code in this PR.

You can see in the godbolt link that we can work around this by creating a new allocation for n and passing that instead will correctly pass base as a constant to do_next.

The type of N and the contents of do_next don't matter. do_next can be fully inlined and the work around will still have its effect.

Meta

rustc --version --verbose:

rustc 1.90.0-nightly (5795086bd 2025-07-16)
binary: rustc
commit-hash: 5795086bdfe7ed988aa53a110bd0692c33d8755b
commit-date: 2025-07-16
host: x86_64-unknown-linux-gnu
release: 1.90.0-nightly
LLVM version: 20.1.8

@rustbot modify labels: +A-LLVM +I-slow +C-optimization -C-bug

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing such

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions