Why `assert_eq` makes optimization worser?

I tried this code with -Copt-level=3 :

#[no_mangle]
fn internal(src: &[f32], any_variable: usize) -> Vec<f32> {
    assert_eq!(src.len(), any_variable);

    let mut dst = Vec::<f32>::with_capacity(src.len());
    for i in 0..src.len() {
        dst.push(-src[i]);
    }
    dst
}

I expect that there is not panic_bounds_check in generated asm, but there is. However, if I remove assert_eq!(src.len(), any_variable); in the code, panic_bounds_check disappears. If I change assert_eq!(src.len(), any_variable); to assert!(src.len() == any_variable);, panic_bounds_check disappears too.

If I switch rustc to <= 1.79.0, no bound checking is generated, too.

I feel it might be a bug in rustc and it's related to assert_eq but I'm not sure. What makes it?

The usual method to avoid bound checks is to use iterators instead of loops:

#[no_mangle]
fn internal(src: &[f32], any_variable: usize) -> Vec<f32> {
    src.iter().map(std::ops::Neg::neg).collect()
}

This references neither assertions, nor grow-related functions.

3 Likes

The original example is a bit complex: there are three input arrays and one output array, their sizes are dependent by an expression and it's a two-dimensional loop. Using iterations makes code harder to read and the compiler won't compile it to SIMD version automantically if I add -Ctarget-cpu=core-avx2. And I think it should get optimized code even if indexes are used.

I think it is fine to file a bug report for this since it is a compiler regression.

5 Likes

TBH, for simple Copy types like this, I'd suggest using vec![0.0; src.len()] instead.

That way it calls the single alloc_zeroed function to allocate it, and you can just overwrite the fields instead of needing the push, and thus doesn't need to realize that the push can never actually reallocate.

If your real case is more complex, then please include the full thing. Otherwise you're always going to get the "well do the easier thing" replies.

3 Likes

To address the title, it's not the assertion making it worse, it's the use of Vec.

If you change to this, keeping the assertion

it vectorizes just fine.

1 Like

Thanks for pointing this out, I had no idea. Looks like this optimization is not documented, but I guess that's not uncommon.

1 Like

optimizations generally aren't documented (at least in normative text) because they cannot be relied on.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.