From 70ad31847d568b291253714f06b562ef1d07eda6 Mon Sep 17 00:00:00 2001 From: kadmin Date: Thu, 13 Aug 2020 21:59:47 +0000 Subject: [PATCH 1/2] Clean up some mir transform passes I noticed a few places where there were intermediates being created in MIR optimization passes, so I removed them. --- src/librustc_mir/transform/add_retag.rs | 38 ++++++++---------- src/librustc_mir/transform/deaggregator.rs | 24 ++++++------ .../transform/unreachable_prop.rs | 39 +++++++++++-------- 3 files changed, 50 insertions(+), 51 deletions(-) diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs index baa3e5e1581..324289166b9 100644 --- a/src/librustc_mir/transform/add_retag.rs +++ b/src/librustc_mir/transform/add_retag.rs @@ -86,12 +86,11 @@ impl<'tcx> MirPass<'tcx> for AddRetag { .skip(1) .take(arg_count) .map(|(local, _)| Place::from(local)) - .filter(needs_retag) - .collect::>(); + .filter(needs_retag); // Emit their retags. basic_blocks[START_BLOCK].statements.splice( 0..0, - places.into_iter().map(|place| Statement { + places.map(|place| Statement { source_info, kind: StatementKind::Retag(RetagKind::FnEntry, box (place)), }), @@ -101,29 +100,24 @@ impl<'tcx> MirPass<'tcx> for AddRetag { // PART 2 // Retag return values of functions. Also escape-to-raw the argument of `drop`. // We collect the return destinations because we cannot mutate while iterating. - let mut returns: Vec<(SourceInfo, Place<'tcx>, BasicBlock)> = Vec::new(); - for block_data in basic_blocks.iter_mut() { - match block_data.terminator().kind { - TerminatorKind::Call { ref destination, .. } => { - // Remember the return destination for later - if let Some(ref destination) = destination { - if needs_retag(&destination.0) { - returns.push(( - block_data.terminator().source_info, - destination.0, - destination.1, - )); - } + let returns = basic_blocks + .iter_mut() + .filter_map(|block_data| { + match block_data.terminator().kind { + TerminatorKind::Call { destination: Some(ref destination), .. } + if needs_retag(&destination.0) => + { + // Remember the return destination for later + Some((block_data.terminator().source_info, destination.0, destination.1)) } - } - TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => { + // `Drop` is also a call, but it doesn't return anything so we are good. - } - _ => { + TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => None, // Not a block ending in a Call -> ignore. + _ => None, } - } - } + }) + .collect::>(); // Now we go over the returns we collected to retag the return values. for (source_info, dest_place, dest_block) in returns { basic_blocks[dest_block].statements.insert( diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs index 2de701284e3..66989a90244 100644 --- a/src/librustc_mir/transform/deaggregator.rs +++ b/src/librustc_mir/transform/deaggregator.rs @@ -12,26 +12,24 @@ impl<'tcx> MirPass<'tcx> for Deaggregator { for bb in basic_blocks { bb.expand_statements(|stmt| { // FIXME(eddyb) don't match twice on `stmt.kind` (post-NLL). - if let StatementKind::Assign(box (_, ref rhs)) = stmt.kind { - if let Rvalue::Aggregate(ref kind, _) = *rhs { - // FIXME(#48193) Deaggregate arrays when it's cheaper to do so. - if let AggregateKind::Array(_) = **kind { - return None; - } - } else { + match stmt.kind { + // FIXME(#48193) Deaggregate arrays when it's cheaper to do so. + StatementKind::Assign(box ( + _, + Rvalue::Aggregate(box AggregateKind::Array(_), _), + )) => { return None; } - } else { - return None; + StatementKind::Assign(box (_, Rvalue::Aggregate(_, _))) => {} + _ => return None, } let stmt = stmt.replace_nop(); let source_info = stmt.source_info; let (lhs, kind, operands) = match stmt.kind { - StatementKind::Assign(box (lhs, rvalue)) => match rvalue { - Rvalue::Aggregate(kind, operands) => (lhs, kind, operands), - _ => bug!(), - }, + StatementKind::Assign(box (lhs, Rvalue::Aggregate(kind, operands))) => { + (lhs, kind, operands) + } _ => bug!(), }; diff --git a/src/librustc_mir/transform/unreachable_prop.rs b/src/librustc_mir/transform/unreachable_prop.rs index d9f2259030f..e2f8917156b 100644 --- a/src/librustc_mir/transform/unreachable_prop.rs +++ b/src/librustc_mir/transform/unreachable_prop.rs @@ -67,18 +67,24 @@ fn remove_successors( where F: Fn(BasicBlock) -> bool, { - match *terminator_kind { - TerminatorKind::Goto { target } if predicate(target) => Some(TerminatorKind::Unreachable), + let terminator = match *terminator_kind { + TerminatorKind::FalseEdge { real_target, imaginary_target } + if predicate(real_target) && predicate(imaginary_target) => + { + TerminatorKind::Unreachable + } + TerminatorKind::FalseUnwind { real_target, unwind } + if predicate(real_target) && unwind.map_or(true, &predicate) => + { + TerminatorKind::Unreachable + } + + TerminatorKind::Goto { target } if predicate(target) => TerminatorKind::Unreachable, TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => { let original_targets_len = targets.len(); let (otherwise, targets) = targets.split_last().unwrap(); - let retained = values - .iter() - .zip(targets.iter()) - .filter(|(_, &t)| !predicate(t)) - .collect::>(); - let mut values = retained.iter().map(|&(v, _)| *v).collect::>(); - let mut targets = retained.iter().map(|&(_, d)| *d).collect::>(); + let (mut values, mut targets): (Vec<_>, Vec<_>) = + values.iter().zip(targets.iter()).filter(|(_, &t)| !predicate(t)).unzip(); if !predicate(*otherwise) { targets.push(*otherwise); @@ -89,20 +95,21 @@ where let retained_targets_len = targets.len(); if targets.is_empty() { - Some(TerminatorKind::Unreachable) + TerminatorKind::Unreachable } else if targets.len() == 1 { - Some(TerminatorKind::Goto { target: targets[0] }) + TerminatorKind::Goto { target: targets[0] } } else if original_targets_len != retained_targets_len { - Some(TerminatorKind::SwitchInt { + TerminatorKind::SwitchInt { discr: discr.clone(), switch_ty, values: Cow::from(values), targets, - }) + } } else { - None + return None; } } - _ => None, - } + _ => return None, + }; + Some(terminator) } From fd63bf7262d616e8fb5d3465a736434ddc81ff99 Mon Sep 17 00:00:00 2001 From: kadmin Date: Thu, 13 Aug 2020 22:54:09 +0000 Subject: [PATCH 2/2] Rm allocation in uninhabited_enum_branching Also convert `uninhabited_enum_branching` `Cow<[u128]>::to_mut` --- src/librustc_mir/transform/simplify_try.rs | 43 +++++++++---------- .../transform/uninhabited_enum_branching.rs | 30 +++++-------- .../transform/unreachable_prop.rs | 11 ----- 3 files changed, 32 insertions(+), 52 deletions(-) diff --git a/src/librustc_mir/transform/simplify_try.rs b/src/librustc_mir/transform/simplify_try.rs index 02896d7de35..84082edd193 100644 --- a/src/librustc_mir/transform/simplify_try.rs +++ b/src/librustc_mir/transform/simplify_try.rs @@ -246,12 +246,14 @@ fn get_arm_identity_info<'a, 'tcx>( tmp_assigned_vars.insert(*r); } - let mut dbg_info_to_adjust = Vec::new(); - for (i, var_info) in debug_info.iter().enumerate() { - if tmp_assigned_vars.contains(var_info.place.local) { - dbg_info_to_adjust.push(i); - } - } + let dbg_info_to_adjust: Vec<_> = + debug_info + .iter() + .enumerate() + .filter_map(|(i, var_info)| { + if tmp_assigned_vars.contains(var_info.place.local) { Some(i) } else { None } + }) + .collect(); Some(ArmIdentityInfo { local_temp_0: local_tmp_s0, @@ -461,14 +463,14 @@ fn match_get_variant_field<'tcx>( stmt: &Statement<'tcx>, ) -> Option<(Local, Local, VarField<'tcx>, &'tcx List>)> { match &stmt.kind { - StatementKind::Assign(box (place_into, rvalue_from)) => match rvalue_from { - Rvalue::Use(Operand::Copy(pf) | Operand::Move(pf)) => { - let local_into = place_into.as_local()?; - let (local_from, vf) = match_variant_field_place(*pf)?; - Some((local_into, local_from, vf, pf.projection)) - } - _ => None, - }, + StatementKind::Assign(box ( + place_into, + Rvalue::Use(Operand::Copy(pf) | Operand::Move(pf)), + )) => { + let local_into = place_into.as_local()?; + let (local_from, vf) = match_variant_field_place(*pf)?; + Some((local_into, local_from, vf, pf.projection)) + } _ => None, } } @@ -479,14 +481,11 @@ fn match_get_variant_field<'tcx>( /// ``` fn match_set_variant_field<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, Local, VarField<'tcx>)> { match &stmt.kind { - StatementKind::Assign(box (place_from, rvalue_into)) => match rvalue_into { - Rvalue::Use(Operand::Move(place_into)) => { - let local_into = place_into.as_local()?; - let (local_from, vf) = match_variant_field_place(*place_from)?; - Some((local_into, local_from, vf)) - } - _ => None, - }, + StatementKind::Assign(box (place_from, Rvalue::Use(Operand::Move(place_into)))) => { + let local_into = place_into.as_local()?; + let (local_from, vf) = match_variant_field_place(*place_from)?; + Some((local_into, local_from, vf)) + } _ => None, } } diff --git a/src/librustc_mir/transform/uninhabited_enum_branching.rs b/src/librustc_mir/transform/uninhabited_enum_branching.rs index e3b182b8849..4cca4d223c0 100644 --- a/src/librustc_mir/transform/uninhabited_enum_branching.rs +++ b/src/librustc_mir/transform/uninhabited_enum_branching.rs @@ -99,26 +99,18 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { if let TerminatorKind::SwitchInt { values, targets, .. } = &mut body.basic_blocks_mut()[bb].terminator_mut().kind { - let vals = &*values; - let zipped = vals.iter().zip(targets.iter()); + // take otherwise out early + let otherwise = targets.pop().unwrap(); + assert_eq!(targets.len(), values.len()); + let mut i = 0; + targets.retain(|_| { + let keep = allowed_variants.contains(&values[i]); + i += 1; + keep + }); + targets.push(otherwise); - let mut matched_values = Vec::with_capacity(allowed_variants.len()); - let mut matched_targets = Vec::with_capacity(allowed_variants.len() + 1); - - for (val, target) in zipped { - if allowed_variants.contains(val) { - matched_values.push(*val); - matched_targets.push(*target); - } else { - trace!("eliminating {:?} -> {:?}", val, target); - } - } - - // handle the "otherwise" branch - matched_targets.push(targets.pop().unwrap()); - - *values = matched_values.into(); - *targets = matched_targets; + values.to_mut().retain(|var| allowed_variants.contains(var)); } else { unreachable!() } diff --git a/src/librustc_mir/transform/unreachable_prop.rs b/src/librustc_mir/transform/unreachable_prop.rs index e2f8917156b..fa362c66fb2 100644 --- a/src/librustc_mir/transform/unreachable_prop.rs +++ b/src/librustc_mir/transform/unreachable_prop.rs @@ -68,17 +68,6 @@ where F: Fn(BasicBlock) -> bool, { let terminator = match *terminator_kind { - TerminatorKind::FalseEdge { real_target, imaginary_target } - if predicate(real_target) && predicate(imaginary_target) => - { - TerminatorKind::Unreachable - } - TerminatorKind::FalseUnwind { real_target, unwind } - if predicate(real_target) && unwind.map_or(true, &predicate) => - { - TerminatorKind::Unreachable - } - TerminatorKind::Goto { target } if predicate(target) => TerminatorKind::Unreachable, TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => { let original_targets_len = targets.len();