summary refs log tree commit diff
path: root/tests/codegen-llvm/issues/issue-122600-ptr-discriminant-update.rs
diff options
context:
space:
mode:
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.rs43
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));
+}