Skip to content

opt-level=z fails to remove bounds checks/panics even if every other opt-level succeeds #115463

Closed
@thomcc

Description

@thomcc

If compiling with -Copt-level=z we fail to remove bounds checks and panicking branches in code like this (godbolt https://godbolt.org/z/YsoMszxPe):

pub fn read_up_to_8(buf: &[u8]) -> u64 {
    if buf.len() < 4 {
        // actual instance has more code.
        return 0;
    }
    let lo = u32::from_le_bytes(buf[..4].try_into().unwrap()) as u64;
    let hi = u32::from_le_bytes(buf[buf.len() - 4..][..4].try_into().unwrap()) as u64;
    lo | (hi << 8 * (buf.len() as u64 - 4))
}

Unfortunately, while -Copt-levels=[123s] all manage to remove the panic branches, -Copt-level=z does not, leading to a lot more code and significantly worse performance.

Note that we do manage to remove it in cases where the function does less stuff -- it's removed entirely in simple examples that do nothing other than load the value from a slice. However, in real code, (perhaps after a layer of inlining) you tend to have a couple of these in a function, and this issue seems to crop up again1.

Given that this pattern is more or less the recommended "safe" way to read a u32 out of a &[u8], this seems unfortunate to me.

Footnotes

  1. Although not 100% reliably -- having trouble reproducing on godbolt, but it seems like it's happening in real-world code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.I-heavyIssue: Problems and improvements with respect to binary size of generated code.I-slowIssue: Problems and improvements with respect to performance of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-libs-apiRelevant to the library API 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