Skip to content

leading_zeros() return value is still bounds checked #83779

Description

@martin2250

leading_zeros() can return at most the number of bits of the underlying data type. The compiler does not seem to consider this during optimization.

Code

#![feature(core_intrinsics)]

const LOOKUP: [usize; 65] = [15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 12, 12, 12, 11, 11, 10, 10, 9, 8, 7, 6, 5, 4, 3, 0, 0];

pub fn min_selector(i: u64) -> usize {
    let l_z = i.leading_zeros() as usize;
    // unsafe {core::intrinsics::assume(l_z < 65);}
    return LOOKUP[l_z];
}

Tested on rustc 1.51.0 (2fd73fabe 2021-03-23), nightly in the Compiler Explorer with -C opt-level=3.

I expect the unsafe block to have no effect, since u64::leading_zeros() shouldn't return a number greater than 64. Instead, the disassembly shows that there is a bounds check which disappears when the unsafe block is uncommented.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.C-bugCategory: This is a bug.I-slowIssue: Problems and improvements with respect to performance of generated code.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions