40 lines
1 KiB
Rust
40 lines
1 KiB
Rust
//@ test-mir-pass: GVN
|
|
//@ compile-flags: -Zdump-mir-exclude-alloc-bytes -Zmir-enable-passes=+ReferencePropagation
|
|
|
|
#![crate_type = "lib"]
|
|
#![feature(core_intrinsics, rustc_attrs)]
|
|
|
|
pub enum Value {
|
|
V0(i32),
|
|
V1,
|
|
}
|
|
|
|
// Check that we do not use the dereferenced value of `val_alias` when returning.
|
|
|
|
// EMIT_MIR gvn_loop.loop_deref_mut.GVN.diff
|
|
fn loop_deref_mut(val: &mut Value) -> Value {
|
|
// CHECK-LABEL: fn loop_deref_mut(
|
|
// CHECK: [[VAL_REF:_.*]] = get::<Value>(
|
|
// CHECK: [[V:_.*]] = copy (((*[[VAL_REF]]) as V0).0: i32);
|
|
// CHECK-NOT: copy (*[[VAL_REF]]);
|
|
// CHECK: [[RET:_*]] = Value::V0(copy [[V]]);
|
|
// CHECK-NOT: copy (*[[VAL_REF]]);
|
|
// CHECK: _0 = move [[RET]]
|
|
let val_alias: &Value = get(val);
|
|
let mut stop = false;
|
|
let Value::V0(v) = *val_alias else { unsafe { core::intrinsics::unreachable() } };
|
|
loop {
|
|
let v = Value::V0(v);
|
|
if stop {
|
|
return v;
|
|
}
|
|
stop = true;
|
|
*val = Value::V1;
|
|
}
|
|
}
|
|
|
|
#[inline(never)]
|
|
#[rustc_nounwind]
|
|
fn get<T>(v: &T) -> &T {
|
|
v
|
|
}
|