about summary refs log tree commit diff
path: root/tests/codegen-llvm/issues/issue-122600-ptr-discriminant-update.rs
blob: 631468d8c217a4dda6186cdea6bf4b58b5c1fefc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//@ compile-flags: -Copt-level=3
//@ revisions: new old
//@ [old] ignore-llvm-version: 22 - 99
//@ [new] min-llvm-version: 22

#![crate_type = "lib"]

// The bug here was that it was loading and storing the whole value.
// It's ok for it to load the discriminant,
// to preserve the UB from `unreachable_unchecked`,
// but it better only store the constant discriminant of `B`.

pub enum State {
    A([u8; 753]),
    B([u8; 753]),
}

// CHECK-LABEL: @update
#[no_mangle]
pub unsafe fn update(s: *mut State) {
    // CHECK-NOT: alloca

    // CHECK-NOT: load
    // CHECK-NOT: store
    // CHECK-NOT: memcpy
    // CHECK-NOT: 75{{3|4}}

    // old: %[[TAG:.+]] = load i8, ptr %s, align 1
    // old-NEXT: trunc nuw i8 %[[TAG]] to i1

    // CHECK-NOT: load
    // CHECK-NOT: store
    // CHECK-NOT: memcpy
    // CHECK-NOT: 75{{3|4}}

    // CHECK: store i8 1, ptr %s, align 1

    // CHECK-NOT: load
    // CHECK-NOT: store
    // CHECK-NOT: memcpy
    // CHECK-NOT: 75{{3|4}}

    // CHECK: ret
    let State::A(v) = s.read() else { std::hint::unreachable_unchecked() };
    s.write(State::B(v));
}