| //! 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 | |
| } | |
| } |