Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions tests/codegen-llvm/some-non-zero-from-atomic-optimization.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/60044>.

// We want to check that `unreachable!()` is optimized away.
//@ compile-flags: -O

// Don't de-duplicate `some_non_zero_from_atomic_get2()` since we want its LLVM IR.
//@ compile-flags: -Zmerge-functions=disabled

// So we don't have to worry about usize.
//@ only-64bit

#![crate_type = "lib"]

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

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

/// We don't need to check the LLVM IR of this function, but we expect its LLVM
/// IR to be identical to `some_non_zero_from_atomic_get2()`.
#[no_mangle]
pub unsafe fn some_non_zero_from_atomic_get() -> Option<NonZeroUsize> {
let x = X.load(Relaxed);
Some(NonZeroUsize::new_unchecked(x))
}

/// We want to test that the `unreachable!()` branch is optimized out.
///
/// When that does not happen, the LLVM IR will look like this:
///
/// ```sh
/// rustc +nightly-2024-02-08 --emit=llvm-ir -O -Zmerge-functions=disabled \
/// tests/codegen-llvm/some-non-zero-from-atomic-optimization.rs && \
/// grep -B 1 -A 13 '@some_non_zero_from_atomic_get2()' some-non-zero-from-atomic-optimization.ll
/// ```
/// ```llvm
/// ; Function Attrs: nonlazybind uwtable
/// define noundef i64 @some_non_zero_from_atomic_get2() unnamed_addr #1 {
/// start:
/// %0 = load atomic i64, ptr @_ZN38some_non_zero_from_atomic_optimization1X17h monotonic, align 8
/// %1 = icmp eq i64 %0, 0
/// br i1 %1, label %bb2, label %bb3
///
/// bb2: ; preds = %start
/// ; call core::panicking::panic
/// tail call void @_ZN4core9panicking5panic17h0cc48E(..., ..., ... ) #3
/// unreachable
///
/// bb3: ; preds = %start
/// ret i64 %0
/// }
/// ```
///
/// When it _is_ optimized out, the LLVM IR will look like this:
///
/// ```sh
/// rustc +nightly-2024-02-09 --emit=llvm-ir -O -Zmerge-functions=disabled \
/// tests/codegen-llvm/some-non-zero-from-atomic-optimization.rs && \
/// grep -B 1 -A 6 '@some_non_zero_from_atomic_get2()' some-non-zero-from-atomic-optimization.ll
/// ```
/// ```llvm
/// ; Function Attrs: mustprogress nofree nounwind nonlazybind willreturn memory(...) uwtable
/// define noundef i64 @some_non_zero_from_atomic_get2() unnamed_addr #0 {
/// bb3:
/// %0 = load atomic i64, ptr @_ZN38some_non_zero_from_atomic_optimization1X17h monotonic, align 8
/// %1 = icmp ne i64 %0, 0
/// tail call void @llvm.assume(i1 %1)
/// ret i64 %0
/// }
/// ```
///
/// The way we check that the LLVM IR is correct is by making sure that neither
/// `panic` nor `unreachable` is part of the LLVM IR:
// CHECK-LABEL: define {{.*}} i64 @some_non_zero_from_atomic_get2() {{.*}} {
// CHECK-NOT: panic
// CHECK-NOT: unreachable
#[no_mangle]
pub unsafe fn some_non_zero_from_atomic_get2() -> usize {
match some_non_zero_from_atomic_get() {
Some(x) => x.get(),
None => unreachable!(), // shall be optimized out
}
}
Loading