mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
implemented separate_const_switch MIR opt
un-update itertools improve predecessor amount short-circuiting cleanup and comments somewhat improved drawing
This commit is contained in:
parent
b8be3162d7
commit
a77e2ad533
@ -48,6 +48,7 @@ pub mod remove_unneeded_drops;
|
||||
pub mod remove_zsts;
|
||||
pub mod required_consts;
|
||||
pub mod rustc_peek;
|
||||
pub mod separate_const_switch;
|
||||
pub mod simplify;
|
||||
pub mod simplify_branches;
|
||||
pub mod simplify_comparison_integral;
|
||||
@ -501,6 +502,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
// inst combine is after MatchBranchSimplification to clean up Ne(_1, false)
|
||||
&multiple_return_terminators::MultipleReturnTerminators,
|
||||
&instcombine::InstCombine,
|
||||
&separate_const_switch::SeparateConstSwitch,
|
||||
&const_prop::ConstProp,
|
||||
&simplify_branches::SimplifyBranches::new("after-const-prop"),
|
||||
&early_otherwise_branch::EarlyOtherwiseBranch,
|
||||
|
343
compiler/rustc_mir/src/transform/separate_const_switch.rs
Normal file
343
compiler/rustc_mir/src/transform/separate_const_switch.rs
Normal file
@ -0,0 +1,343 @@
|
||||
//! A pass that duplicates switch-terminated blocks
|
||||
//! into a new copy for each predecessor, provided
|
||||
//! the predecessor sets the value being switched
|
||||
//! over to a constant.
|
||||
//!
|
||||
//! The purpose of this pass is to help constant
|
||||
//! propagation passes to simplify the switch terminator
|
||||
//! of the copied blocks into gotos when some predecessors
|
||||
//! statically determine the output of switches.
|
||||
//!
|
||||
//! ```text
|
||||
//! x = 12 --- ---> something
|
||||
//! \ / 12
|
||||
//! --> switch x
|
||||
//! / \ otherwise
|
||||
//! x = y --- ---> something else
|
||||
//! ```
|
||||
//! becomes
|
||||
//! ```text
|
||||
//! x = 12 ---> switch x ------> something
|
||||
//! \ / 12
|
||||
//! X
|
||||
//! / \ otherwise
|
||||
//! x = y ---> switch x ------> something else
|
||||
//! ```
|
||||
//! so it can hopefully later be turned by another pass into
|
||||
//! ```text
|
||||
//! x = 12 --------------------> something
|
||||
//! / 12
|
||||
//! /
|
||||
//! / otherwise
|
||||
//! x = y ---- switch x ------> something else
|
||||
//! ```
|
||||
//!
|
||||
//! This optimization is meant to cover simple cases
|
||||
//! like `?` desugaring. For now, it thus focuses on
|
||||
//! simplicity rather than completeness (it notably
|
||||
//! sometimes duplicates abusively).
|
||||
|
||||
use crate::transform::MirPass;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
pub struct SeparateConstSwitch;
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for SeparateConstSwitch {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
if tcx.sess.mir_opt_level() < 4 {
|
||||
return;
|
||||
}
|
||||
|
||||
// If execution did something, applying a simplification layer
|
||||
// helps later passes optimize the copy away.
|
||||
if separate_const_switch(body) > 0 {
|
||||
super::simplify::simplify_cfg(tcx, body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the amount of blocks that were duplicated
|
||||
pub fn separate_const_switch<'tcx>(body: &mut Body<'tcx>) -> usize {
|
||||
let mut new_blocks: SmallVec<[(BasicBlock, BasicBlock); 6]> = SmallVec::new();
|
||||
let predecessors = body.predecessors();
|
||||
'block_iter: for (block_id, block) in body.basic_blocks().iter_enumerated() {
|
||||
if let TerminatorKind::SwitchInt {
|
||||
discr: Operand::Copy(switch_place) | Operand::Move(switch_place),
|
||||
..
|
||||
} = block.terminator().kind
|
||||
{
|
||||
// If the block is on an unwind path, do not
|
||||
// apply the optimization as unwind paths
|
||||
// rely on a unique parent invariant
|
||||
if block.is_cleanup {
|
||||
continue 'block_iter;
|
||||
}
|
||||
|
||||
// If the block has fewer than 2 predecessors, ignore it
|
||||
// we could maybe chain blocks that have exactly one
|
||||
// predecessor, but for now we ignore that
|
||||
if predecessors[block_id].len() < 2 {
|
||||
continue 'block_iter;
|
||||
}
|
||||
|
||||
// First, let's find a non-const place
|
||||
// that determines the result of the switch
|
||||
if let Some(switch_place) = find_determining_place(switch_place, block) {
|
||||
// We now have an input place for which it would
|
||||
// be interesting if predecessors assigned it from a const
|
||||
|
||||
let mut predecessors_left = predecessors[block_id].len();
|
||||
'predec_iter: for predecessor_id in predecessors[block_id].iter().copied() {
|
||||
let predecessor = &body.basic_blocks()[predecessor_id];
|
||||
|
||||
// First we make sure the predecessor jumps
|
||||
// in a reasonable way
|
||||
match &predecessor.terminator().kind {
|
||||
// The following terminators are
|
||||
// unconditionally valid
|
||||
TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } => {}
|
||||
|
||||
TerminatorKind::FalseEdge { real_target, .. } => {
|
||||
if *real_target != block_id {
|
||||
continue 'predec_iter;
|
||||
}
|
||||
}
|
||||
|
||||
// The following terminators are not allowed
|
||||
TerminatorKind::Resume
|
||||
| TerminatorKind::Drop { .. }
|
||||
| TerminatorKind::DropAndReplace { .. }
|
||||
| TerminatorKind::Call { .. }
|
||||
| TerminatorKind::Assert { .. }
|
||||
| TerminatorKind::FalseUnwind { .. }
|
||||
| TerminatorKind::Yield { .. }
|
||||
| TerminatorKind::Abort
|
||||
| TerminatorKind::Return
|
||||
| TerminatorKind::Unreachable
|
||||
| TerminatorKind::InlineAsm { .. }
|
||||
| TerminatorKind::GeneratorDrop => {
|
||||
continue 'predec_iter;
|
||||
}
|
||||
}
|
||||
|
||||
if is_likely_const(switch_place, predecessor) {
|
||||
new_blocks.push((predecessor_id, block_id));
|
||||
predecessors_left -= 1;
|
||||
if predecessors_left < 2 {
|
||||
// If the original block only has one predecessor left,
|
||||
// we have nothing left to do
|
||||
break 'predec_iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Once the analysis is done, perform the duplication
|
||||
let body_span = body.span;
|
||||
let copied_blocks = new_blocks.len();
|
||||
let blocks = body.basic_blocks_mut();
|
||||
for (pred_id, target_id) in new_blocks {
|
||||
let new_block = blocks[target_id].clone();
|
||||
let new_block_id = blocks.push(new_block);
|
||||
let terminator = blocks[pred_id].terminator_mut();
|
||||
|
||||
match terminator.kind {
|
||||
TerminatorKind::Goto { ref mut target } => {
|
||||
*target = new_block_id;
|
||||
}
|
||||
|
||||
TerminatorKind::FalseEdge { ref mut real_target, .. } => {
|
||||
if *real_target == target_id {
|
||||
*real_target = new_block_id;
|
||||
}
|
||||
}
|
||||
|
||||
TerminatorKind::SwitchInt { ref mut targets, .. } => {
|
||||
targets.all_targets_mut().iter_mut().for_each(|x| {
|
||||
if *x == target_id {
|
||||
*x = new_block_id;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TerminatorKind::Resume
|
||||
| TerminatorKind::Abort
|
||||
| TerminatorKind::Return
|
||||
| TerminatorKind::Unreachable
|
||||
| TerminatorKind::GeneratorDrop
|
||||
| TerminatorKind::Assert { .. }
|
||||
| TerminatorKind::DropAndReplace { .. }
|
||||
| TerminatorKind::FalseUnwind { .. }
|
||||
| TerminatorKind::Drop { .. }
|
||||
| TerminatorKind::Call { .. }
|
||||
| TerminatorKind::InlineAsm { .. }
|
||||
| TerminatorKind::Yield { .. } => {
|
||||
span_bug!(
|
||||
body_span,
|
||||
"basic block terminator had unexpected kind {:?}",
|
||||
&terminator.kind
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
copied_blocks
|
||||
}
|
||||
|
||||
/// This function describes a rough heuristic guessing
|
||||
/// whether a place is last set with a const within the block.
|
||||
/// Notably, it will be overly pessimistic in cases that are already
|
||||
/// not handled by `separate_const_switch`.
|
||||
fn is_likely_const<'tcx>(mut tracked_place: Place<'tcx>, block: &BasicBlockData<'tcx>) -> bool {
|
||||
for statement in block.statements.iter().rev() {
|
||||
match &statement.kind {
|
||||
StatementKind::Assign(assign) => {
|
||||
if assign.0 == tracked_place {
|
||||
match assign.1 {
|
||||
// These rvalues are definitely constant
|
||||
Rvalue::Use(Operand::Constant(_))
|
||||
| Rvalue::Ref(_, _, _)
|
||||
| Rvalue::AddressOf(_, _)
|
||||
| Rvalue::Cast(_, Operand::Constant(_), _)
|
||||
| Rvalue::NullaryOp(_, _)
|
||||
| Rvalue::UnaryOp(_, Operand::Constant(_)) => return true,
|
||||
|
||||
// These rvalues make things ambiguous
|
||||
Rvalue::Repeat(_, _)
|
||||
| Rvalue::ThreadLocalRef(_)
|
||||
| Rvalue::Len(_)
|
||||
| Rvalue::BinaryOp(_, _)
|
||||
| Rvalue::CheckedBinaryOp(_, _)
|
||||
| Rvalue::Aggregate(_, _) => return false,
|
||||
|
||||
// These rvalues move the place to track
|
||||
Rvalue::Cast(_, Operand::Copy(place) | Operand::Move(place), _)
|
||||
| Rvalue::Use(Operand::Copy(place) | Operand::Move(place))
|
||||
| Rvalue::UnaryOp(_, Operand::Copy(place) | Operand::Move(place))
|
||||
| Rvalue::Discriminant(place) => tracked_place = place,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the discriminant is set, it is always set
|
||||
// as a constant, so the job is done.
|
||||
// As we are **ignoring projections**, if the place
|
||||
// we are tracking sees its discriminant be set,
|
||||
// that means we had to be tracking the discriminant
|
||||
// specifically (as it is impossible to switch over
|
||||
// an enum directly, and if we were switching over
|
||||
// its content, we would have had to at least cast it to
|
||||
// some variant first)
|
||||
StatementKind::SetDiscriminant { place, .. } => {
|
||||
if **place == tracked_place {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// If inline assembly is found, we probably should
|
||||
// not try to analyze the code
|
||||
StatementKind::LlvmInlineAsm(_) => return false,
|
||||
|
||||
// These statements have no influence on the place
|
||||
// we are interested in
|
||||
StatementKind::FakeRead(_)
|
||||
| StatementKind::StorageLive(_)
|
||||
| StatementKind::Retag(_, _)
|
||||
| StatementKind::AscribeUserType(_, _)
|
||||
| StatementKind::Coverage(_)
|
||||
| StatementKind::StorageDead(_)
|
||||
| StatementKind::CopyNonOverlapping(_)
|
||||
| StatementKind::Nop => {}
|
||||
}
|
||||
}
|
||||
|
||||
// If no good reason for the place to be const is found,
|
||||
// give up. We could maybe go up predecessors, but in
|
||||
// most cases giving up now should be sufficient.
|
||||
false
|
||||
}
|
||||
|
||||
/// Finds a unique place that entirely determines the value
|
||||
/// of `switch_place`, if it exists. This is only a heuristic.
|
||||
/// Ideally we would like to track multiple determining places
|
||||
/// for some edge cases, but one is enough for a lot of situations.
|
||||
fn find_determining_place<'tcx>(
|
||||
mut switch_place: Place<'tcx>,
|
||||
block: &BasicBlockData<'tcx>,
|
||||
) -> Option<Place<'tcx>> {
|
||||
for statement in block.statements.iter().rev() {
|
||||
match &statement.kind {
|
||||
StatementKind::Assign(op) => {
|
||||
if op.0 != switch_place {
|
||||
continue;
|
||||
}
|
||||
|
||||
match op.1 {
|
||||
// The following rvalues move the place
|
||||
// that may be const in the predecessor
|
||||
Rvalue::Use(Operand::Move(new) | Operand::Copy(new))
|
||||
| Rvalue::UnaryOp(_, Operand::Copy(new) | Operand::Move(new))
|
||||
| Rvalue::Cast(_, Operand::Move(new) | Operand::Copy(new), _)
|
||||
| Rvalue::Repeat(Operand::Move(new) | Operand::Copy(new), _)
|
||||
| Rvalue::Discriminant(new)
|
||||
=> switch_place = new,
|
||||
|
||||
// The following rvalues might still make the block
|
||||
// be valid but for now we reject them
|
||||
Rvalue::Len(_)
|
||||
| Rvalue::Ref(_, _, _)
|
||||
| Rvalue::BinaryOp(_, _)
|
||||
| Rvalue::CheckedBinaryOp(_, _)
|
||||
| Rvalue::Aggregate(_, _)
|
||||
|
||||
// The following rvalues definitely mean we cannot
|
||||
// or should not apply this optimization
|
||||
| Rvalue::Use(Operand::Constant(_))
|
||||
| Rvalue::Repeat(Operand::Constant(_), _)
|
||||
| Rvalue::ThreadLocalRef(_)
|
||||
| Rvalue::AddressOf(_, _)
|
||||
| Rvalue::NullaryOp(_, _)
|
||||
| Rvalue::UnaryOp(_, Operand::Constant(_))
|
||||
| Rvalue::Cast(_, Operand::Constant(_), _)
|
||||
=> return None,
|
||||
}
|
||||
}
|
||||
|
||||
// These statements have no influence on the place
|
||||
// we are interested in
|
||||
StatementKind::FakeRead(_)
|
||||
| StatementKind::StorageLive(_)
|
||||
| StatementKind::StorageDead(_)
|
||||
| StatementKind::Retag(_, _)
|
||||
| StatementKind::AscribeUserType(_, _)
|
||||
| StatementKind::Coverage(_)
|
||||
| StatementKind::CopyNonOverlapping(_)
|
||||
| StatementKind::Nop => {}
|
||||
|
||||
// If inline assembly is found, we probably should
|
||||
// not try to analyze the code
|
||||
StatementKind::LlvmInlineAsm(_) => return None,
|
||||
|
||||
// If the discriminant is set, it is always set
|
||||
// as a constant, so the job is already done.
|
||||
// As we are **ignoring projections**, if the place
|
||||
// we are tracking sees its discriminant be set,
|
||||
// that means we had to be tracking the discriminant
|
||||
// specifically (as it is impossible to switch over
|
||||
// an enum directly, and if we were switching over
|
||||
// its content, we would have had to at least cast it to
|
||||
// some variant first)
|
||||
StatementKind::SetDiscriminant { place, .. } => {
|
||||
if **place == switch_place {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(switch_place)
|
||||
}
|
140
src/test/mir-opt/separate_const_switch.identity.ConstProp.diff
Normal file
140
src/test/mir-opt/separate_const_switch.identity.ConstProp.diff
Normal file
@ -0,0 +1,140 @@
|
||||
- // MIR for `identity` before ConstProp
|
||||
+ // MIR for `identity` after ConstProp
|
||||
|
||||
fn identity(_1: Result<i32, i32>) -> Result<i32, i32> {
|
||||
debug x => _1; // in scope 0 at $DIR/separate_const_switch.rs:28:13: 28:14
|
||||
let mut _0: std::result::Result<i32, i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:28:37: 28:53
|
||||
let mut _2: i32; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _3: std::ops::ControlFlow<std::result::Result<std::convert::Infallible, i32>, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _4: std::result::Result<i32, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
|
||||
let mut _5: isize; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
let _6: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
let mut _7: !; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
let mut _8: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
let _9: i32; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 1 {
|
||||
debug residual => _6; // in scope 1 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
scope 2 {
|
||||
scope 8 (inlined <Result<i32, i32> as FromResidual<Result<Infallible, i32>>>::from_residual) { // at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
debug residual => _8; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let _16: i32; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _17: i32; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _18: i32; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 9 {
|
||||
debug e => _16; // in scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 10 (inlined <i32 as From<i32>>::from) { // at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
debug t => _18; // in scope 10 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scope 3 {
|
||||
debug val => _9; // in scope 3 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 4 {
|
||||
}
|
||||
}
|
||||
scope 5 (inlined <Result<i32, i32> as Try>::branch) { // at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
debug self => _4; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _10: isize; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let _11: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _12: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let _13: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _14: std::result::Result<std::convert::Infallible, i32>; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _15: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 6 {
|
||||
debug v => _11; // in scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
scope 7 {
|
||||
debug e => _13; // in scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_3); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_4); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
|
||||
_4 = _1; // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
|
||||
StorageLive(_10); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_10 = discriminant(_4); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
switchInt(move _10) -> [0_isize: bb5, 1_isize: bb3, otherwise: bb4]; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageLive(_9); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_9 = ((_3 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_2 = _9; // scope 4 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_9); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
((_0 as Ok).0: i32) = move _2; // scope 0 at $DIR/separate_const_switch.rs:29:5: 29:11
|
||||
discriminant(_0) = 0; // scope 0 at $DIR/separate_const_switch.rs:29:5: 29:11
|
||||
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:29:10: 29:11
|
||||
StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:30:1: 30:2
|
||||
return; // scope 0 at $DIR/separate_const_switch.rs:30:2: 30:2
|
||||
}
|
||||
|
||||
bb2: {
|
||||
StorageLive(_6); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
_6 = ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageLive(_8); // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
_8 = _6; // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageLive(_16); // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_16 = move ((_8 as Err).0: i32); // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_17); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_18); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_18 = move _16; // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_17 = move _18; // scope 10 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_18); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_0 as Err).0: i32) = move _17; // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_0) = 1; // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_17); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_16); // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_8); // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:29:10: 29:11
|
||||
StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:30:1: 30:2
|
||||
return; // scope 0 at $DIR/separate_const_switch.rs:30:2: 30:2
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageLive(_13); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_13 = move ((_4 as Err).0: i32); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_14); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_15); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_15 = move _13; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_14 as Err).0: i32) = move _15; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_14) = 1; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_15); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>) = move _14; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_3) = 1; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_14); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_13); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_10); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
- _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
- switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
+ _5 = const 1_isize; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
+ switchInt(const 1_isize) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
}
|
||||
|
||||
bb4: {
|
||||
unreachable; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageLive(_11); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_11 = move ((_4 as Ok).0: i32); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_12); // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_12 = move _11; // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_3 as Continue).0: i32) = move _12; // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_3) = 0; // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_12); // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_11); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_10); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
- _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
- switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
+ _5 = const 0_isize; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
+ switchInt(const 0_isize) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,122 @@
|
||||
// MIR for `identity` after PreCodegen
|
||||
|
||||
fn identity(_1: Result<i32, i32>) -> Result<i32, i32> {
|
||||
debug x => _1; // in scope 0 at $DIR/separate_const_switch.rs:28:13: 28:14
|
||||
let mut _0: std::result::Result<i32, i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:28:37: 28:53
|
||||
let mut _2: i32; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _3: std::ops::ControlFlow<std::result::Result<std::convert::Infallible, i32>, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _4: std::result::Result<i32, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
|
||||
let _5: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
let mut _6: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
let _7: i32; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 1 {
|
||||
debug residual => _5; // in scope 1 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
scope 2 {
|
||||
scope 8 (inlined <Result<i32, i32> as FromResidual<Result<Infallible, i32>>>::from_residual) { // at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
debug residual => _6; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let _14: i32; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _15: i32; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _16: i32; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 9 {
|
||||
debug e => _14; // in scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 10 (inlined <i32 as From<i32>>::from) { // at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
debug t => _16; // in scope 10 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scope 3 {
|
||||
debug val => _7; // in scope 3 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 4 {
|
||||
}
|
||||
}
|
||||
scope 5 (inlined <Result<i32, i32> as Try>::branch) { // at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
debug self => _4; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _8: isize; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let _9: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _10: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let _11: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _12: std::result::Result<std::convert::Infallible, i32>; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _13: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 6 {
|
||||
debug v => _9; // in scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
scope 7 {
|
||||
debug e => _11; // in scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_3); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_4); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
|
||||
_4 = _1; // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
|
||||
StorageLive(_8); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_8 = discriminant(_4); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
switchInt(move _8) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageLive(_11); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_11 = move ((_4 as Err).0: i32); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_12); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_13); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_13 = move _11; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_12 as Err).0: i32) = move _13; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_12) = 1; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_13); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>) = move _12; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_3) = 1; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_12); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_11); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_8); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageLive(_5); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
_5 = ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageLive(_6); // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
_6 = _5; // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageLive(_14); // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_14 = move ((_6 as Err).0: i32); // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_15); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_16); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_16 = move _14; // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_15 = move _16; // scope 10 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_16); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_0 as Err).0: i32) = move _15; // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_0) = 1; // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_15); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_14); // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_6); // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageDead(_5); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:29:10: 29:11
|
||||
StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:30:1: 30:2
|
||||
return; // scope 0 at $DIR/separate_const_switch.rs:30:2: 30:2
|
||||
}
|
||||
|
||||
bb2: {
|
||||
unreachable; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageLive(_9); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_9 = move ((_4 as Ok).0: i32); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_10); // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_10 = move _9; // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_3 as Continue).0: i32) = move _10; // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_3) = 0; // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_10); // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_9); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_8); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageLive(_7); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_7 = ((_3 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_2 = _7; // scope 4 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_7); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
((_0 as Ok).0: i32) = move _2; // scope 0 at $DIR/separate_const_switch.rs:29:5: 29:11
|
||||
discriminant(_0) = 0; // scope 0 at $DIR/separate_const_switch.rs:29:5: 29:11
|
||||
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:29:10: 29:11
|
||||
StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:30:1: 30:2
|
||||
return; // scope 0 at $DIR/separate_const_switch.rs:30:2: 30:2
|
||||
}
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
- // MIR for `identity` before SeparateConstSwitch
|
||||
+ // MIR for `identity` after SeparateConstSwitch
|
||||
|
||||
fn identity(_1: Result<i32, i32>) -> Result<i32, i32> {
|
||||
debug x => _1; // in scope 0 at $DIR/separate_const_switch.rs:28:13: 28:14
|
||||
let mut _0: std::result::Result<i32, i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:28:37: 28:53
|
||||
let mut _2: i32; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _3: std::ops::ControlFlow<std::result::Result<std::convert::Infallible, i32>, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _4: std::result::Result<i32, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
|
||||
let mut _5: isize; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
let _6: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
let mut _7: !; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
let mut _8: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
let _9: i32; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 1 {
|
||||
debug residual => _6; // in scope 1 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
scope 2 {
|
||||
scope 8 (inlined <Result<i32, i32> as FromResidual<Result<Infallible, i32>>>::from_residual) { // at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
debug residual => _8; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let _16: i32; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _17: i32; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _18: i32; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 9 {
|
||||
debug e => _16; // in scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 10 (inlined <i32 as From<i32>>::from) { // at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
debug t => _18; // in scope 10 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scope 3 {
|
||||
debug val => _9; // in scope 3 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 4 {
|
||||
}
|
||||
}
|
||||
scope 5 (inlined <Result<i32, i32> as Try>::branch) { // at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
debug self => _4; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _10: isize; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let _11: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _12: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let _13: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _14: std::result::Result<std::convert::Infallible, i32>; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _15: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 6 {
|
||||
debug v => _11; // in scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
scope 7 {
|
||||
debug e => _13; // in scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_3); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_4); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
|
||||
_4 = _1; // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
|
||||
StorageLive(_10); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_10 = discriminant(_4); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
- switchInt(move _10) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
+ switchInt(move _10) -> [0_isize: bb5, 1_isize: bb3, otherwise: bb4]; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
|
||||
bb1: {
|
||||
- StorageDead(_10); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
- StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
- _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
- switchInt(move _5) -> [0_isize: bb2, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
- }
|
||||
-
|
||||
- bb2: {
|
||||
StorageLive(_9); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_9 = ((_3 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_2 = _9; // scope 4 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_9); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
((_0 as Ok).0: i32) = move _2; // scope 0 at $DIR/separate_const_switch.rs:29:5: 29:11
|
||||
discriminant(_0) = 0; // scope 0 at $DIR/separate_const_switch.rs:29:5: 29:11
|
||||
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:29:10: 29:11
|
||||
StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:30:1: 30:2
|
||||
return; // scope 0 at $DIR/separate_const_switch.rs:30:2: 30:2
|
||||
}
|
||||
|
||||
- bb3: {
|
||||
+ bb2: {
|
||||
StorageLive(_6); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
_6 = ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageLive(_8); // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
_8 = _6; // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageLive(_16); // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_16 = move ((_8 as Err).0: i32); // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_17); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_18); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_18 = move _16; // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_17 = move _18; // scope 10 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_18); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_0 as Err).0: i32) = move _17; // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_0) = 1; // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_17); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_16); // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_8); // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:29:10: 29:11
|
||||
StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:30:1: 30:2
|
||||
return; // scope 0 at $DIR/separate_const_switch.rs:30:2: 30:2
|
||||
}
|
||||
|
||||
- bb4: {
|
||||
+ bb3: {
|
||||
StorageLive(_13); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_13 = move ((_4 as Err).0: i32); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_14); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_15); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_15 = move _13; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_14 as Err).0: i32) = move _15; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_14) = 1; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_15); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>) = move _14; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_3) = 1; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_14); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_13); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
- goto -> bb1; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
+ StorageDead(_10); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
+ StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
+ _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
+ switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
}
|
||||
|
||||
- bb5: {
|
||||
+ bb4: {
|
||||
unreachable; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
|
||||
- bb6: {
|
||||
+ bb5: {
|
||||
StorageLive(_11); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_11 = move ((_4 as Ok).0: i32); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_12); // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_12 = move _11; // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_3 as Continue).0: i32) = move _12; // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_3) = 0; // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_12); // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_11); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
- goto -> bb1; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
+ StorageDead(_10); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
+ StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
+ _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
+ switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
}
|
||||
}
|
||||
|
35
src/test/mir-opt/separate_const_switch.rs
Normal file
35
src/test/mir-opt/separate_const_switch.rs
Normal file
@ -0,0 +1,35 @@
|
||||
#![feature(control_flow_enum)]
|
||||
#![feature(try_trait_v2)]
|
||||
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
// EMIT_MIR separate_const_switch.too_complex.SeparateConstSwitch.diff
|
||||
// EMIT_MIR separate_const_switch.too_complex.ConstProp.diff
|
||||
// EMIT_MIR separate_const_switch.too_complex.PreCodegen.after.mir
|
||||
fn too_complex(x: Result<i32, usize>) -> Option<i32> {
|
||||
// The pass should break the outer match into
|
||||
// two blocks that only have one parent each.
|
||||
// Parents are one of the two branches of the first
|
||||
// match, so a later pass can propagate constants.
|
||||
match {
|
||||
match x {
|
||||
Ok(v) => ControlFlow::Continue(v),
|
||||
Err(r) => ControlFlow::Break(r),
|
||||
}
|
||||
} {
|
||||
ControlFlow::Continue(v) => Some(v),
|
||||
ControlFlow::Break(r) => None,
|
||||
}
|
||||
}
|
||||
|
||||
// EMIT_MIR separate_const_switch.identity.SeparateConstSwitch.diff
|
||||
// EMIT_MIR separate_const_switch.identity.ConstProp.diff
|
||||
// EMIT_MIR separate_const_switch.identity.PreCodegen.after.mir
|
||||
fn identity(x: Result<i32, i32>) -> Result<i32, i32> {
|
||||
Ok(x?)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
too_complex(Ok(0));
|
||||
identity(Ok(0));
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
- // MIR for `too_complex` before ConstProp
|
||||
+ // MIR for `too_complex` after ConstProp
|
||||
|
||||
fn too_complex(_1: Result<i32, usize>) -> Option<i32> {
|
||||
debug x => _1; // in scope 0 at $DIR/separate_const_switch.rs:9:16: 9:17
|
||||
let mut _0: std::option::Option<i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:9:42: 9:53
|
||||
let mut _2: std::ops::ControlFlow<usize, i32>; // in scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
|
||||
let mut _3: isize; // in scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
|
||||
let _4: i32; // in scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
let mut _5: i32; // in scope 0 at $DIR/separate_const_switch.rs:16:44: 16:45
|
||||
let _6: usize; // in scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
let mut _7: usize; // in scope 0 at $DIR/separate_const_switch.rs:17:42: 17:43
|
||||
let mut _8: isize; // in scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
let _9: i32; // in scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
let mut _10: i32; // in scope 0 at $DIR/separate_const_switch.rs:20:42: 20:43
|
||||
let _11: usize; // in scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
scope 1 {
|
||||
debug v => _4; // in scope 1 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
}
|
||||
scope 2 {
|
||||
debug r => _6; // in scope 2 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
}
|
||||
scope 3 {
|
||||
debug v => _9; // in scope 3 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
}
|
||||
scope 4 {
|
||||
debug r => _11; // in scope 4 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
|
||||
_3 = discriminant(_1); // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
|
||||
switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageLive(_6); // scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
_6 = ((_1 as Err).0: usize); // scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
StorageLive(_7); // scope 2 at $DIR/separate_const_switch.rs:17:42: 17:43
|
||||
_7 = _6; // scope 2 at $DIR/separate_const_switch.rs:17:42: 17:43
|
||||
((_2 as Break).0: usize) = move _7; // scope 2 at $DIR/separate_const_switch.rs:17:23: 17:44
|
||||
discriminant(_2) = 1; // scope 2 at $DIR/separate_const_switch.rs:17:23: 17:44
|
||||
StorageDead(_7); // scope 2 at $DIR/separate_const_switch.rs:17:43: 17:44
|
||||
StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:17:43: 17:44
|
||||
- _8 = discriminant(_2); // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
- switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
+ _8 = const 1_isize; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
+ switchInt(const 1_isize) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
}
|
||||
|
||||
bb2: {
|
||||
StorageLive(_4); // scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
_4 = ((_1 as Ok).0: i32); // scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
StorageLive(_5); // scope 1 at $DIR/separate_const_switch.rs:16:44: 16:45
|
||||
_5 = _4; // scope 1 at $DIR/separate_const_switch.rs:16:44: 16:45
|
||||
((_2 as Continue).0: i32) = move _5; // scope 1 at $DIR/separate_const_switch.rs:16:22: 16:46
|
||||
discriminant(_2) = 0; // scope 1 at $DIR/separate_const_switch.rs:16:22: 16:46
|
||||
StorageDead(_5); // scope 1 at $DIR/separate_const_switch.rs:16:45: 16:46
|
||||
StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:16:45: 16:46
|
||||
- _8 = discriminant(_2); // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
- switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
+ _8 = const 0_isize; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
+ switchInt(const 0_isize) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageLive(_11); // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
_11 = ((_2 as Break).0: usize); // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
discriminant(_0) = 0; // scope 4 at $DIR/separate_const_switch.rs:21:34: 21:38
|
||||
StorageDead(_11); // scope 0 at $DIR/separate_const_switch.rs:21:37: 21:38
|
||||
goto -> bb5; // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
|
||||
}
|
||||
|
||||
bb4: {
|
||||
StorageLive(_9); // scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
_9 = ((_2 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
StorageLive(_10); // scope 3 at $DIR/separate_const_switch.rs:20:42: 20:43
|
||||
_10 = _9; // scope 3 at $DIR/separate_const_switch.rs:20:42: 20:43
|
||||
((_0 as Some).0: i32) = move _10; // scope 3 at $DIR/separate_const_switch.rs:20:37: 20:44
|
||||
discriminant(_0) = 1; // scope 3 at $DIR/separate_const_switch.rs:20:37: 20:44
|
||||
StorageDead(_10); // scope 3 at $DIR/separate_const_switch.rs:20:43: 20:44
|
||||
StorageDead(_9); // scope 0 at $DIR/separate_const_switch.rs:20:43: 20:44
|
||||
goto -> bb5; // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:23:1: 23:2
|
||||
return; // scope 0 at $DIR/separate_const_switch.rs:23:2: 23:2
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,74 @@
|
||||
// MIR for `too_complex` after PreCodegen
|
||||
|
||||
fn too_complex(_1: Result<i32, usize>) -> Option<i32> {
|
||||
debug x => _1; // in scope 0 at $DIR/separate_const_switch.rs:9:16: 9:17
|
||||
let mut _0: std::option::Option<i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:9:42: 9:53
|
||||
let mut _2: std::ops::ControlFlow<usize, i32>; // in scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
|
||||
let mut _3: isize; // in scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
|
||||
let _4: i32; // in scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
let mut _5: i32; // in scope 0 at $DIR/separate_const_switch.rs:16:44: 16:45
|
||||
let _6: usize; // in scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
let mut _7: usize; // in scope 0 at $DIR/separate_const_switch.rs:17:42: 17:43
|
||||
let _8: i32; // in scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
let mut _9: i32; // in scope 0 at $DIR/separate_const_switch.rs:20:42: 20:43
|
||||
let _10: usize; // in scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
scope 1 {
|
||||
debug v => _4; // in scope 1 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
}
|
||||
scope 2 {
|
||||
debug r => _6; // in scope 2 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
}
|
||||
scope 3 {
|
||||
debug v => _8; // in scope 3 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
}
|
||||
scope 4 {
|
||||
debug r => _10; // in scope 4 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
|
||||
_3 = discriminant(_1); // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
|
||||
switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageLive(_6); // scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
_6 = ((_1 as Err).0: usize); // scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
StorageLive(_7); // scope 2 at $DIR/separate_const_switch.rs:17:42: 17:43
|
||||
_7 = _6; // scope 2 at $DIR/separate_const_switch.rs:17:42: 17:43
|
||||
((_2 as Break).0: usize) = move _7; // scope 2 at $DIR/separate_const_switch.rs:17:23: 17:44
|
||||
discriminant(_2) = 1; // scope 2 at $DIR/separate_const_switch.rs:17:23: 17:44
|
||||
StorageDead(_7); // scope 2 at $DIR/separate_const_switch.rs:17:43: 17:44
|
||||
StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:17:43: 17:44
|
||||
StorageLive(_10); // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
_10 = ((_2 as Break).0: usize); // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
discriminant(_0) = 0; // scope 4 at $DIR/separate_const_switch.rs:21:34: 21:38
|
||||
StorageDead(_10); // scope 0 at $DIR/separate_const_switch.rs:21:37: 21:38
|
||||
goto -> bb3; // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
|
||||
}
|
||||
|
||||
bb2: {
|
||||
StorageLive(_4); // scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
_4 = ((_1 as Ok).0: i32); // scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
StorageLive(_5); // scope 1 at $DIR/separate_const_switch.rs:16:44: 16:45
|
||||
_5 = _4; // scope 1 at $DIR/separate_const_switch.rs:16:44: 16:45
|
||||
((_2 as Continue).0: i32) = move _5; // scope 1 at $DIR/separate_const_switch.rs:16:22: 16:46
|
||||
discriminant(_2) = 0; // scope 1 at $DIR/separate_const_switch.rs:16:22: 16:46
|
||||
StorageDead(_5); // scope 1 at $DIR/separate_const_switch.rs:16:45: 16:46
|
||||
StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:16:45: 16:46
|
||||
StorageLive(_8); // scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
_8 = ((_2 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
StorageLive(_9); // scope 3 at $DIR/separate_const_switch.rs:20:42: 20:43
|
||||
_9 = _8; // scope 3 at $DIR/separate_const_switch.rs:20:42: 20:43
|
||||
((_0 as Some).0: i32) = move _9; // scope 3 at $DIR/separate_const_switch.rs:20:37: 20:44
|
||||
discriminant(_0) = 1; // scope 3 at $DIR/separate_const_switch.rs:20:37: 20:44
|
||||
StorageDead(_9); // scope 3 at $DIR/separate_const_switch.rs:20:43: 20:44
|
||||
StorageDead(_8); // scope 0 at $DIR/separate_const_switch.rs:20:43: 20:44
|
||||
goto -> bb3; // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:23:1: 23:2
|
||||
return; // scope 0 at $DIR/separate_const_switch.rs:23:2: 23:2
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
- // MIR for `too_complex` before SeparateConstSwitch
|
||||
+ // MIR for `too_complex` after SeparateConstSwitch
|
||||
|
||||
fn too_complex(_1: Result<i32, usize>) -> Option<i32> {
|
||||
debug x => _1; // in scope 0 at $DIR/separate_const_switch.rs:9:16: 9:17
|
||||
let mut _0: std::option::Option<i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:9:42: 9:53
|
||||
let mut _2: std::ops::ControlFlow<usize, i32>; // in scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
|
||||
let mut _3: isize; // in scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
|
||||
let _4: i32; // in scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
let mut _5: i32; // in scope 0 at $DIR/separate_const_switch.rs:16:44: 16:45
|
||||
let _6: usize; // in scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
let mut _7: usize; // in scope 0 at $DIR/separate_const_switch.rs:17:42: 17:43
|
||||
let mut _8: isize; // in scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
let _9: i32; // in scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
let mut _10: i32; // in scope 0 at $DIR/separate_const_switch.rs:20:42: 20:43
|
||||
let _11: usize; // in scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
scope 1 {
|
||||
debug v => _4; // in scope 1 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
}
|
||||
scope 2 {
|
||||
debug r => _6; // in scope 2 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
}
|
||||
scope 3 {
|
||||
debug v => _9; // in scope 3 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
}
|
||||
scope 4 {
|
||||
debug r => _11; // in scope 4 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
|
||||
_3 = discriminant(_1); // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
|
||||
switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageLive(_6); // scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
_6 = ((_1 as Err).0: usize); // scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
StorageLive(_7); // scope 2 at $DIR/separate_const_switch.rs:17:42: 17:43
|
||||
_7 = _6; // scope 2 at $DIR/separate_const_switch.rs:17:42: 17:43
|
||||
((_2 as Break).0: usize) = move _7; // scope 2 at $DIR/separate_const_switch.rs:17:23: 17:44
|
||||
discriminant(_2) = 1; // scope 2 at $DIR/separate_const_switch.rs:17:23: 17:44
|
||||
StorageDead(_7); // scope 2 at $DIR/separate_const_switch.rs:17:43: 17:44
|
||||
StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:17:43: 17:44
|
||||
- goto -> bb3; // scope 0 at $DIR/separate_const_switch.rs:15:9: 18:10
|
||||
+ _8 = discriminant(_2); // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
+ switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
}
|
||||
|
||||
bb2: {
|
||||
StorageLive(_4); // scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
_4 = ((_1 as Ok).0: i32); // scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
StorageLive(_5); // scope 1 at $DIR/separate_const_switch.rs:16:44: 16:45
|
||||
_5 = _4; // scope 1 at $DIR/separate_const_switch.rs:16:44: 16:45
|
||||
((_2 as Continue).0: i32) = move _5; // scope 1 at $DIR/separate_const_switch.rs:16:22: 16:46
|
||||
discriminant(_2) = 0; // scope 1 at $DIR/separate_const_switch.rs:16:22: 16:46
|
||||
StorageDead(_5); // scope 1 at $DIR/separate_const_switch.rs:16:45: 16:46
|
||||
StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:16:45: 16:46
|
||||
- goto -> bb3; // scope 0 at $DIR/separate_const_switch.rs:15:9: 18:10
|
||||
- }
|
||||
-
|
||||
- bb3: {
|
||||
_8 = discriminant(_2); // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
- switchInt(move _8) -> [0_isize: bb5, otherwise: bb4]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
+ switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
}
|
||||
|
||||
- bb4: {
|
||||
+ bb3: {
|
||||
StorageLive(_11); // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
_11 = ((_2 as Break).0: usize); // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
discriminant(_0) = 0; // scope 4 at $DIR/separate_const_switch.rs:21:34: 21:38
|
||||
StorageDead(_11); // scope 0 at $DIR/separate_const_switch.rs:21:37: 21:38
|
||||
- goto -> bb6; // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
|
||||
+ goto -> bb5; // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
|
||||
}
|
||||
|
||||
- bb5: {
|
||||
+ bb4: {
|
||||
StorageLive(_9); // scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
_9 = ((_2 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
StorageLive(_10); // scope 3 at $DIR/separate_const_switch.rs:20:42: 20:43
|
||||
_10 = _9; // scope 3 at $DIR/separate_const_switch.rs:20:42: 20:43
|
||||
((_0 as Some).0: i32) = move _10; // scope 3 at $DIR/separate_const_switch.rs:20:37: 20:44
|
||||
discriminant(_0) = 1; // scope 3 at $DIR/separate_const_switch.rs:20:37: 20:44
|
||||
StorageDead(_10); // scope 3 at $DIR/separate_const_switch.rs:20:43: 20:44
|
||||
StorageDead(_9); // scope 0 at $DIR/separate_const_switch.rs:20:43: 20:44
|
||||
- goto -> bb6; // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
|
||||
+ goto -> bb5; // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
|
||||
}
|
||||
|
||||
- bb6: {
|
||||
+ bb5: {
|
||||
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:23:1: 23:2
|
||||
return; // scope 0 at $DIR/separate_const_switch.rs:23:2: 23:2
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user