diff options
Diffstat (limited to 'tests/codegen-llvm/issues/issue-122600-ptr-discriminant-update.rs')
| -rw-r--r-- | tests/codegen-llvm/issues/issue-122600-ptr-discriminant-update.rs | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/tests/codegen-llvm/issues/issue-122600-ptr-discriminant-update.rs b/tests/codegen-llvm/issues/issue-122600-ptr-discriminant-update.rs new file mode 100644 index 00000000000..853a1ff36b1 --- /dev/null +++ b/tests/codegen-llvm/issues/issue-122600-ptr-discriminant-update.rs @@ -0,0 +1,43 @@ +//@ compile-flags: -Copt-level=3 + +#![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}} + + // CHECK: %[[TAG:.+]] = load i8, ptr %s, align 1 + // CHECK-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)); +} |
