Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a MIR pass manager, take 2 #91386

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions compiler/rustc_const_eval/src/transform/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
pub mod check_consts;
pub mod promote_consts;
pub mod validate;

pub use rustc_middle::mir::MirPass;
12 changes: 4 additions & 8 deletions compiler/rustc_const_eval/src/transform/promote_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,21 @@ use rustc_span::Span;

use rustc_index::vec::{Idx, IndexVec};

use std::cell::Cell;
use std::{cmp, iter, mem};

use crate::transform::check_consts::{qualifs, ConstCx};
use crate::transform::MirPass;

/// A `MirPass` for promotion.
///
/// Promotion is the extraction of promotable temps into separate MIR bodies so they can have
/// `'static` lifetime.
///
/// After this pass is run, `promoted_fragments` will hold the MIR body corresponding to each
/// After this pass is run, `body.promoted_fragments` will hold the MIR body corresponding to each
/// newly created `Constant`.
#[derive(Default)]
pub struct PromoteTemps<'tcx> {
pub promoted_fragments: Cell<IndexVec<Promoted, Body<'tcx>>>,
}
pub struct PromoteTemps;

impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> {
impl<'tcx> MirPass<'tcx> for PromoteTemps {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// There's not really any point in promoting errorful MIR.
//
Expand All @@ -62,7 +58,7 @@ impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> {
let promotable_candidates = validate_candidates(&ccx, &temps, &all_candidates);

let promoted = promote_candidates(body, tcx, temps, promotable_candidates);
self.promoted_fragments.set(promoted);
body.promoted_fragments = promoted;
}
}

Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_const_eval/src/transform/validate.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
//! Validates the MIR to ensure that invariants are upheld.

use super::MirPass;
use rustc_index::bit_set::BitSet;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::traversal;
use rustc_middle::mir::visit::{PlaceContext, Visitor};
use rustc_middle::mir::{
AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceElem,
PlaceRef, ProjectionElem, Rvalue, SourceScope, Statement, StatementKind, Terminator,
AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPass, MirPhase, Operand,
PlaceElem, PlaceRef, ProjectionElem, Rvalue, SourceScope, Statement, StatementKind, Terminator,
TerminatorKind, START_BLOCK,
};
use rustc_middle::ty::fold::BottomUpFolder;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -731,7 +731,7 @@ fn test_debugging_options_tracking_hash() {
tracked!(function_sections, Some(false));
tracked!(human_readable_cgu_names, true);
tracked!(inline_in_all_cgus, Some(true));
tracked!(inline_mir, Some(true));
tracked!(inline_mir, true);
tracked!(inline_mir_hint_threshold, Some(123));
tracked!(inline_mir_threshold, Some(123));
tracked!(instrument_coverage, Some(InstrumentCoverage::All));
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_middle/src/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,12 @@ pub struct Body<'tcx> {
/// potentially allow things like `[u8; std::mem::size_of::<T>() * 0]` due to this.
pub is_polymorphic: bool,

/// A list of MIR fragments for promotable temps inside this body.
///
/// This field is only populated during the `PromoteTemps` MIR pass and will be emptied
/// immediately after.
pub promoted_fragments: IndexVec<Promoted, Body<'tcx>>,

predecessor_cache: PredecessorCache,
is_cyclic: GraphIsCyclicCache,
}
Expand Down Expand Up @@ -311,6 +317,7 @@ impl<'tcx> Body<'tcx> {
is_polymorphic: false,
predecessor_cache: PredecessorCache::new(),
is_cyclic: GraphIsCyclicCache::new(),
promoted_fragments: Default::default(),
};
body.is_polymorphic = body.definitely_has_param_types_or_consts(tcx);
body
Expand Down Expand Up @@ -338,6 +345,7 @@ impl<'tcx> Body<'tcx> {
is_polymorphic: false,
predecessor_cache: PredecessorCache::new(),
is_cyclic: GraphIsCyclicCache::new(),
promoted_fragments: Default::default(),
}
}

