Skip to content

Commit da4cb6c

Browse files
Define a PassManager for managing MIR passes
1 parent 790d19c commit da4cb6c

File tree

4 files changed

+245
-203
lines changed

4 files changed

+245
-203
lines changed

compiler/rustc_mir/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,15 @@ extern crate tracing;
3434
#[macro_use]
3535
extern crate rustc_middle;
3636

37+
#[macro_use]
38+
pub mod transform;
39+
3740
mod borrow_check;
3841
pub mod const_eval;
3942
pub mod dataflow;
4043
pub mod interpret;
4144
pub mod monomorphize;
4245
mod shim;
43-
pub mod transform;
4446
pub mod util;
4547

4648
use rustc_middle::ty::query::Providers;

compiler/rustc_mir/src/shim.rs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use std::iter;
1717

1818
use crate::transform::{
1919
add_call_guards, add_moves_for_packed_drops, no_landing_pads, remove_noop_landing_pads,
20-
run_passes, simplify,
20+
simplify, PassManager,
2121
};
2222
use crate::util::elaborate_drops::{self, DropElaborator, DropFlagMode, DropStyle};
2323
use crate::util::expand_aggregate;
@@ -75,18 +75,15 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
7575
};
7676
debug!("make_shim({:?}) = untransformed {:?}", instance, result);
7777

78-
run_passes(
79-
tcx,
80-
&mut result,
81-
MirPhase::Const,
82-
&[&[
83-
&add_moves_for_packed_drops::AddMovesForPackedDrops,
84-
&no_landing_pads::NoLandingPads::new(tcx),
85-
&remove_noop_landing_pads::RemoveNoopLandingPads,
86-
&simplify::SimplifyCfg::new("make_shim"),
87-
&add_call_guards::CriticalCallEdges,
88-
]],
89-
);
78+
if result.phase < MirPhase::Const {
79+
run_passes!(PassManager::new(tcx, &mut result, MirPhase::Const) => [
80+
add_moves_for_packed_drops::AddMovesForPackedDrops,
81+
no_landing_pads::NoLandingPads::new(tcx),
82+
remove_noop_landing_pads::RemoveNoopLandingPads,
83+
simplify::SimplifyCfg::new("make_shim"),
84+
add_call_guards::CriticalCallEdges,
85+
]);
86+
}
9087

9188
debug!("make_shim({:?}) = {:?}", instance, result);
9289

compiler/rustc_mir/src/transform/mod.rs

Lines changed: 85 additions & 189 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,13 @@ use rustc_middle::ty::query::Providers;
1111
use rustc_middle::ty::steal::Steal;
1212
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
1313
use rustc_span::{Span, Symbol};
14-
use std::borrow::Cow;
1514

15+
#[macro_use]
16+
mod pass;
17+
18+
pub use self::pass::{MirPass, OptLevel, PassManager};
19+
20+
// Passes
1621
pub mod add_call_guards;
1722
pub mod add_moves_for_packed_drops;
1823
pub mod add_retag;
@@ -134,82 +139,6 @@ fn mir_keys(tcx: TyCtxt<'_>, krate: CrateNum) -> FxHashSet<LocalDefId> {
134139
set
135140
}
136141

137-
/// Generates a default name for the pass based on the name of the
138-
/// type `T`.
139-
pub fn default_name<T: ?Sized>() -> Cow<'static, str> {
140-
let name = ::std::any::type_name::<T>();
141-
if let Some(tail) = name.rfind(':') { Cow::from(&name[tail + 1..]) } else { Cow::from(name) }
142-
}
143-
144-
/// A streamlined trait that you can implement to create a pass; the
145-
/// pass will be named after the type, and it will consist of a main
146-
/// loop that goes over each available MIR and applies `run_pass`.
147-
pub trait MirPass<'tcx> {
148-
fn name(&self) -> Cow<'_, str> {
149-
default_name::<Self>()
150-
}
151-
152-
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>);
153-
}
154-
155-
pub fn run_passes(
156-
tcx: TyCtxt<'tcx>,
157-
body: &mut Body<'tcx>,
158-
mir_phase: MirPhase,
159-
passes: &[&[&dyn MirPass<'tcx>]],
160-
) {
161-
let phase_index = mir_phase.phase_index();
162-
let validate = tcx.sess.opts.debugging_opts.validate_mir;
163-
164-
if body.phase >= mir_phase {
165-
return;
166-
}
167-
168-
if validate {
169-
validate::Validator { when: format!("input to phase {:?}", mir_phase), mir_phase }
170-
.run_pass(tcx, body);
171-
}
172-
173-
let mut index = 0;
174-
let mut run_pass = |pass: &dyn MirPass<'tcx>| {
175-
let run_hooks = |body: &_, index, is_after| {
176-
dump_mir::on_mir_pass(
177-
tcx,
178-
&format_args!("{:03}-{:03}", phase_index, index),
179-
&pass.name(),
180-
body,
181-
is_after,
182-
);
183-
};
184-
run_hooks(body, index, false);
185-
pass.run_pass(tcx, body);
186-
run_hooks(body, index, true);
187-
188-
if validate {
189-
validate::Validator {
190-
when: format!("after {} in phase {:?}", pass.name(), mir_phase),
191-
mir_phase,
192-
}
193-
.run_pass(tcx, body);
194-
}
195-
196-
index += 1;
197-
};
198-
199-
for pass_group in passes {
200-
for pass in *pass_group {
201-
run_pass(*pass);
202-
}
203-
}
204-
205-
body.phase = mir_phase;
206-
207-
if mir_phase == MirPhase::Optimization {
208-
validate::Validator { when: format!("end of phase {:?}", mir_phase), mir_phase }
209-
.run_pass(tcx, body);
210-
}
211-
}
212-
213142
fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> ConstQualifs {
214143
let const_kind = tcx.hir().body_const_context(def.did);
215144

@@ -259,19 +188,15 @@ fn mir_const<'tcx>(
259188

260189
util::dump_mir(tcx, None, "mir_map", &0, &body, |_, _| Ok(()));
261190

262-
run_passes(
263-
tcx,
264-
&mut body,
265-
MirPhase::Const,
266-
&[&[
267-
// MIR-level lints.
268-
&check_packed_ref::CheckPackedRef,
269-
&check_const_item_mutation::CheckConstItemMutation,
270-
// What we need to do constant evaluation.
271-
&simplify::SimplifyCfg::new("initial"),
272-
&rustc_peek::SanityCheck,
273-
]],
274-
);
191+
run_passes!(PassManager::new(tcx, &mut body, MirPhase::Const) => [
192+
// MIR-level lints.
193+
check_packed_ref::CheckPackedRef,
194+
check_const_item_mutation::CheckConstItemMutation,
195+
// What we need to do constant evaluation.
196+
simplify::SimplifyCfg::new("initial"),
197+
rustc_peek::SanityCheck,
198+
]);
199+
275200
tcx.alloc_steal_mir(body)
276201
}
277202

@@ -301,20 +226,19 @@ fn mir_promoted(
301226
}
302227
body.required_consts = required_consts;
303228

229+
let mut promotion_passes = PassManager::new(tcx, &mut body, MirPhase::ConstPromotion);
230+
304231
let promote_pass = promote_consts::PromoteTemps::default();
305-
let promote: &[&dyn MirPass<'tcx>] = &[
306-
// What we need to run borrowck etc.
307-
&promote_pass,
308-
&simplify::SimplifyCfg::new("promote-consts"),
309-
];
310-
311-
let opt_coverage: &[&dyn MirPass<'tcx>] = if tcx.sess.opts.debugging_opts.instrument_coverage {
312-
&[&instrument_coverage::InstrumentCoverage]
313-
} else {
314-
&[]
315-
};
232+
run_passes!(promotion_passes => [
233+
promote_pass,
234+
simplify::SimplifyCfg::new("promote-consts"),
235+
]);
236+
237+
if tcx.sess.opts.debugging_opts.instrument_coverage {
238+
run_passes!(promotion_passes => [instrument_coverage::InstrumentCoverage]);
239+
}
316240

317-
run_passes(tcx, &mut body, MirPhase::ConstPromotion, &[promote, opt_coverage]);
241+
drop(promotion_passes);
318242

319243
let promoted = promote_pass.promoted_fragments.into_inner();
320244
(tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted))
@@ -348,30 +272,28 @@ fn mir_drops_elaborated_and_const_checked<'tcx>(
348272
fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
349273
debug!("post_borrowck_cleanup({:?})", body.source.def_id());
350274

351-
let post_borrowck_cleanup: &[&dyn MirPass<'tcx>] = &[
275+
run_passes!(PassManager::new(tcx, body, MirPhase::DropLowering) => [
352276
// Remove all things only needed by analysis
353-
&no_landing_pads::NoLandingPads::new(tcx),
354-
&simplify_branches::SimplifyBranches::new("initial"),
355-
&remove_noop_landing_pads::RemoveNoopLandingPads,
356-
&cleanup_post_borrowck::CleanupNonCodegenStatements,
357-
&simplify::SimplifyCfg::new("early-opt"),
277+
no_landing_pads::NoLandingPads::new(tcx),
278+
simplify_branches::SimplifyBranches::new("initial"),
279+
remove_noop_landing_pads::RemoveNoopLandingPads,
280+
cleanup_post_borrowck::CleanupNonCodegenStatements,
281+
simplify::SimplifyCfg::new("early-opt"),
358282
// These next passes must be executed together
359-
&add_call_guards::CriticalCallEdges,
360-
&elaborate_drops::ElaborateDrops,
361-
&no_landing_pads::NoLandingPads::new(tcx),
283+
add_call_guards::CriticalCallEdges,
284+
elaborate_drops::ElaborateDrops,
285+
no_landing_pads::NoLandingPads::new(tcx),
362286
// AddMovesForPackedDrops needs to run after drop
363287
// elaboration.
364-
&add_moves_for_packed_drops::AddMovesForPackedDrops,
288+
add_moves_for_packed_drops::AddMovesForPackedDrops,
365289
// `AddRetag` needs to run after `ElaborateDrops`. Otherwise it should run fairly late,
366290
// but before optimizations begin.
367-
&add_retag::AddRetag,
368-
&simplify::SimplifyCfg::new("elaborate-drops"),
291+
add_retag::AddRetag,
292+
simplify::SimplifyCfg::new("elaborate-drops"),
369293
// `Deaggregator` is conceptually part of MIR building, some backends rely on it happening
370294
// and it can help optimizations.
371-
&deaggregator::Deaggregator,
372-
];
373-
374-
run_passes(tcx, body, MirPhase::DropLowering, &[post_borrowck_cleanup]);
295+
deaggregator::Deaggregator,
296+
]);
375297
}
376298

377299
fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
@@ -380,80 +302,54 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
380302
// Lowering generator control-flow and variables has to happen before we do anything else
381303
// to them. We run some optimizations before that, because they may be harder to do on the state
382304
// machine than on MIR with async primitives.
383-
let optimizations_with_generators: &[&dyn MirPass<'tcx>] = &[
384-
&unreachable_prop::UnreachablePropagation,
385-
&uninhabited_enum_branching::UninhabitedEnumBranching,
386-
&simplify::SimplifyCfg::new("after-uninhabited-enum-branching"),
387-
&inline::Inline,
388-
&generator::StateTransform,
389-
];
390-
391-
// Even if we don't do optimizations, we still have to lower generators for codegen.
392-
let no_optimizations_with_generators: &[&dyn MirPass<'tcx>] = &[&generator::StateTransform];
393-
394-
// The main optimizations that we do on MIR.
395-
let optimizations: &[&dyn MirPass<'tcx>] = &[
396-
&remove_unneeded_drops::RemoveUnneededDrops,
397-
&match_branches::MatchBranchSimplification,
398-
// inst combine is after MatchBranchSimplification to clean up Ne(_1, false)
399-
&multiple_return_terminators::MultipleReturnTerminators,
400-
&instcombine::InstCombine,
401-
&const_prop::ConstProp,
402-
&simplify_branches::SimplifyBranches::new("after-const-prop"),
403-
&early_otherwise_branch::EarlyOtherwiseBranch,
404-
&simplify_comparison_integral::SimplifyComparisonIntegral,
405-
&simplify_try::SimplifyArmIdentity,
406-
&simplify_try::SimplifyBranchSame,
407-
&dest_prop::DestinationPropagation,
408-
&copy_prop::CopyPropagation,
409-
&simplify_branches::SimplifyBranches::new("after-copy-prop"),
410-
&remove_noop_landing_pads::RemoveNoopLandingPads,
411-
&simplify::SimplifyCfg::new("final"),
412-
&nrvo::RenameReturnPlace,
413-
&simplify::SimplifyLocals,
414-
&multiple_return_terminators::MultipleReturnTerminators,
415-
];
416-
417-
// Optimizations to run even if mir optimizations have been disabled.
418-
let no_optimizations: &[&dyn MirPass<'tcx>] = &[
419-
// FIXME(#70073): This pass is responsible for both optimization as well as some lints.
420-
&const_prop::ConstProp,
421-
];
305+
run_passes!(PassManager::new(tcx, body, MirPhase::GeneratorLowering) => [
306+
unreachable_prop::UnreachablePropagation,
307+
uninhabited_enum_branching::UninhabitedEnumBranching,
308+
simplify::SimplifyCfg::new("after-uninhabited-enum-branching"),
309+
inline::Inline,
310+
generator::StateTransform,
311+
]);
312+
313+
let mut optimizations = PassManager::new(tcx, body, MirPhase::Optimization);
314+
315+
// FIXME(ecstaticmorse): We shouldn't branch on `mir_opt_level` here, but instead rely on the
316+
// `LEVEL` of each `MirPass` to determine whether it runs. However, this would run some
317+
// "cleanup" passes as well as `RemoveNoopLandingPads` when we didn't before.
318+
if mir_opt_level > 0 {
319+
run_passes!(optimizations => [
320+
remove_unneeded_drops::RemoveUnneededDrops,
321+
match_branches::MatchBranchSimplification,
322+
// inst combine is after MatchBranchSimplification to clean up Ne(_1, false)
323+
multiple_return_terminators::MultipleReturnTerminators,
324+
instcombine::InstCombine,
325+
const_prop::ConstProp,
326+
simplify_branches::SimplifyBranches::new("after-const-prop"),
327+
early_otherwise_branch::EarlyOtherwiseBranch,
328+
simplify_comparison_integral::SimplifyComparisonIntegral,
329+
simplify_try::SimplifyArmIdentity,
330+
simplify_try::SimplifyBranchSame,
331+
dest_prop::DestinationPropagation,
332+
copy_prop::CopyPropagation,
333+
simplify_branches::SimplifyBranches::new("after-copy-prop"),
334+
remove_noop_landing_pads::RemoveNoopLandingPads,
335+
simplify::SimplifyCfg::new("final"),
336+
nrvo::RenameReturnPlace,
337+
simplify::SimplifyLocals,
338+
multiple_return_terminators::MultipleReturnTerminators,
339+
]);
340+
} else {
341+
run_passes!(optimizations => [
342+
// FIXME(#70073): This pass is responsible for both optimization as well as some lints.
343+
const_prop::ConstProp,
344+
]);
345+
}
422346

423347
// Some cleanup necessary at least for LLVM and potentially other codegen backends.
424-
let pre_codegen_cleanup: &[&dyn MirPass<'tcx>] = &[
425-
&add_call_guards::CriticalCallEdges,
348+
run_passes!(optimizations => [
349+
add_call_guards::CriticalCallEdges,
426350
// Dump the end result for testing and debugging purposes.
427-
&dump_mir::Marker("PreCodegen"),
428-
];
429-
430-
// End of pass declarations, now actually run the passes.
431-
// Generator Lowering
432-
#[rustfmt::skip]
433-
run_passes(
434-
tcx,
435-
body,
436-
MirPhase::GeneratorLowering,
437-
&[
438-
if mir_opt_level > 0 {
439-
optimizations_with_generators
440-
} else {
441-
no_optimizations_with_generators
442-
}
443-
],
444-
);
445-
446-
// Main optimization passes
447-
#[rustfmt::skip]
448-
run_passes(
449-
tcx,
450-
body,
451-
MirPhase::Optimization,
452-
&[
453-
if mir_opt_level > 0 { optimizations } else { no_optimizations },
454-
pre_codegen_cleanup,
455-
],
456-
);
351+
dump_mir::Marker("PreCodegen"),
352+
]);
457353
}
458354

459355
fn optimized_mir<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx Body<'tcx> {

0 commit comments

Comments
 (0)