|
| 1 | +//! Regression test for <https://github.com/rust-lang/rust/issues/60044>. |
| 2 | +
|
| 3 | +// We want to check that `unreachable!()` is optimized away. |
| 4 | +//@ compile-flags: -O |
| 5 | + |
| 6 | +// Don't de-duplicate `some_non_zero_from_atomic_get2()` since we want its LLVM IR. |
| 7 | +//@ compile-flags: -Zmerge-functions=disabled |
| 8 | + |
| 9 | +// So we don't have to worry about usize. |
| 10 | +//@ only-64bit |
| 11 | + |
| 12 | +#![crate_type = "lib"] |
| 13 | + |
| 14 | +use std::num::NonZeroUsize; |
| 15 | +use std::sync::atomic::AtomicUsize; |
| 16 | +use std::sync::atomic::Ordering::Relaxed; |
| 17 | + |
| 18 | +pub static X: AtomicUsize = AtomicUsize::new(1); |
| 19 | + |
| 20 | +/// We don't need to check the LLVM IR of this function, but we expect its LLVM |
| 21 | +/// IR to be identical to `some_non_zero_from_atomic_get2()`. |
| 22 | +#[no_mangle] |
| 23 | +pub unsafe fn some_non_zero_from_atomic_get() -> Option<NonZeroUsize> { |
| 24 | + let x = X.load(Relaxed); |
| 25 | + Some(NonZeroUsize::new_unchecked(x)) |
| 26 | +} |
| 27 | + |
| 28 | +/// We want to test that the `unreachable!()` branch is optimized out. |
| 29 | +/// |
| 30 | +/// When that does not happen, the LLVM IR will look like this: |
| 31 | +/// |
| 32 | +/// ```sh |
| 33 | +/// rustc +nightly-2024-02-08 --emit=llvm-ir -O -Zmerge-functions=disabled \ |
| 34 | +/// tests/codegen-llvm/some-non-zero-from-atomic-optimization.rs && \ |
| 35 | +/// grep -B 1 -A 13 '@some_non_zero_from_atomic_get2()' some-non-zero-from-atomic-optimization.ll |
| 36 | +/// ``` |
| 37 | +/// ```llvm |
| 38 | +/// ; Function Attrs: nonlazybind uwtable |
| 39 | +/// define noundef i64 @some_non_zero_from_atomic_get2() unnamed_addr #1 { |
| 40 | +/// start: |
| 41 | +/// %0 = load atomic i64, ptr @_ZN38some_non_zero_from_atomic_optimization1X17h monotonic, align 8 |
| 42 | +/// %1 = icmp eq i64 %0, 0 |
| 43 | +/// br i1 %1, label %bb2, label %bb3 |
| 44 | +/// |
| 45 | +/// bb2: ; preds = %start |
| 46 | +/// ; call core::panicking::panic |
| 47 | +/// tail call void @_ZN4core9panicking5panic17h0cc48E(..., ..., ... ) #3 |
| 48 | +/// unreachable |
| 49 | +/// |
| 50 | +/// bb3: ; preds = %start |
| 51 | +/// ret i64 %0 |
| 52 | +/// } |
| 53 | +/// ``` |
| 54 | +/// |
| 55 | +/// When it _is_ optimized out, the LLVM IR will look like this: |
| 56 | +/// |
| 57 | +/// ```sh |
| 58 | +/// rustc +nightly-2024-02-09 --emit=llvm-ir -O -Zmerge-functions=disabled \ |
| 59 | +/// tests/codegen-llvm/some-non-zero-from-atomic-optimization.rs && \ |
| 60 | +/// grep -B 1 -A 6 '@some_non_zero_from_atomic_get2()' some-non-zero-from-atomic-optimization.ll |
| 61 | +/// ``` |
| 62 | +/// ```llvm |
| 63 | +/// ; Function Attrs: mustprogress nofree nounwind nonlazybind willreturn memory(...) uwtable |
| 64 | +/// define noundef i64 @some_non_zero_from_atomic_get2() unnamed_addr #0 { |
| 65 | +/// bb3: |
| 66 | +/// %0 = load atomic i64, ptr @_ZN38some_non_zero_from_atomic_optimization1X17h monotonic, align 8 |
| 67 | +/// %1 = icmp ne i64 %0, 0 |
| 68 | +/// tail call void @llvm.assume(i1 %1) |
| 69 | +/// ret i64 %0 |
| 70 | +/// } |
| 71 | +/// ``` |
| 72 | +/// |
| 73 | +/// The way we check that the LLVM IR is correct is by making sure that neither |
| 74 | +/// `panic` nor `unreachable` is part of the LLVM IR: |
| 75 | +// CHECK-LABEL: define {{.*}} i64 @some_non_zero_from_atomic_get2() {{.*}} { |
| 76 | +// CHECK-NOT: panic |
| 77 | +// CHECK-NOT: unreachable |
| 78 | +#[no_mangle] |
| 79 | +pub unsafe fn some_non_zero_from_atomic_get2() -> usize { |
| 80 | + match some_non_zero_from_atomic_get() { |
| 81 | + Some(x) => x.get(), |
| 82 | + None => unreachable!(), // shall be optimized out |
| 83 | + } |
| 84 | +} |
0 commit comments