Expand Down
11 changes: 10 additions & 1 deletion compiler/rustc_mir_transform/src/coverage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ use counters::CoverageCounters;
use graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph};
use spans::{CoverageSpan, CoverageSpans};

use crate::MirPass;
use crate::pass_manager::{Flag, Constraint, constraints::*};
use crate::{MirPass, MirPassC};

use rustc_data_structures::graph::WithNumNodes;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
Expand Down Expand Up @@ -48,6 +49,14 @@ impl Error {
/// to construct the coverage map.
pub struct InstrumentCoverage;

impl MirPassC for InstrumentCoverage {
const FLAGS: &'static [Flag] = &[Flag::InstrumentCoverage];
const CONSTRAINTS: &'static [Constraint] = &[
// Promoteds run at compile-time, so they don't have meaningful coverage information.
after::<super::promote_consts::PromoteTemps>(),
];
}

impl<'tcx> MirPass<'tcx> for InstrumentCoverage {
fn run_pass(&self, tcx: TyCtxt<'tcx>, mir_body: &mut mir::Body<'tcx>) {
let mir_source = mir_body.source;
Expand Down
6 changes: 1 addition & 5 deletions compiler/rustc_mir_transform/src/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,7 @@ struct CallSite<'tcx> {

/// Returns true if MIR inlining is enabled in the current compilation session.
crate fn is_enabled(tcx: TyCtxt<'_>) -> bool {
if let Some(enabled) = tcx.sess.opts.debugging_opts.inline_mir {
return enabled;
}

tcx.sess.mir_opt_level() >= 3
tcx.sess.opts.debugging_opts.inline_mir && tcx.sess.mir_opt_level() >= 3
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes the condition. Before it would always run if -Zinline-mir=yes is used, never if -Zinline-mir=no is used and only for mir opt level >= 3 if -Zinline-mir is not specified. After it will only run when -Zinline-mir=yes and mir opt level >= 3 is combined.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah. I'm sorry. I understand the Option<bool> now.

}

impl<'tcx> MirPass<'tcx> for Inline {
Expand Down
37 changes: 23 additions & 14 deletions compiler/rustc_mir_transform/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(const_fn_trait_bound)]
#![feature(const_mut_refs)]
#![feature(const_range_bounds)]
#![feature(const_trait_impl)]
#![feature(const_type_id)]
#![feature(const_type_id_cmp)]
#![feature(crate_visibility_modifier)]
#![feature(in_band_lifetimes)]
#![feature(iter_zip)]
Expand Down Expand Up @@ -27,11 +33,16 @@ 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, MirPhase, Promoted};
use rustc_middle::mir::{dump_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};

use self::pass_manager::{Lint, MirPassC};

#[macro_use]
mod pass_manager;

mod abort_unwinding_calls;
mod add_call_guards;
mod add_moves_for_packed_drops;
Expand Down Expand Up @@ -78,9 +89,13 @@ mod unreachable_prop;
use rustc_const_eval::transform::check_consts;
use rustc_const_eval::transform::promote_consts;
use rustc_const_eval::transform::validate;
pub use rustc_const_eval::transform::MirPass;
use rustc_mir_dataflow::rustc_peek;

// TODO: All MIR passes should be defined in this module. Until then...
impl MirPassC for promote_consts::PromoteTemps {
const PHASE_CHANGE: Option<MirPhase> = Some(MirPhase::ConstPromotion);
}

pub fn provide(providers: &mut Providers) {
check_unsafety::provide(providers);
check_packed_ref::provide(providers);
Expand Down Expand Up @@ -317,19 +332,13 @@ fn mir_promoted(
}
body.required_consts = required_consts;

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]);
run_passes!(tcx, &mut body, [
promote_consts::PromoteTemps,
simplify::SimplifyCfg::new("promote-consts"),
coverage::InstrumentCoverage,
]);

let promoted = promote_pass.promoted_fragments.into_inner();
let promoted = std::mem::take(&mut body.promoted_fragments);
(tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted))
}

Expand Down
Loading