Skip to content

Missed NonZero optimization opportunity #60044

Description

@mtak-

Godbolt link

When a NonZeroUsize is created through new_unchecked and wrapped in a Some, the optimizer does not recognize that the value is always Some. This can be fixed by adding a std::intrinsics::assume(value != 0) line before creating the NonZero type.

use std::num::NonZeroUsize;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::Relaxed;

pub static X: AtomicUsize = AtomicUsize::new(1);

pub unsafe fn get() -> Option<NonZeroUsize> {
    let x = X.load(Relaxed);
    Some(NonZeroUsize::new_unchecked(x))
}

pub unsafe fn get2() -> usize {
    match get() {
        Some(x) => x.get(),
        None => unreachable!(), // not optimized out
    }
}

Lots of panicking code gets generated in this example.

Fixed by:

#![feature(core_intrinsics)]

use std::num::NonZeroUsize;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::Relaxed;

pub static X: AtomicUsize = AtomicUsize::new(1);

pub unsafe fn get() -> Option<NonZeroUsize> {
    let x = X.load(Relaxed);
    std::intrinsics::assume(x != 0); // gets rid of the panicking code
    Some(NonZeroUsize::new_unchecked(x))
}

pub unsafe fn get2() -> usize {
    match get() {
        Some(x) => x.get(),
        None => unreachable!(), // optimized away
    }
}

I would guess that adding assume inside of new_unchecked would be ok, since it's already UB if it's not zero.

Related: #51346. Posted as a new issue, because it can be fixed without any LLVM pass changes.

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-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchE-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.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.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions