Skip to content

Iteration over arrays until end pointer (C++ vector iterator, Rust iterators) doesn't preserve number of iterations for the optimizer #48309

Open
@sdroege

Description

@sdroege
Bugzilla Link 48965
Version 11.0
OS Linux
CC @dwblaikie,@fhahn,@jrmuizel,@LebedevRI,@nikic

Extended Description

This was originally reported here: rust-lang/rust#75935

In the end it boils down to the following minimal testcases in C/C++/Rust.

Godbolt links: https://godbolt.org/z/s6reoz and https://rust.godbolt.org/z/a7f6rj

All of them have in common that the iteration happens not by having a counter but instead iterating until the end pointer. When additionally counting the iterations, the maximum (or here: exact) number of iterations does not seem to be available during optimizations. As such the two assertions are not detected as dead code and not optimized away. In this specific minimal case, the whole function should've been possible to optimize away.

The testcase is extremely contrived but it also happens in real code (the Rust issue contains something closer to my original code) and causes missed optimization opportunities, and is especially problematic with Rust because of automatic bounds checks for array indexing that can be impossible to optimize away because of this and then preventing other optimizations (like auto-vectorization or loop unrolling) to kick in.

C

void foo(const uint32_t *y, size_t y_len) {
const uint32_t *y_end = y + y_len;
size_t c = 0;
for (const uint32_t *y_iter = y; y_iter != y_end; y_iter++, c++) {
assert(c < y_len);
}
assert(c == y_len);
}

C++

void foo(const std::vector<uint32_t>& y) {
size_t c = 0;
for (auto y_iter = y.cbegin(); y_iter != y.cend(); y_iter++, c++) {
assert(c < y.size());
}
assert(c == y.size());
}

Rust

pub fn foo(y: &[u32]) {
let mut x = 0;
for (c, _y) in y.iter().enumerate() {
assert!(c < y.len());
x = c;
}
assert!(x == y.len());
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions