From 78a37f888a00c7406e7a54346697a41802891db7 Mon Sep 17 00:00:00 2001 From: cjkenn Date: Mon, 16 Nov 2020 18:09:10 -0500 Subject: [PATCH 1/7] add optimization fuel checks to some mir passes --- compiler/rustc_mir/src/transform/const_prop.rs | 4 ++++ .../rustc_mir/src/transform/early_otherwise_branch.rs | 4 ++++ compiler/rustc_mir/src/transform/instcombine.rs | 7 +++++++ compiler/rustc_mir/src/transform/match_branches.rs | 5 +++++ .../src/transform/multiple_return_terminators.rs | 6 ++++++ compiler/rustc_mir/src/transform/nrvo.rs | 10 +++++++--- compiler/rustc_mir/src/transform/promote_consts.rs | 4 ++++ .../rustc_mir/src/transform/remove_unneeded_drops.rs | 4 ++++ compiler/rustc_mir/src/transform/unreachable_prop.rs | 6 ++++++ 9 files changed, 47 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs index aeb9920c0e3..1f266a95f03 100644 --- a/compiler/rustc_mir/src/transform/const_prop.rs +++ b/compiler/rustc_mir/src/transform/const_prop.rs @@ -89,6 +89,10 @@ impl<'tcx> MirPass<'tcx> for ConstProp { return; } + if !tcx.consider_optimizing(|| format!("ConstantPropagation {:?} {:?}", def_id, hir_id)) { + return; + } + // Check if it's even possible to satisfy the 'where' clauses // for this item. // This branch will never be taken for any normal function. diff --git a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs index f97dcf4852d..f91477911a4 100644 --- a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs +++ b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs @@ -46,6 +46,10 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { let should_cleanup = !opts_to_apply.is_empty(); for opt_to_apply in opts_to_apply { + if !tcx.consider_optimizing(|| format!("EarlyOtherwiseBranch {:?}", &opt_to_apply)) { + break; + } + trace!("SUCCESS: found optimization possibility to apply: {:?}", &opt_to_apply); let statements_before = diff --git a/compiler/rustc_mir/src/transform/instcombine.rs b/compiler/rustc_mir/src/transform/instcombine.rs index 59b7db24319..5a21cdc6891 100644 --- a/compiler/rustc_mir/src/transform/instcombine.rs +++ b/compiler/rustc_mir/src/transform/instcombine.rs @@ -20,6 +20,13 @@ pub struct InstCombine; impl<'tcx> MirPass<'tcx> for InstCombine { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + // Check for fuel here before gathering the optimization list. If we're out of fuel, + // we don't want to take the time to pass over the MIR only to find optimizations + // we won't run. + if !tcx.consider_optimizing(|| format!("InstCombine {:?} ", body.source.def_id())) { + return; + } + // First, find optimization opportunities. This is done in a pre-pass to keep the MIR // read-only so that we can do global analyses on the MIR in the process (e.g. // `Place::ty()`). diff --git a/compiler/rustc_mir/src/transform/match_branches.rs b/compiler/rustc_mir/src/transform/match_branches.rs index 82c0b924f28..53eeecc780f 100644 --- a/compiler/rustc_mir/src/transform/match_branches.rs +++ b/compiler/rustc_mir/src/transform/match_branches.rs @@ -43,8 +43,13 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { } let param_env = tcx.param_env(body.source.def_id()); + let def_id = body.source.def_id(); let (bbs, local_decls) = body.basic_blocks_and_local_decls_mut(); 'outer: for bb_idx in bbs.indices() { + if !tcx.consider_optimizing(|| format!("MatchBranchSimplification {:?} ", def_id)) { + continue; + } + let (discr, val, switch_ty, first, second) = match bbs[bb_idx].terminator().kind { TerminatorKind::SwitchInt { discr: ref discr @ (Operand::Copy(_) | Operand::Move(_)), diff --git a/compiler/rustc_mir/src/transform/multiple_return_terminators.rs b/compiler/rustc_mir/src/transform/multiple_return_terminators.rs index c37b54a3190..4a66bc45ae3 100644 --- a/compiler/rustc_mir/src/transform/multiple_return_terminators.rs +++ b/compiler/rustc_mir/src/transform/multiple_return_terminators.rs @@ -14,6 +14,12 @@ impl<'tcx> MirPass<'tcx> for MultipleReturnTerminators { return; } + if !tcx.consider_optimizing(|| { + format!("MultipleReturnTerminators {:?} ", body.source.def_id()) + }) { + return; + } + // find basic blocks with no statement and a return terminator let mut bbs_simple_returns = BitSet::new_empty(body.basic_blocks().len()); let bbs = body.basic_blocks_mut(); diff --git a/compiler/rustc_mir/src/transform/nrvo.rs b/compiler/rustc_mir/src/transform/nrvo.rs index 45b906bf542..ce02fb261df 100644 --- a/compiler/rustc_mir/src/transform/nrvo.rs +++ b/compiler/rustc_mir/src/transform/nrvo.rs @@ -38,18 +38,22 @@ impl<'tcx> MirPass<'tcx> for RenameReturnPlace { return; } + let def_id = body.source.def_id(); let returned_local = match local_eligible_for_nrvo(body) { Some(l) => l, None => { - debug!("`{:?}` was ineligible for NRVO", body.source.def_id()); + debug!("`{:?}` was ineligible for NRVO", def_id); return; } }; + if !tcx.consider_optimizing(|| format!("RenameReturnPlace {:?}", def_id)) { + return; + } + debug!( "`{:?}` was eligible for NRVO, making {:?} the return place", - body.source.def_id(), - returned_local + def_id, returned_local ); RenameToReturnPlace { tcx, to_rename: returned_local }.visit_body(body); diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs index 927aae82a36..0539d8fffab 100644 --- a/compiler/rustc_mir/src/transform/promote_consts.rs +++ b/compiler/rustc_mir/src/transform/promote_consts.rs @@ -60,6 +60,10 @@ impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> { return; } + if !tcx.consider_optimizing(|| format!("PromoteTemps {:?} ", body.source.def_id())) { + return; + } + let mut rpo = traversal::reverse_postorder(body); let ccx = ConstCx::new(tcx, body); let (temps, all_candidates) = collect_temps_and_candidates(&ccx, &mut rpo); diff --git a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs b/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs index aaf3ecab4dc..2a72751071b 100644 --- a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs +++ b/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs @@ -11,6 +11,10 @@ pub struct RemoveUnneededDrops; impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + if !tcx.consider_optimizing(|| format!("RemoveUnneededDrops {:?} ", body.source.def_id())) { + return; + } + trace!("Running RemoveUnneededDrops on {:?}", body.source); let mut opt_finder = RemoveUnneededDropsOptimizationFinder { tcx, diff --git a/compiler/rustc_mir/src/transform/unreachable_prop.rs b/compiler/rustc_mir/src/transform/unreachable_prop.rs index f6d39dae342..4100a50c225 100644 --- a/compiler/rustc_mir/src/transform/unreachable_prop.rs +++ b/compiler/rustc_mir/src/transform/unreachable_prop.rs @@ -18,6 +18,12 @@ impl MirPass<'_> for UnreachablePropagation { return; } + if !tcx + .consider_optimizing(|| format!("UnreachablePropagation {:?} ", body.source.def_id())) + { + return; + } + let mut unreachable_blocks = FxHashSet::default(); let mut replacements = FxHashMap::default(); From b4c94241476298936a868b1416f7285ab1e320a7 Mon Sep 17 00:00:00 2001 From: cjkenn Date: Mon, 16 Nov 2020 19:02:02 -0500 Subject: [PATCH 2/7] update ui test for increased fuel usage --- src/test/ui/print-fuel/print-fuel.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/print-fuel/print-fuel.stderr b/src/test/ui/print-fuel/print-fuel.stderr index cc88cc077bb..f1424d587d0 100644 --- a/src/test/ui/print-fuel/print-fuel.stderr +++ b/src/test/ui/print-fuel/print-fuel.stderr @@ -1 +1 @@ -Fuel used by foo: 3 +Fuel used by foo: 7 From 51c2218d1feb38272963ea39768996eb81a13826 Mon Sep 17 00:00:00 2001 From: cjkenn Date: Wed, 18 Nov 2020 08:49:46 -0500 Subject: [PATCH 3/7] move fuel checks to later points in instcombine and const_prop, add opt level flag to test --- .../rustc_mir/src/transform/const_prop.rs | 10 +++--- .../rustc_mir/src/transform/instcombine.rs | 35 +++++++++++-------- src/test/ui/print-fuel/print-fuel.rs | 2 +- src/test/ui/print-fuel/print-fuel.stderr | 2 +- 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs index 1f266a95f03..abcf1862fd8 100644 --- a/compiler/rustc_mir/src/transform/const_prop.rs +++ b/compiler/rustc_mir/src/transform/const_prop.rs @@ -89,10 +89,6 @@ impl<'tcx> MirPass<'tcx> for ConstProp { return; } - if !tcx.consider_optimizing(|| format!("ConstantPropagation {:?} {:?}", def_id, hir_id)) { - return; - } - // Check if it's even possible to satisfy the 'where' clauses // for this item. // This branch will never be taken for any normal function. @@ -804,7 +800,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } - trace!("attepting to replace {:?} with {:?}", rval, value); + trace!("attempting to replace {:?} with {:?}", rval, value); if let Err(e) = self.ecx.const_validate_operand( value, vec![], @@ -894,6 +890,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { return false; } + if !self.tcx.consider_optimizing(|| format!("ConstantPropagation - OpTy: {:?}", op)) { + return false; + } + match *op { interpret::Operand::Immediate(Immediate::Scalar(ScalarMaybeUninit::Scalar(s))) => { s.is_bits() diff --git a/compiler/rustc_mir/src/transform/instcombine.rs b/compiler/rustc_mir/src/transform/instcombine.rs index 5a21cdc6891..3eb2b500d66 100644 --- a/compiler/rustc_mir/src/transform/instcombine.rs +++ b/compiler/rustc_mir/src/transform/instcombine.rs @@ -20,13 +20,6 @@ pub struct InstCombine; impl<'tcx> MirPass<'tcx> for InstCombine { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - // Check for fuel here before gathering the optimization list. If we're out of fuel, - // we don't want to take the time to pass over the MIR only to find optimizations - // we won't run. - if !tcx.consider_optimizing(|| format!("InstCombine {:?} ", body.source.def_id())) { - return; - } - // First, find optimization opportunities. This is done in a pre-pass to keep the MIR // read-only so that we can do global analyses on the MIR in the process (e.g. // `Place::ty()`). @@ -46,13 +39,21 @@ pub struct InstCombineVisitor<'tcx> { tcx: TyCtxt<'tcx>, } +impl<'tcx> InstCombineVisitor<'tcx> { + fn should_combine(&self, rvalue: &Rvalue<'tcx>, location: Location) -> bool { + self.tcx.consider_optimizing(|| { + format!("InstCombine - Rvalue: {:?} Location: {:?}", rvalue, location) + }) + } +} + impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) { - if self.optimizations.and_stars.remove(&location) { + if self.optimizations.and_stars.remove(&location) && self.should_combine(rvalue, location) { debug!("replacing `&*`: {:?}", rvalue); let new_place = match rvalue { Rvalue::Ref(_, _, place) => { @@ -74,18 +75,24 @@ impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> { } if let Some(constant) = self.optimizations.arrays_lengths.remove(&location) { - debug!("replacing `Len([_; N])`: {:?}", rvalue); - *rvalue = Rvalue::Use(Operand::Constant(box constant)); + if self.should_combine(rvalue, location) { + debug!("replacing `Len([_; N])`: {:?}", rvalue); + *rvalue = Rvalue::Use(Operand::Constant(box constant)); + } } if let Some(operand) = self.optimizations.unneeded_equality_comparison.remove(&location) { - debug!("replacing {:?} with {:?}", rvalue, operand); - *rvalue = Rvalue::Use(operand); + if self.should_combine(rvalue, location) { + debug!("replacing {:?} with {:?}", rvalue, operand); + *rvalue = Rvalue::Use(operand); + } } if let Some(place) = self.optimizations.unneeded_deref.remove(&location) { - debug!("unneeded_deref: replacing {:?} with {:?}", rvalue, place); - *rvalue = Rvalue::Use(Operand::Copy(place)); + if self.should_combine(rvalue, location) { + debug!("unneeded_deref: replacing {:?} with {:?}", rvalue, place); + *rvalue = Rvalue::Use(Operand::Copy(place)); + } } self.super_rvalue(rvalue, location) diff --git a/src/test/ui/print-fuel/print-fuel.rs b/src/test/ui/print-fuel/print-fuel.rs index e4434695446..c7d49b58744 100644 --- a/src/test/ui/print-fuel/print-fuel.rs +++ b/src/test/ui/print-fuel/print-fuel.rs @@ -2,7 +2,7 @@ #![allow(dead_code)] // (#55495: The --error-format is to sidestep an issue in our test harness) -// compile-flags: --error-format human -Z print-fuel=foo +// compile-flags: -C opt-level=0 --error-format human -Z print-fuel=foo // build-pass (FIXME(62277): could be check-pass?) struct S1(u8, u16, u8); diff --git a/src/test/ui/print-fuel/print-fuel.stderr b/src/test/ui/print-fuel/print-fuel.stderr index f1424d587d0..e8ed746f57f 100644 --- a/src/test/ui/print-fuel/print-fuel.stderr +++ b/src/test/ui/print-fuel/print-fuel.stderr @@ -1 +1 @@ -Fuel used by foo: 7 +Fuel used by foo: 6 From 1e524fb36c0d1d20495b67ccb232f123d7a11891 Mon Sep 17 00:00:00 2001 From: cjkenn Date: Wed, 18 Nov 2020 11:27:37 -0500 Subject: [PATCH 4/7] change print-fuel ui test to check-pass --- src/test/ui/print-fuel/print-fuel.rs | 2 +- src/test/ui/print-fuel/print-fuel.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/print-fuel/print-fuel.rs b/src/test/ui/print-fuel/print-fuel.rs index c7d49b58744..f68de00b9b5 100644 --- a/src/test/ui/print-fuel/print-fuel.rs +++ b/src/test/ui/print-fuel/print-fuel.rs @@ -3,7 +3,7 @@ // (#55495: The --error-format is to sidestep an issue in our test harness) // compile-flags: -C opt-level=0 --error-format human -Z print-fuel=foo -// build-pass (FIXME(62277): could be check-pass?) +// check-pass struct S1(u8, u16, u8); struct S2(u8, u16, u8); diff --git a/src/test/ui/print-fuel/print-fuel.stderr b/src/test/ui/print-fuel/print-fuel.stderr index e8ed746f57f..4cbda0d8b25 100644 --- a/src/test/ui/print-fuel/print-fuel.stderr +++ b/src/test/ui/print-fuel/print-fuel.stderr @@ -1 +1 @@ -Fuel used by foo: 6 +Fuel used by foo: 4 From b556690c53d87ea7530c631d3c257da3567e5a9a Mon Sep 17 00:00:00 2001 From: cjkenn Date: Wed, 18 Nov 2020 19:16:23 -0500 Subject: [PATCH 5/7] move checks later into optimization passes --- .../src/transform/multiple_return_terminators.rs | 11 +++++------ .../rustc_mir/src/transform/remove_unneeded_drops.rs | 10 ++++++---- compiler/rustc_mir/src/transform/unreachable_prop.rs | 12 ++++++------ 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_mir/src/transform/multiple_return_terminators.rs b/compiler/rustc_mir/src/transform/multiple_return_terminators.rs index 4a66bc45ae3..617086622cc 100644 --- a/compiler/rustc_mir/src/transform/multiple_return_terminators.rs +++ b/compiler/rustc_mir/src/transform/multiple_return_terminators.rs @@ -14,14 +14,9 @@ impl<'tcx> MirPass<'tcx> for MultipleReturnTerminators { return; } - if !tcx.consider_optimizing(|| { - format!("MultipleReturnTerminators {:?} ", body.source.def_id()) - }) { - return; - } - // find basic blocks with no statement and a return terminator let mut bbs_simple_returns = BitSet::new_empty(body.basic_blocks().len()); + let def_id = body.source.def_id(); let bbs = body.basic_blocks_mut(); for idx in bbs.indices() { if bbs[idx].statements.is_empty() @@ -32,6 +27,10 @@ impl<'tcx> MirPass<'tcx> for MultipleReturnTerminators { } for bb in bbs { + if !tcx.consider_optimizing(|| format!("MultipleReturnTerminators {:?} ", def_id)) { + break; + } + if let TerminatorKind::Goto { target } = bb.terminator().kind { if bbs_simple_returns.contains(target) { bb.terminator_mut().kind = TerminatorKind::Return; diff --git a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs b/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs index 2a72751071b..221114eebaa 100644 --- a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs +++ b/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs @@ -11,10 +11,6 @@ pub struct RemoveUnneededDrops; impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if !tcx.consider_optimizing(|| format!("RemoveUnneededDrops {:?} ", body.source.def_id())) { - return; - } - trace!("Running RemoveUnneededDrops on {:?}", body.source); let mut opt_finder = RemoveUnneededDropsOptimizationFinder { tcx, @@ -25,6 +21,12 @@ impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops { opt_finder.visit_body(body); let should_simplify = !opt_finder.optimizations.is_empty(); for (loc, target) in opt_finder.optimizations { + if !tcx + .consider_optimizing(|| format!("RemoveUnneededDrops {:?} ", body.source.def_id())) + { + break; + } + let terminator = body.basic_blocks_mut()[loc.block].terminator_mut(); debug!("SUCCESS: replacing `drop` with goto({:?})", target); terminator.kind = TerminatorKind::Goto { target }; diff --git a/compiler/rustc_mir/src/transform/unreachable_prop.rs b/compiler/rustc_mir/src/transform/unreachable_prop.rs index 4100a50c225..e39c8656021 100644 --- a/compiler/rustc_mir/src/transform/unreachable_prop.rs +++ b/compiler/rustc_mir/src/transform/unreachable_prop.rs @@ -18,12 +18,6 @@ impl MirPass<'_> for UnreachablePropagation { return; } - if !tcx - .consider_optimizing(|| format!("UnreachablePropagation {:?} ", body.source.def_id())) - { - return; - } - let mut unreachable_blocks = FxHashSet::default(); let mut replacements = FxHashMap::default(); @@ -56,6 +50,12 @@ impl MirPass<'_> for UnreachablePropagation { let replaced = !replacements.is_empty(); for (bb, terminator_kind) in replacements { + if !tcx.consider_optimizing(|| { + format!("UnreachablePropagation {:?} ", body.source.def_id()) + }) { + break; + } + body.basic_blocks_mut()[bb].terminator_mut().kind = terminator_kind; } From 1d3305aa6668705af71aaab82a004c5c06642246 Mon Sep 17 00:00:00 2001 From: cjkenn Date: Thu, 19 Nov 2020 08:21:20 -0500 Subject: [PATCH 6/7] remove check from const promotion --- compiler/rustc_mir/src/transform/promote_consts.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs index 0539d8fffab..927aae82a36 100644 --- a/compiler/rustc_mir/src/transform/promote_consts.rs +++ b/compiler/rustc_mir/src/transform/promote_consts.rs @@ -60,10 +60,6 @@ impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> { return; } - if !tcx.consider_optimizing(|| format!("PromoteTemps {:?} ", body.source.def_id())) { - return; - } - let mut rpo = traversal::reverse_postorder(body); let ccx = ConstCx::new(tcx, body); let (temps, all_candidates) = collect_temps_and_candidates(&ccx, &mut rpo); From 07de70250bd350befde0bf80fcb0e2836cd5d8b9 Mon Sep 17 00:00:00 2001 From: cjkenn Date: Thu, 19 Nov 2020 08:47:00 -0500 Subject: [PATCH 7/7] update print fuel test output again... --- src/test/ui/print-fuel/print-fuel.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/print-fuel/print-fuel.stderr b/src/test/ui/print-fuel/print-fuel.stderr index 4cbda0d8b25..cc88cc077bb 100644 --- a/src/test/ui/print-fuel/print-fuel.stderr +++ b/src/test/ui/print-fuel/print-fuel.stderr @@ -1 +1 @@ -Fuel used by foo: 4 +Fuel used by foo: 3