blob: 35317b0dd39cc9e9ec3c00a67c01b51cfca696d6 [file] [log] [blame] [edit]
//! 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
}
}