rust/tests/mir-opt/dataflow-const-prop/enum.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

152 lines
4.2 KiB
Rust
Raw Normal View History

// unit-test: DataflowConstProp
2023-09-09 11:47:17 -05:00
// EMIT_MIR_FOR_EACH_BIT_WIDTH
#![feature(custom_mir, core_intrinsics, rustc_attrs)]
use std::intrinsics::mir::*;
2023-05-13 09:19:31 -05:00
#[derive(Copy, Clone)]
enum E {
V1(i32),
V2(i32)
}
// EMIT_MIR enum.simple.DataflowConstProp.diff
2024-01-08 00:03:42 -06:00
// CHECK-LABEL: fn simple(
fn simple() {
2024-01-08 00:03:42 -06:00
// CHECK: debug e => [[e:_.*]];
// CHECK: debug x => [[x:_.*]];
// CHECK: [[e]] = const E::V1(0_i32);
let e = E::V1(0);
2024-01-08 00:03:42 -06:00
2024-02-11 21:56:03 -06:00
// CHECK: switchInt(const 0_isize) -> [0: [[target_bb:bb.*]], 1: bb2, otherwise: bb1];
2024-01-12 01:22:33 -06:00
// CHECK: [[target_bb]]: {
2024-01-08 00:03:42 -06:00
// CHECK: [[x]] = const 0_i32;
let x = match e { E::V1(x1) => x1, E::V2(x2) => x2 };
}
2023-05-13 07:30:40 -05:00
// EMIT_MIR enum.constant.DataflowConstProp.diff
2024-01-08 00:03:42 -06:00
// CHECK-LABEL: fn constant(
2023-05-13 07:30:40 -05:00
fn constant() {
2024-01-08 00:03:42 -06:00
// CHECK: debug e => [[e:_.*]];
// CHECK: debug x => [[x:_.*]];
2023-05-13 07:30:40 -05:00
const C: E = E::V1(0);
2024-01-08 00:03:42 -06:00
// CHECK: [[e]] = const _;
2023-05-13 07:30:40 -05:00
let e = C;
2024-02-11 21:56:03 -06:00
// CHECK: switchInt(const 0_isize) -> [0: [[target_bb:bb.*]], 1: bb2, otherwise: bb1];
2024-01-12 01:22:33 -06:00
// CHECK: [[target_bb]]: {
2024-01-08 00:03:42 -06:00
// CHECK: [[x]] = const 0_i32;
let x = match e { E::V1(x1) => x1, E::V2(x2) => x2 };
2023-05-13 07:30:40 -05:00
}
2023-05-13 09:19:31 -05:00
// EMIT_MIR enum.statics.DataflowConstProp.diff
2024-01-08 00:03:42 -06:00
// CHECK-LABEL: fn statics(
2023-05-13 09:19:31 -05:00
fn statics() {
2024-01-08 00:03:42 -06:00
// CHECK: debug e1 => [[e1:_.*]];
// CHECK: debug x1 => [[x1:_.*]];
// CHECK: debug e2 => [[e2:_.*]];
// CHECK: debug x2 => [[x2:_.*]];
2023-05-13 09:19:31 -05:00
static C: E = E::V1(0);
2024-01-08 00:03:42 -06:00
// CHECK: [[e1]] = const E::V1(0_i32);
let e1 = C;
2024-02-11 21:56:03 -06:00
// CHECK: switchInt(const 0_isize) -> [0: [[target_bb:bb.*]], 1: bb2, otherwise: bb1];
2024-01-12 01:22:33 -06:00
// CHECK: [[target_bb]]: {
2024-01-08 00:03:42 -06:00
// CHECK: [[x1]] = const 0_i32;
let x1 = match e1 { E::V1(x11) => x11, E::V2(x12) => x12 };
2023-05-13 09:19:31 -05:00
static RC: &E = &E::V2(4);
2024-01-08 00:03:42 -06:00
// CHECK: [[t:_.*]] = const {alloc2: &&E};
// CHECK: [[e2]] = (*[[t]]);
let e2 = RC;
2024-01-12 01:22:33 -06:00
// CHECK: switchInt({{move _.*}}) -> {{.*}}
2024-01-08 00:03:42 -06:00
// FIXME: add checks for x2. Currently, their MIRs are not symmetric in the two
// switch branches.
// One is `_9 = &(*_12) and another is `_9 = _11`. It is different from what we can
// get by printing MIR directly. It is better to check if there are any bugs in the
// MIR passes around this stage.
let x2 = match e2 { E::V1(x21) => x21, E::V2(x22) => x22 };
2023-05-13 09:19:31 -05:00
}
#[rustc_layout_scalar_valid_range_start(1)]
#[rustc_nonnull_optimization_guaranteed]
struct NonZeroUsize(usize);
// EMIT_MIR enum.mutate_discriminant.DataflowConstProp.diff
2024-01-08 00:03:42 -06:00
// CHECK-LABEL: fn mutate_discriminant(
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
fn mutate_discriminant() -> u8 {
mir!(
let x: Option<NonZeroUsize>;
{
SetDiscriminant(x, 1);
// This assignment overwrites the niche in which the discriminant is stored.
place!(Field(Field(Variant(x, 1), 0), 0)) = 0_usize;
// So we cannot know the value of this discriminant.
2024-01-08 00:03:42 -06:00
2024-01-12 01:22:33 -06:00
// CHECK: [[a:_.*]] = discriminant({{_.*}});
let a = Discriminant(x);
2024-01-08 00:03:42 -06:00
2024-01-12 01:22:33 -06:00
// CHECK: switchInt([[a]]) -> [0: {{bb.*}}, otherwise: {{bb.*}}];
match a {
0 => bb1,
_ => bad,
}
}
bb1 = {
RET = 1;
Return()
}
bad = {
RET = 2;
Unreachable()
}
)
}
2023-02-18 03:35:52 -06:00
// EMIT_MIR enum.multiple.DataflowConstProp.diff
2024-01-08 00:03:42 -06:00
// CHECK-LABEL: fn multiple(
2023-02-18 03:35:52 -06:00
fn multiple(x: bool, i: u8) {
2024-01-08 00:03:42 -06:00
// CHECK: debug x => [[x:_.*]];
// CHECK: debug e => [[e:_.*]];
// CHECK: debug x2 => [[x2:_.*]];
2024-01-12 22:50:28 -06:00
// CHECK: debug y => [[y:_.*]];
2023-02-18 03:35:52 -06:00
let e = if x {
2024-01-12 01:22:33 -06:00
// CHECK: [[e]] = Option::<u8>::Some(move {{_.*}});
2023-02-18 03:35:52 -06:00
Some(i)
} else {
2024-01-08 00:03:42 -06:00
// CHECK: [[e]] = Option::<u8>::None;
2023-02-18 03:35:52 -06:00
None
};
// The dataflow state must have:
// discriminant(e) => Top
// (e as Some).0 => Top
2024-01-08 00:03:42 -06:00
// CHECK: [[x2]] = const 0_u8;
2024-01-20 10:22:07 -06:00
// CHECK: [[some:_.*]] = (({{_.*}} as Some).0: u8)
2024-01-12 22:50:28 -06:00
// CHECK: [[x2]] = [[some]];
2024-01-08 00:03:42 -06:00
let x2 = match e { Some(i) => i, None => 0 };
2024-01-12 22:50:28 -06:00
2024-01-08 00:03:42 -06:00
// Therefore, `x2` should be `Top` here, and no replacement shall happen.
2024-01-12 22:50:28 -06:00
// CHECK-NOT: [[y]] = const
// CHECK: [[y]] = [[x2]];
// CHECK-NOT: [[y]] = const
2024-01-08 00:03:42 -06:00
let y = x2;
2023-02-18 03:35:52 -06:00
}
fn main() {
simple();
2023-05-13 07:30:40 -05:00
constant();
2023-05-13 09:19:31 -05:00
statics();
mutate_discriminant();
2023-02-18 03:35:52 -06:00
multiple(false, 5);
}