mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
FileCheck annotations.
This commit is contained in:
parent
8fb99afb02
commit
a845bac6ba
@ -3,14 +3,11 @@
|
|||||||
|
|
||||||
fn disappearing_bb(_1: u8) -> u8 {
|
fn disappearing_bb(_1: u8) -> u8 {
|
||||||
let mut _0: u8;
|
let mut _0: u8;
|
||||||
let mut _2: i8;
|
let mut _2: bool;
|
||||||
let mut _3: bool;
|
let mut _3: bool;
|
||||||
let mut _4: bool;
|
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
_4 = const false;
|
_2 = const true;
|
||||||
_3 = const false;
|
|
||||||
_4 = const true;
|
|
||||||
_3 = const true;
|
_3 = const true;
|
||||||
switchInt(_1) -> [0: bb3, 1: bb3, 2: bb1, otherwise: bb2];
|
switchInt(_1) -> [0: bb3, 1: bb3, 2: bb1, otherwise: bb2];
|
||||||
}
|
}
|
||||||
@ -26,7 +23,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
bb3: {
|
bb3: {
|
||||||
_4 = const false;
|
_2 = const false;
|
||||||
goto -> bb4;
|
goto -> bb4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,7 +32,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
bb5: {
|
bb5: {
|
||||||
switchInt(_4) -> [0: bb6, otherwise: bb8];
|
switchInt(_2) -> [0: bb6, otherwise: bb8];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb6: {
|
bb6: {
|
||||||
|
@ -3,14 +3,11 @@
|
|||||||
|
|
||||||
fn disappearing_bb(_1: u8) -> u8 {
|
fn disappearing_bb(_1: u8) -> u8 {
|
||||||
let mut _0: u8;
|
let mut _0: u8;
|
||||||
let mut _2: i8;
|
let mut _2: bool;
|
||||||
let mut _3: bool;
|
let mut _3: bool;
|
||||||
let mut _4: bool;
|
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
_4 = const false;
|
_2 = const true;
|
||||||
_3 = const false;
|
|
||||||
_4 = const true;
|
|
||||||
_3 = const true;
|
_3 = const true;
|
||||||
switchInt(_1) -> [0: bb3, 1: bb3, 2: bb1, otherwise: bb2];
|
switchInt(_1) -> [0: bb3, 1: bb3, 2: bb1, otherwise: bb2];
|
||||||
}
|
}
|
||||||
@ -26,7 +23,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
bb3: {
|
bb3: {
|
||||||
_4 = const false;
|
_2 = const false;
|
||||||
goto -> bb4;
|
goto -> bb4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,7 +32,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
bb5: {
|
bb5: {
|
||||||
switchInt(_4) -> [0: bb6, otherwise: bb8];
|
switchInt(_2) -> [0: bb6, otherwise: bb8];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb6: {
|
bb6: {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// unit-test: JumpThreading
|
// unit-test: JumpThreading
|
||||||
// compile-flags: -Zmir-enable-passes=+Inline -Zinline-mir
|
// compile-flags: -Zmir-enable-passes=+Inline
|
||||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||||
|
|
||||||
#![feature(control_flow_enum)]
|
#![feature(control_flow_enum)]
|
||||||
@ -10,6 +10,31 @@ use std::intrinsics::mir::*;
|
|||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
fn too_complex(x: Result<i32, usize>) -> Option<i32> {
|
fn too_complex(x: Result<i32, usize>) -> Option<i32> {
|
||||||
|
// CHECK-LABEL: fn too_complex(
|
||||||
|
// CHECK: bb0: {
|
||||||
|
// CHECK: switchInt(move {{_.*}}) -> [0: bb3, 1: bb1, otherwise: bb2];
|
||||||
|
// CHECK: bb1: {
|
||||||
|
// CHECK: [[controlflow:_.*]] = ControlFlow::<usize, i32>::Break(
|
||||||
|
// CHECK: goto -> bb8;
|
||||||
|
// CHECK: bb2: {
|
||||||
|
// CHECK: unreachable;
|
||||||
|
// CHECK: bb3: {
|
||||||
|
// CHECK: [[controlflow]] = ControlFlow::<usize, i32>::Continue(
|
||||||
|
// CHECK: goto -> bb4;
|
||||||
|
// CHECK: bb4: {
|
||||||
|
// CHECK: goto -> bb6;
|
||||||
|
// CHECK: bb5: {
|
||||||
|
// CHECK: {{_.*}} = (([[controlflow]] as Break).0: usize);
|
||||||
|
// CHECK: _0 = Option::<i32>::None;
|
||||||
|
// CHECK: goto -> bb7;
|
||||||
|
// CHECK: bb6: {
|
||||||
|
// CHECK: {{_.*}} = (([[controlflow]] as Continue).0: i32);
|
||||||
|
// CHECK: _0 = Option::<i32>::Some(
|
||||||
|
// CHECK: goto -> bb7;
|
||||||
|
// CHECK: bb7: {
|
||||||
|
// CHECK: return;
|
||||||
|
// CHECK: bb8: {
|
||||||
|
// CHECK: goto -> bb5;
|
||||||
match {
|
match {
|
||||||
match x {
|
match x {
|
||||||
Ok(v) => ControlFlow::Continue(v),
|
Ok(v) => ControlFlow::Continue(v),
|
||||||
@ -22,6 +47,36 @@ fn too_complex(x: Result<i32, usize>) -> Option<i32> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn identity(x: Result<i32, i32>) -> Result<i32, i32> {
|
fn identity(x: Result<i32, i32>) -> Result<i32, i32> {
|
||||||
|
// CHECK-LABEL: fn identity(
|
||||||
|
// CHECK: bb0: {
|
||||||
|
// CHECK: [[x:_.*]] = _1;
|
||||||
|
// CHECK: switchInt(move {{_.*}}) -> [0: bb8, 1: bb6, otherwise: bb7];
|
||||||
|
// CHECK: bb1: {
|
||||||
|
// CHECK: goto -> bb2;
|
||||||
|
// CHECK: bb2: {
|
||||||
|
// CHECK: {{_.*}} = (([[controlflow:_.*]] as Continue).0: i32);
|
||||||
|
// CHECK: _0 = Result::<i32, i32>::Ok(
|
||||||
|
// CHECK: goto -> bb5;
|
||||||
|
// CHECK: bb3: {
|
||||||
|
// CHECK: unreachable;
|
||||||
|
// CHECK: bb4: {
|
||||||
|
// CHECK: {{_.*}} = (([[controlflow]] as Break).0: std::result::Result<std::convert::Infallible, i32>);
|
||||||
|
// CHECK: _0 = Result::<i32, i32>::Err(
|
||||||
|
// CHECK: goto -> bb5;
|
||||||
|
// CHECK: bb5: {
|
||||||
|
// CHECK: return;
|
||||||
|
// CHECK: bb6: {
|
||||||
|
// CHECK: {{_.*}} = move (([[x]] as Err).0: i32);
|
||||||
|
// CHECK: [[controlflow]] = ControlFlow::<Result<Infallible, i32>, i32>::Break(
|
||||||
|
// CHECK: goto -> bb9;
|
||||||
|
// CHECK: bb7: {
|
||||||
|
// CHECK: unreachable;
|
||||||
|
// CHECK: bb8: {
|
||||||
|
// CHECK: {{_.*}} = move (([[x]] as Ok).0: i32);
|
||||||
|
// CHECK: [[controlflow]] = ControlFlow::<Result<Infallible, i32>, i32>::Continue(
|
||||||
|
// CHECK: goto -> bb1;
|
||||||
|
// CHECK: bb9: {
|
||||||
|
// CHECK: goto -> bb4;
|
||||||
Ok(x?)
|
Ok(x?)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +87,28 @@ enum DFA {
|
|||||||
D,
|
D,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check that we do not thread through a loop header,
|
||||||
|
/// to avoid creating an irreducible CFG.
|
||||||
fn dfa() {
|
fn dfa() {
|
||||||
|
// CHECK-LABEL: fn dfa(
|
||||||
|
// CHECK: bb0: {
|
||||||
|
// CHECK: {{_.*}} = DFA::A;
|
||||||
|
// CHECK: goto -> bb1;
|
||||||
|
// CHECK: bb1: {
|
||||||
|
// CHECK: switchInt({{.*}}) -> [0: bb4, 1: bb5, 2: bb6, 3: bb2, otherwise: bb3];
|
||||||
|
// CHECK: bb2: {
|
||||||
|
// CHECK: return;
|
||||||
|
// CHECK: bb3: {
|
||||||
|
// CHECK: unreachable;
|
||||||
|
// CHECK: bb4: {
|
||||||
|
// CHECK: {{_.*}} = DFA::B;
|
||||||
|
// CHECK: goto -> bb1;
|
||||||
|
// CHECK: bb5: {
|
||||||
|
// CHECK: {{_.*}} = DFA::C;
|
||||||
|
// CHECK: goto -> bb1;
|
||||||
|
// CHECK: bb6: {
|
||||||
|
// CHECK: {{_.*}} = DFA::D;
|
||||||
|
// CHECK: goto -> bb1;
|
||||||
let mut state = DFA::A;
|
let mut state = DFA::A;
|
||||||
loop {
|
loop {
|
||||||
match state {
|
match state {
|
||||||
@ -51,7 +127,29 @@ enum CustomDiscr {
|
|||||||
C = 99,
|
C = 99,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Verify that we correctly match the discriminant value, and not its index.
|
||||||
fn custom_discr(x: bool) -> u8 {
|
fn custom_discr(x: bool) -> u8 {
|
||||||
|
// CHECK-LABEL: fn custom_discr(
|
||||||
|
// CHECK: bb0: {
|
||||||
|
// CHECK: switchInt({{.*}}) -> [0: bb2, otherwise: bb1];
|
||||||
|
// CHECK: bb1: {
|
||||||
|
// CHECK: {{_.*}} = CustomDiscr::A;
|
||||||
|
// CHECK: goto -> bb7;
|
||||||
|
// CHECK: bb2: {
|
||||||
|
// CHECK: {{_.*}} = CustomDiscr::B;
|
||||||
|
// CHECK: goto -> bb3;
|
||||||
|
// CHECK: bb3: {
|
||||||
|
// CHECK: goto -> bb4;
|
||||||
|
// CHECK: bb4: {
|
||||||
|
// CHECK: _0 = const 13_u8;
|
||||||
|
// CHECK: goto -> bb6;
|
||||||
|
// CHECK: bb5: {
|
||||||
|
// CHECK: _0 = const 5_u8;
|
||||||
|
// CHECK: goto -> bb6;
|
||||||
|
// CHECK: bb6: {
|
||||||
|
// CHECK: return;
|
||||||
|
// CHECK: bb7: {
|
||||||
|
// CHECK: goto -> bb5;
|
||||||
match if x { CustomDiscr::A } else { CustomDiscr::B } {
|
match if x { CustomDiscr::A } else { CustomDiscr::B } {
|
||||||
CustomDiscr::A => 5,
|
CustomDiscr::A => 5,
|
||||||
_ => 13,
|
_ => 13,
|
||||||
@ -60,76 +158,125 @@ fn custom_discr(x: bool) -> u8 {
|
|||||||
|
|
||||||
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
|
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
|
||||||
fn multiple_match(x: u8) -> u8 {
|
fn multiple_match(x: u8) -> u8 {
|
||||||
|
// CHECK-LABEL: fn multiple_match(
|
||||||
mir!(
|
mir!(
|
||||||
{
|
{
|
||||||
|
// CHECK: bb0: {
|
||||||
|
// CHECK: switchInt([[x:_.*]]) -> [3: bb1, otherwise: bb2];
|
||||||
match x { 3 => bb1, _ => bb2 }
|
match x { 3 => bb1, _ => bb2 }
|
||||||
}
|
}
|
||||||
bb1 = {
|
bb1 = {
|
||||||
// We know `x == 3`, so we can take `bb3`.
|
// We know `x == 3`, so we can take `bb3`.
|
||||||
|
// CHECK: bb1: {
|
||||||
|
// CHECK: {{_.*}} = [[x]];
|
||||||
|
// CHECK: goto -> bb3;
|
||||||
let y = x;
|
let y = x;
|
||||||
match y { 3 => bb3, _ => bb4 }
|
match y { 3 => bb3, _ => bb4 }
|
||||||
}
|
}
|
||||||
bb2 = {
|
bb2 = {
|
||||||
// We know `x != 3`, so we can take `bb6`.
|
// We know `x != 3`, so we can take `bb6`.
|
||||||
|
// CHECK: bb2: {
|
||||||
|
// CHECK: [[z:_.*]] = [[x]];
|
||||||
|
// CHECK: goto -> bb6;
|
||||||
let z = x;
|
let z = x;
|
||||||
match z { 3 => bb5, _ => bb6 }
|
match z { 3 => bb5, _ => bb6 }
|
||||||
}
|
}
|
||||||
bb3 = {
|
bb3 = {
|
||||||
|
// CHECK: bb3: {
|
||||||
|
// CHECK: _0 = const 5_u8;
|
||||||
|
// CHECK: return;
|
||||||
RET = 5;
|
RET = 5;
|
||||||
Return()
|
Return()
|
||||||
}
|
}
|
||||||
bb4 = {
|
bb4 = {
|
||||||
|
// CHECK: bb4: {
|
||||||
|
// CHECK: _0 = const 7_u8;
|
||||||
|
// CHECK: return;
|
||||||
RET = 7;
|
RET = 7;
|
||||||
Return()
|
Return()
|
||||||
}
|
}
|
||||||
bb5 = {
|
bb5 = {
|
||||||
|
// CHECK: bb5: {
|
||||||
|
// CHECK: _0 = const 9_u8;
|
||||||
|
// CHECK: return;
|
||||||
RET = 9;
|
RET = 9;
|
||||||
Return()
|
Return()
|
||||||
}
|
}
|
||||||
bb6 = {
|
bb6 = {
|
||||||
// We know `z != 3`, so we CANNOT take `bb7`.
|
// We know `z != 3`, so we CANNOT take `bb7`.
|
||||||
|
// CHECK: bb6: {
|
||||||
|
// CHECK: switchInt([[z]]) -> [1: bb7, otherwise: bb8];
|
||||||
match z { 1 => bb7, _ => bb8 }
|
match z { 1 => bb7, _ => bb8 }
|
||||||
}
|
}
|
||||||
bb7 = {
|
bb7 = {
|
||||||
|
// CHECK: bb7: {
|
||||||
|
// CHECK: _0 = const 9_u8;
|
||||||
|
// CHECK: return;
|
||||||
RET = 9;
|
RET = 9;
|
||||||
Return()
|
Return()
|
||||||
}
|
}
|
||||||
bb8 = {
|
bb8 = {
|
||||||
|
// CHECK: bb8: {
|
||||||
|
// CHECK: _0 = const 11_u8;
|
||||||
|
// CHECK: return;
|
||||||
RET = 11;
|
RET = 11;
|
||||||
Return()
|
Return()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Both 1-3-4 and 2-3-4 are threadable. As 1 and 2 are the only predecessors of 3,
|
||||||
|
/// verify that we only thread the 3-4 part.
|
||||||
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
|
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
|
||||||
fn duplicate_chain(x: bool) -> u8 {
|
fn duplicate_chain(x: bool) -> u8 {
|
||||||
|
// CHECK-LABEL: fn duplicate_chain(
|
||||||
mir!(
|
mir!(
|
||||||
let a: u8;
|
let a: u8;
|
||||||
{
|
{
|
||||||
|
// CHECK: bb0: {
|
||||||
|
// CHECK: switchInt({{.*}}) -> [1: bb1, otherwise: bb2];
|
||||||
match x { true => bb1, _ => bb2 }
|
match x { true => bb1, _ => bb2 }
|
||||||
}
|
}
|
||||||
bb1 = {
|
bb1 = {
|
||||||
|
// CHECK: bb1: {
|
||||||
|
// CHECK: [[a:_.*]] = const 5_u8;
|
||||||
|
// CHECK: goto -> bb3;
|
||||||
a = 5;
|
a = 5;
|
||||||
Goto(bb3)
|
Goto(bb3)
|
||||||
}
|
}
|
||||||
bb2 = {
|
bb2 = {
|
||||||
|
// CHECK: bb2: {
|
||||||
|
// CHECK: [[a]] = const 5_u8;
|
||||||
|
// CHECK: goto -> bb3;
|
||||||
a = 5;
|
a = 5;
|
||||||
Goto(bb3)
|
Goto(bb3)
|
||||||
}
|
}
|
||||||
// Verify that we do not create multiple copied of `bb3`.
|
|
||||||
bb3 = {
|
bb3 = {
|
||||||
|
// CHECK: bb3: {
|
||||||
|
// CHECK: {{_.*}} = const 13_i32;
|
||||||
|
// CHECK: goto -> bb4;
|
||||||
let b = 13;
|
let b = 13;
|
||||||
Goto(bb4)
|
Goto(bb4)
|
||||||
}
|
}
|
||||||
bb4 = {
|
bb4 = {
|
||||||
|
// CHECK: bb4: {
|
||||||
|
// CHECK: {{_.*}} = const 15_i32;
|
||||||
|
// CHECK-NOT: switchInt(
|
||||||
|
// CHECK: goto -> bb5;
|
||||||
let c = 15;
|
let c = 15;
|
||||||
match a { 5 => bb5, _ => bb6 }
|
match a { 5 => bb5, _ => bb6 }
|
||||||
}
|
}
|
||||||
bb5 = {
|
bb5 = {
|
||||||
|
// CHECK: bb5: {
|
||||||
|
// CHECK: _0 = const 7_u8;
|
||||||
|
// CHECK: return;
|
||||||
RET = 7;
|
RET = 7;
|
||||||
Return()
|
Return()
|
||||||
}
|
}
|
||||||
bb6 = {
|
bb6 = {
|
||||||
|
// CHECK: bb6: {
|
||||||
|
// CHECK: _0 = const 9_u8;
|
||||||
|
// CHECK: return;
|
||||||
RET = 9;
|
RET = 9;
|
||||||
Return()
|
Return()
|
||||||
}
|
}
|
||||||
@ -140,8 +287,13 @@ fn duplicate_chain(x: bool) -> u8 {
|
|||||||
#[rustc_nonnull_optimization_guaranteed]
|
#[rustc_nonnull_optimization_guaranteed]
|
||||||
struct NonZeroUsize(usize);
|
struct NonZeroUsize(usize);
|
||||||
|
|
||||||
|
/// Verify that we correctly discard threads that may mutate a discriminant by aliasing.
|
||||||
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
|
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
|
||||||
fn mutate_discriminant() -> u8 {
|
fn mutate_discriminant() -> u8 {
|
||||||
|
// CHECK-LABEL: fn mutate_discriminant(
|
||||||
|
// CHECK-NOT: goto -> {{bb.*}};
|
||||||
|
// CHECK: switchInt(
|
||||||
|
// CHECK-NOT: goto -> {{bb.*}};
|
||||||
mir!(
|
mir!(
|
||||||
let x: Option<NonZeroUsize>;
|
let x: Option<NonZeroUsize>;
|
||||||
{
|
{
|
||||||
@ -166,8 +318,16 @@ fn mutate_discriminant() -> u8 {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that we do not try to reason when there are mutable pointers involved.
|
/// Verify that we do not try to reason when there are mutable pointers involved.
|
||||||
fn mutable_ref() -> bool {
|
fn mutable_ref() -> bool {
|
||||||
|
// CHECK-LABEL: fn mutable_ref(
|
||||||
|
// CHECK-NOT: goto -> {{bb.*}};
|
||||||
|
// CHECK: switchInt(
|
||||||
|
// CHECK: goto -> [[bbret:bb.*]];
|
||||||
|
// CHECK: goto -> [[bbret]];
|
||||||
|
// CHECK: [[bbret]]: {
|
||||||
|
// CHECK-NOT: {{bb.*}}: {
|
||||||
|
// CHECK: return;
|
||||||
let mut x = 5;
|
let mut x = 5;
|
||||||
let a = std::ptr::addr_of_mut!(x);
|
let a = std::ptr::addr_of_mut!(x);
|
||||||
x = 7;
|
x = 7;
|
||||||
@ -179,80 +339,105 @@ fn mutable_ref() -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This function has 2 TOs: 1-3-4 and 0-1-3-4-6.
|
||||||
|
/// We verify that the second TO does not modify 3 once the first has been applied.
|
||||||
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
|
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
|
||||||
fn renumbered_bb(x: bool) -> u8 {
|
fn renumbered_bb(x: bool) -> u8 {
|
||||||
// This function has 2 TOs: 1-3-4 and 0-1-3-4-6.
|
// CHECK-LABEL: fn renumbered_bb(
|
||||||
// We verify that the second TO does not modify 3 once the first has been applied.
|
|
||||||
mir!(
|
mir!(
|
||||||
let a: bool;
|
let a: bool;
|
||||||
let b: bool;
|
let b: bool;
|
||||||
{
|
{
|
||||||
|
// CHECK: bb0: {
|
||||||
|
// CHECK: switchInt({{.*}}) -> [1: bb1, otherwise: bb2];
|
||||||
b = false;
|
b = false;
|
||||||
match x { true => bb1, _ => bb2 }
|
match x { true => bb1, _ => bb2 }
|
||||||
}
|
}
|
||||||
bb1 = {
|
bb1 = {
|
||||||
|
// CHECK: bb1: {
|
||||||
|
// CHECK: goto -> bb8;
|
||||||
a = false;
|
a = false;
|
||||||
Goto(bb3)
|
Goto(bb3)
|
||||||
}
|
}
|
||||||
bb2 = {
|
bb2 = {
|
||||||
|
// CHECK: bb2: {
|
||||||
|
// CHECK: goto -> bb3;
|
||||||
a = x;
|
a = x;
|
||||||
b = x;
|
b = x;
|
||||||
Goto(bb3)
|
Goto(bb3)
|
||||||
}
|
}
|
||||||
bb3 = {
|
bb3 = {
|
||||||
|
// CHECK: bb3: {
|
||||||
|
// CHECK: switchInt({{.*}}) -> [0: bb4, otherwise: bb5];
|
||||||
match a { false => bb4, _ => bb5 }
|
match a { false => bb4, _ => bb5 }
|
||||||
}
|
}
|
||||||
bb4 = {
|
bb4 = {
|
||||||
|
// CHECK: bb4: {
|
||||||
|
// CHECK: switchInt({{.*}}) -> [0: bb6, otherwise: bb7];
|
||||||
match b { false => bb6, _ => bb7 }
|
match b { false => bb6, _ => bb7 }
|
||||||
}
|
}
|
||||||
bb5 = {
|
bb5 = {
|
||||||
|
// CHECK: bb5: {
|
||||||
|
// CHECK: _0 = const 7_u8;
|
||||||
RET = 7;
|
RET = 7;
|
||||||
Return()
|
Return()
|
||||||
}
|
}
|
||||||
bb6 = {
|
bb6 = {
|
||||||
|
// CHECK: bb6: {
|
||||||
|
// CHECK: _0 = const 9_u8;
|
||||||
RET = 9;
|
RET = 9;
|
||||||
Return()
|
Return()
|
||||||
}
|
}
|
||||||
bb7 = {
|
bb7 = {
|
||||||
|
// CHECK: bb7: {
|
||||||
|
// CHECK: _0 = const 11_u8;
|
||||||
RET = 11;
|
RET = 11;
|
||||||
Return()
|
Return()
|
||||||
}
|
}
|
||||||
|
// Duplicate of bb3.
|
||||||
|
// CHECK: bb8: {
|
||||||
|
// CHECK-NEXT: goto -> bb9;
|
||||||
|
// Duplicate of bb4.
|
||||||
|
// CHECK: bb9: {
|
||||||
|
// CHECK-NEXT: goto -> bb6;
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This function has 3 TOs: 1-4-5, 0-1-4-7-5-8 and 3-4-7-5-6
|
||||||
|
/// After applying the first TO, we create bb9 to replace 4, and rename 1-4 edge by 1-9. The
|
||||||
|
/// second TO may try to thread non-existing edge 9-4.
|
||||||
|
/// This test verifies that we preserve semantics by bailing out of this second TO.
|
||||||
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
|
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
|
||||||
fn disappearing_bb(x: u8) -> u8 {
|
fn disappearing_bb(x: u8) -> u8 {
|
||||||
// This function has 3 TOs: 1-4-5, 0-1-4-7-5-8 and 3-4-7-5-6
|
// CHECK-LABEL: fn disappearing_bb(
|
||||||
// After applying the first TO, we create bb9 to replace 4, and rename 1-4 edge by 1-9. The
|
|
||||||
// second TO may try to thread non-existing edge 9-4.
|
|
||||||
// This test verifies that we preserve semantics by bailing out of this second TO.
|
|
||||||
mir!(
|
mir!(
|
||||||
let _11: i8;
|
let a: bool;
|
||||||
let _12: bool;
|
let b: bool;
|
||||||
let _13: bool;
|
|
||||||
{
|
{
|
||||||
_13 = false;
|
a = true;
|
||||||
_12 = false;
|
b = true;
|
||||||
_13 = true;
|
|
||||||
_12 = true;
|
|
||||||
match x { 0 => bb3, 1 => bb3, 2 => bb1, _ => bb2 }
|
match x { 0 => bb3, 1 => bb3, 2 => bb1, _ => bb2 }
|
||||||
}
|
}
|
||||||
bb1 = {
|
bb1 = {
|
||||||
_12 = false;
|
// CHECK: bb1: {
|
||||||
|
// CHECK: goto -> bb9;
|
||||||
|
b = false;
|
||||||
Goto(bb4)
|
Goto(bb4)
|
||||||
}
|
}
|
||||||
bb2 = {
|
bb2 = {
|
||||||
Unreachable()
|
Unreachable()
|
||||||
}
|
}
|
||||||
bb3 = {
|
bb3 = {
|
||||||
_13 = false;
|
// CHECK: bb3: {
|
||||||
|
// CHECK: goto -> bb10;
|
||||||
|
a = false;
|
||||||
Goto(bb4)
|
Goto(bb4)
|
||||||
}
|
}
|
||||||
bb4 = {
|
bb4 = {
|
||||||
match _12 { false => bb5, _ => bb7 }
|
match b { false => bb5, _ => bb7 }
|
||||||
}
|
}
|
||||||
bb5 = {
|
bb5 = {
|
||||||
match _13 { false => bb6, _ => bb8 }
|
match a { false => bb6, _ => bb8 }
|
||||||
}
|
}
|
||||||
bb6 = {
|
bb6 = {
|
||||||
Return()
|
Return()
|
||||||
@ -263,6 +448,10 @@ fn disappearing_bb(x: u8) -> u8 {
|
|||||||
bb8 = {
|
bb8 = {
|
||||||
Goto(bb6)
|
Goto(bb6)
|
||||||
}
|
}
|
||||||
|
// CHECK: bb9: {
|
||||||
|
// CHECK: goto -> bb5;
|
||||||
|
// CHECK: bb10: {
|
||||||
|
// CHECK: goto -> bb6;
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user