mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 22:41:50 +00:00
Use new MIR pass manager
This commit is contained in:
parent
fca642c1c3
commit
71dd5422ac
@ -27,7 +27,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_middle::mir::visit::Visitor as _;
|
||||
use rustc_middle::mir::{dump_mir, traversal, Body, ConstQualifs, MirPass, MirPhase, Promoted};
|
||||
use rustc_middle::mir::{traversal, Body, ConstQualifs, MirPass, MirPhase, Promoted};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
|
||||
use rustc_span::{Span, Symbol};
|
||||
@ -35,7 +35,7 @@ use rustc_span::{Span, Symbol};
|
||||
#[macro_use]
|
||||
mod pass_manager;
|
||||
|
||||
use pass_manager::{Lint, MirLint};
|
||||
use pass_manager::{self as pm, Lint, MirLint};
|
||||
|
||||
mod abort_unwinding_calls;
|
||||
mod add_call_guards;
|
||||
@ -174,66 +174,6 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxHashSet<LocalDefId> {
|
||||
set
|
||||
}
|
||||
|
||||
fn run_passes(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &mut Body<'tcx>,
|
||||
mir_phase: MirPhase,
|
||||
passes: &[&[&dyn MirPass<'tcx>]],
|
||||
) {
|
||||
let phase_index = mir_phase.phase_index();
|
||||
let validate = tcx.sess.opts.debugging_opts.validate_mir;
|
||||
|
||||
if body.phase >= mir_phase {
|
||||
return;
|
||||
}
|
||||
|
||||
if validate {
|
||||
validate::Validator { when: format!("input to phase {:?}", mir_phase), mir_phase }
|
||||
.run_pass(tcx, body);
|
||||
}
|
||||
|
||||
let mut index = 0;
|
||||
let mut run_pass = |pass: &dyn MirPass<'tcx>| {
|
||||
let run_hooks = |body: &_, index, is_after| {
|
||||
let disambiguator = if is_after { "after" } else { "before" };
|
||||
dump_mir(
|
||||
tcx,
|
||||
Some(&format_args!("{:03}-{:03}", phase_index, index)),
|
||||
&pass.name(),
|
||||
&disambiguator,
|
||||
body,
|
||||
|_, _| Ok(()),
|
||||
);
|
||||
};
|
||||
run_hooks(body, index, false);
|
||||
pass.run_pass(tcx, body);
|
||||
run_hooks(body, index, true);
|
||||
|
||||
if validate {
|
||||
validate::Validator {
|
||||
when: format!("after {} in phase {:?}", pass.name(), mir_phase),
|
||||
mir_phase,
|
||||
}
|
||||
.run_pass(tcx, body);
|
||||
}
|
||||
|
||||
index += 1;
|
||||
};
|
||||
|
||||
for pass_group in passes {
|
||||
for pass in *pass_group {
|
||||
run_pass(*pass);
|
||||
}
|
||||
}
|
||||
|
||||
body.phase = mir_phase;
|
||||
|
||||
if mir_phase == MirPhase::Optimization {
|
||||
validate::Validator { when: format!("end of phase {:?}", mir_phase), mir_phase }
|
||||
.run_pass(tcx, body);
|
||||
}
|
||||
}
|
||||
|
||||
fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> ConstQualifs {
|
||||
let const_kind = tcx.hir().body_const_context(def.did);
|
||||
|
||||
@ -285,11 +225,10 @@ fn mir_const<'tcx>(
|
||||
|
||||
rustc_middle::mir::dump_mir(tcx, None, "mir_map", &0, &body, |_, _| Ok(()));
|
||||
|
||||
run_passes(
|
||||
pm::run_passes(
|
||||
tcx,
|
||||
&mut body,
|
||||
MirPhase::Const,
|
||||
&[&[
|
||||
&[
|
||||
// MIR-level lints.
|
||||
&Lint(check_packed_ref::CheckPackedRef),
|
||||
&Lint(check_const_item_mutation::CheckConstItemMutation),
|
||||
@ -297,7 +236,8 @@ fn mir_const<'tcx>(
|
||||
// What we need to do constant evaluation.
|
||||
&simplify::SimplifyCfg::new("initial"),
|
||||
&rustc_peek::SanityCheck, // Just a lint
|
||||
]],
|
||||
&marker::PhaseChange(MirPhase::Const),
|
||||
],
|
||||
);
|
||||
tcx.alloc_steal_mir(body)
|
||||
}
|
||||
@ -324,17 +264,17 @@ fn mir_promoted(
|
||||
}
|
||||
body.required_consts = required_consts;
|
||||
|
||||
// What we need to run borrowck etc.
|
||||
let promote_pass = promote_consts::PromoteTemps::default();
|
||||
let promote: &[&dyn MirPass<'tcx>] = &[
|
||||
// What we need to run borrowck etc.
|
||||
&promote_pass,
|
||||
&simplify::SimplifyCfg::new("promote-consts"),
|
||||
];
|
||||
|
||||
let opt_coverage: &[&dyn MirPass<'tcx>] =
|
||||
if tcx.sess.instrument_coverage() { &[&coverage::InstrumentCoverage] } else { &[] };
|
||||
|
||||
run_passes(tcx, &mut body, MirPhase::ConstPromotion, &[promote, opt_coverage]);
|
||||
pm::run_passes(
|
||||
tcx,
|
||||
&mut body,
|
||||
&[
|
||||
&promote_pass,
|
||||
&simplify::SimplifyCfg::new("promote-consts"),
|
||||
&coverage::InstrumentCoverage,
|
||||
],
|
||||
);
|
||||
|
||||
let promoted = promote_pass.promoted_fragments.into_inner();
|
||||
(tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted))
|
||||
@ -396,19 +336,10 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -
|
||||
// Technically we want to not run on regular const items, but oli-obk doesn't know how to
|
||||
// conveniently detect that at this point without looking at the HIR.
|
||||
hir::ConstContext::Const => {
|
||||
#[rustfmt::skip]
|
||||
let optimizations: &[&dyn MirPass<'_>] = &[
|
||||
&const_prop::ConstProp,
|
||||
];
|
||||
|
||||
#[rustfmt::skip]
|
||||
run_passes(
|
||||
pm::run_passes(
|
||||
tcx,
|
||||
&mut body,
|
||||
MirPhase::Optimization,
|
||||
&[
|
||||
optimizations,
|
||||
],
|
||||
&[&const_prop::ConstProp, &marker::PhaseChange(MirPhase::Optimization)],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -453,19 +384,23 @@ fn mir_drops_elaborated_and_const_checked<'tcx>(
|
||||
let mut body = body.steal();
|
||||
|
||||
// IMPORTANT
|
||||
remove_false_edges::RemoveFalseEdges.run_pass(tcx, &mut body);
|
||||
pm::run_passes(tcx, &mut body, &[&remove_false_edges::RemoveFalseEdges]);
|
||||
|
||||
// Do a little drop elaboration before const-checking if `const_precise_live_drops` is enabled.
|
||||
//
|
||||
// FIXME: Can't use `run_passes` for these, since `run_passes` SILENTLY DOES NOTHING IF THE MIR
|
||||
// PHASE DOESN'T CHANGE.
|
||||
if check_consts::post_drop_elaboration::checking_enabled(&ConstCx::new(tcx, &body)) {
|
||||
simplify::SimplifyCfg::new("remove-false-edges").run_pass(tcx, &mut body);
|
||||
remove_uninit_drops::RemoveUninitDrops.run_pass(tcx, &mut body);
|
||||
check_consts::post_drop_elaboration::check_live_drops(tcx, &body);
|
||||
pm::run_passes(
|
||||
tcx,
|
||||
&mut body,
|
||||
&[
|
||||
&simplify::SimplifyCfg::new("remove-false-edges"),
|
||||
&remove_uninit_drops::RemoveUninitDrops,
|
||||
],
|
||||
);
|
||||
check_consts::post_drop_elaboration::check_live_drops(tcx, &body); // FIXME: make this a MIR lint
|
||||
}
|
||||
|
||||
run_post_borrowck_cleanup_passes(tcx, &mut body);
|
||||
assert!(body.phase == MirPhase::DropLowering);
|
||||
tcx.alloc_steal_mir(body)
|
||||
}
|
||||
|
||||
@ -499,95 +434,65 @@ fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tc
|
||||
&deaggregator::Deaggregator,
|
||||
];
|
||||
|
||||
run_passes(tcx, body, MirPhase::DropLowering, &[post_borrowck_cleanup]);
|
||||
pm::run_passes(tcx, body, post_borrowck_cleanup);
|
||||
}
|
||||
|
||||
fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
let mir_opt_level = tcx.sess.mir_opt_level();
|
||||
|
||||
// Lowering generator control-flow and variables has to happen before we do anything else
|
||||
// to them. We run some optimizations before that, because they may be harder to do on the state
|
||||
// machine than on MIR with async primitives.
|
||||
let optimizations_with_generators: &[&dyn MirPass<'tcx>] = &[
|
||||
&reveal_all::RevealAll, // has to be done before inlining, since inlined code is in RevealAll mode.
|
||||
&lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first
|
||||
&normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering
|
||||
&unreachable_prop::UnreachablePropagation,
|
||||
&uninhabited_enum_branching::UninhabitedEnumBranching,
|
||||
&simplify::SimplifyCfg::new("after-uninhabited-enum-branching"),
|
||||
&inline::Inline,
|
||||
&generator::StateTransform,
|
||||
];
|
||||
|
||||
// Even if we don't do optimizations, we still have to lower generators for codegen.
|
||||
let no_optimizations_with_generators: &[&dyn MirPass<'tcx>] = &[&generator::StateTransform];
|
||||
|
||||
// The main optimizations that we do on MIR.
|
||||
let optimizations: &[&dyn MirPass<'tcx>] = &[
|
||||
&remove_storage_markers::RemoveStorageMarkers,
|
||||
&remove_zsts::RemoveZsts,
|
||||
&const_goto::ConstGoto,
|
||||
&remove_unneeded_drops::RemoveUnneededDrops,
|
||||
&match_branches::MatchBranchSimplification,
|
||||
// inst combine is after MatchBranchSimplification to clean up Ne(_1, false)
|
||||
&multiple_return_terminators::MultipleReturnTerminators,
|
||||
&instcombine::InstCombine,
|
||||
&separate_const_switch::SeparateConstSwitch,
|
||||
&const_prop::ConstProp,
|
||||
&simplify_branches::SimplifyConstCondition::new("after-const-prop"),
|
||||
&early_otherwise_branch::EarlyOtherwiseBranch,
|
||||
&simplify_comparison_integral::SimplifyComparisonIntegral,
|
||||
&simplify_try::SimplifyArmIdentity,
|
||||
&simplify_try::SimplifyBranchSame,
|
||||
&dest_prop::DestinationPropagation,
|
||||
&simplify_branches::SimplifyConstCondition::new("final"),
|
||||
&remove_noop_landing_pads::RemoveNoopLandingPads,
|
||||
&simplify::SimplifyCfg::new("final"),
|
||||
&nrvo::RenameReturnPlace,
|
||||
&const_debuginfo::ConstDebugInfo,
|
||||
&simplify::SimplifyLocals,
|
||||
&multiple_return_terminators::MultipleReturnTerminators,
|
||||
&deduplicate_blocks::DeduplicateBlocks,
|
||||
];
|
||||
|
||||
// Optimizations to run even if mir optimizations have been disabled.
|
||||
let no_optimizations: &[&dyn MirPass<'tcx>] = &[
|
||||
// FIXME(#70073): This pass is responsible for both optimization as well as some lints.
|
||||
&const_prop::ConstProp,
|
||||
];
|
||||
|
||||
// Some cleanup necessary at least for LLVM and potentially other codegen backends.
|
||||
let pre_codegen_cleanup: &[&dyn MirPass<'tcx>] = &[
|
||||
&add_call_guards::CriticalCallEdges,
|
||||
// Dump the end result for testing and debugging purposes.
|
||||
&dump_mir::Marker("PreCodegen"),
|
||||
];
|
||||
|
||||
// End of pass declarations, now actually run the passes.
|
||||
// Generator Lowering
|
||||
#[rustfmt::skip]
|
||||
run_passes(
|
||||
pm::run_passes(
|
||||
tcx,
|
||||
body,
|
||||
MirPhase::GeneratorLowering,
|
||||
&[
|
||||
if mir_opt_level > 0 {
|
||||
optimizations_with_generators
|
||||
} else {
|
||||
no_optimizations_with_generators
|
||||
}
|
||||
&reveal_all::RevealAll, // has to be done before inlining, since inlined code is in RevealAll mode.
|
||||
&lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first
|
||||
&normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering
|
||||
&unreachable_prop::UnreachablePropagation,
|
||||
&uninhabited_enum_branching::UninhabitedEnumBranching,
|
||||
&simplify::SimplifyCfg::new("after-uninhabited-enum-branching"),
|
||||
&inline::Inline,
|
||||
&generator::StateTransform,
|
||||
],
|
||||
);
|
||||
|
||||
// Main optimization passes
|
||||
#[rustfmt::skip]
|
||||
run_passes(
|
||||
assert!(body.phase == MirPhase::GeneratorLowering);
|
||||
|
||||
// The main optimizations that we do on MIR.
|
||||
pm::run_passes(
|
||||
tcx,
|
||||
body,
|
||||
MirPhase::Optimization,
|
||||
&[
|
||||
if mir_opt_level > 0 { optimizations } else { no_optimizations },
|
||||
pre_codegen_cleanup,
|
||||
&remove_storage_markers::RemoveStorageMarkers,
|
||||
&remove_zsts::RemoveZsts,
|
||||
&const_goto::ConstGoto,
|
||||
&remove_unneeded_drops::RemoveUnneededDrops,
|
||||
&match_branches::MatchBranchSimplification,
|
||||
// inst combine is after MatchBranchSimplification to clean up Ne(_1, false)
|
||||
&multiple_return_terminators::MultipleReturnTerminators,
|
||||
&instcombine::InstCombine,
|
||||
&separate_const_switch::SeparateConstSwitch,
|
||||
// FIXME(#70073): This pass is responsible for both optimization as well as some lints.
|
||||
&const_prop::ConstProp,
|
||||
&simplify_branches::SimplifyBranches::new("after-const-prop"),
|
||||
&early_otherwise_branch::EarlyOtherwiseBranch,
|
||||
&simplify_comparison_integral::SimplifyComparisonIntegral,
|
||||
&simplify_try::SimplifyArmIdentity,
|
||||
&simplify_try::SimplifyBranchSame,
|
||||
&dest_prop::DestinationPropagation,
|
||||
&simplify_branches::SimplifyBranches::new("final"),
|
||||
&remove_noop_landing_pads::RemoveNoopLandingPads,
|
||||
&simplify::SimplifyCfg::new("final"),
|
||||
&nrvo::RenameReturnPlace,
|
||||
&const_debuginfo::ConstDebugInfo,
|
||||
&simplify::SimplifyLocals,
|
||||
&multiple_return_terminators::MultipleReturnTerminators,
|
||||
&deduplicate_blocks::DeduplicateBlocks,
|
||||
// Some cleanup necessary at least for LLVM and potentially other codegen backends.
|
||||
&add_call_guards::CriticalCallEdges,
|
||||
&marker::PhaseChange(MirPhase::Optimization),
|
||||
// Dump the end result for testing and debugging purposes.
|
||||
&dump_mir::Marker("PreCodegen"),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
@ -17,8 +17,8 @@ use std::iter;
|
||||
|
||||
use crate::util::expand_aggregate;
|
||||
use crate::{
|
||||
abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, remove_noop_landing_pads,
|
||||
run_passes, simplify,
|
||||
abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, marker, pass_manager as pm,
|
||||
remove_noop_landing_pads, simplify,
|
||||
};
|
||||
use rustc_middle::mir::patch::MirPatch;
|
||||
use rustc_mir_dataflow::elaborate_drops::{self, DropElaborator, DropFlagMode, DropStyle};
|
||||
@ -75,17 +75,17 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
|
||||
};
|
||||
debug!("make_shim({:?}) = untransformed {:?}", instance, result);
|
||||
|
||||
run_passes(
|
||||
pm::run_passes(
|
||||
tcx,
|
||||
&mut result,
|
||||
MirPhase::Const,
|
||||
&[&[
|
||||
&[
|
||||
&add_moves_for_packed_drops::AddMovesForPackedDrops,
|
||||
&remove_noop_landing_pads::RemoveNoopLandingPads,
|
||||
&simplify::SimplifyCfg::new("make_shim"),
|
||||
&add_call_guards::CriticalCallEdges,
|
||||
&abort_unwinding_calls::AbortUnwindingCalls,
|
||||
]],
|
||||
&marker::PhaseChange(MirPhase::Const),
|
||||
],
|
||||
);
|
||||
|
||||
debug!("make_shim({:?}) = {:?}", instance, result);
|
||||
|
Loading…
Reference in New Issue
Block a user