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
9 changed files with 1055 additions and 0 deletions
|
@ -48,6 +48,7 @@ pub mod remove_unneeded_drops;
|
||||||
pub mod remove_zsts;
|
pub mod remove_zsts;
|
||||||
pub mod required_consts;
|
pub mod required_consts;
|
||||||
pub mod rustc_peek;
|
pub mod rustc_peek;
|
||||||
|
pub mod separate_const_switch;
|
||||||
pub mod simplify;
|
pub mod simplify;
|
||||||
pub mod simplify_branches;
|
pub mod simplify_branches;
|
||||||
pub mod simplify_comparison_integral;
|
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)
|
// inst combine is after MatchBranchSimplification to clean up Ne(_1, false)
|
||||||
&multiple_return_terminators::MultipleReturnTerminators,
|
&multiple_return_terminators::MultipleReturnTerminators,
|
||||||
&instcombine::InstCombine,
|
&instcombine::InstCombine,
|
||||||
|
&separate_const_switch::SeparateConstSwitch,
|
||||||
&const_prop::ConstProp,
|
&const_prop::ConstProp,
|
||||||
&simplify_branches::SimplifyBranches::new("after-const-prop"),
|
&simplify_branches::SimplifyBranches::new("after-const-prop"),
|
||||||
&early_otherwise_branch::EarlyOtherwiseBranch,
|
&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…
Add table
Reference in a new issue