Skip to content

Missed NonZero optimization opportunity #60044

@mtak-

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.

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