提交 37e1d297 编写于 作者: N Niko Matsakis 提交者: Wesley Wiser

Don't rerun Mir passes when inlining

When inlining a function using the Mir inliner, we shouldn't rerun the
various Mir passes on it because the Mir has already been lowered and
that wil break various early Mir passes.

The issue in #50411 is that we've inlined a function with promotions
whose Mir has already been lowered. The promotions are then copied into
the local function and we begin to run passes on their lowered Mir
which causes the ICE.

Fixes #50411
上级 22cc2ae8
......@@ -69,6 +69,17 @@ fn local_decls(&self) -> &LocalDecls<'tcx> {
}
}
/// The various "big phases" that MIR goes through.
///
/// Warning: ordering of variants is significant
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum MirPhase {
Build,
Const,
Validated,
Optimized,
}
/// Lowered representation of a single function.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Mir<'tcx> {
......@@ -76,6 +87,13 @@ pub struct Mir<'tcx> {
/// that indexes into this vector.
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
/// Records how far through the "desugaring and optimization" process this particular
/// MIR has traversed. This is particularly useful when inlining, since in that context
/// we instantiate the promoted constants and add them to our promoted vector -- but those
/// promoted items have already been optimized, whereas ours have not. This field allows
/// us to see the difference and forego optimization on the inlined promoted items.
pub phase: MirPhase,
/// List of source scopes; these are referenced by statements
/// and used for debuginfo. Indexed by a `SourceScope`.
pub source_scopes: IndexVec<SourceScope, SourceScopeData>,
......@@ -151,6 +169,7 @@ pub fn new(
);
Mir {
phase: MirPhase::Build,
basic_blocks,
source_scopes,
source_scope_local_data,
......@@ -368,6 +387,7 @@ pub enum Safety {
}
impl_stable_hash_for!(struct Mir<'tcx> {
phase,
basic_blocks,
source_scopes,
source_scope_local_data,
......@@ -616,6 +636,13 @@ pub enum ImplicitSelfKind {
None
});
impl_stable_hash_for!(enum self::MirPhase {
Build,
Const,
Validated,
Optimized,
});
mod binding_form_impl {
use ich::StableHashingContext;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
......@@ -2777,6 +2804,7 @@ pub enum ClosureOutlivesSubject<'tcx> {
CloneTypeFoldableAndLiftImpls! {
BlockTailInfo,
MirPhase,
Mutability,
SourceInfo,
UpvarDecl,
......@@ -2789,6 +2817,7 @@ pub enum ClosureOutlivesSubject<'tcx> {
BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for Mir<'tcx> {
phase,
basic_blocks,
source_scopes,
source_scope_local_data,
......
......@@ -11,7 +11,7 @@
use borrow_check::nll::type_check;
use build;
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc::mir::{Mir, Promoted};
use rustc::mir::{Mir, MirPhase, Promoted};
use rustc::ty::TyCtxt;
use rustc::ty::query::Providers;
use rustc::ty::steal::Steal;
......@@ -155,9 +155,22 @@ fn run_pass<'a, 'tcx>(&self,
mir: &mut Mir<'tcx>);
}
pub macro run_passes($tcx:ident, $mir:ident, $def_id:ident, $suite_index:expr; $($pass:expr,)*) {{
pub macro run_passes(
$tcx:ident,
$mir:ident,
$def_id:ident,
$suite_index:expr,
$mir_phase:expr;
$($pass:expr,)*
) {{
let suite_index: usize = $suite_index;
let run_passes = |mir: &mut _, promoted| {
let mir: &mut Mir<'_> = mir;
if mir.phase >= $mir_phase {
return;
}
let source = MirSource {
def_id: $def_id,
promoted
......@@ -175,6 +188,8 @@ fn run_pass<'a, 'tcx>(&self,
index += 1;
};
$(run_pass(&$pass);)*
mir.phase = $mir_phase;
};
run_passes(&mut $mir, None);
......@@ -192,7 +207,7 @@ fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Stea
let _ = tcx.unsafety_check_result(def_id);
let mut mir = tcx.mir_built(def_id).steal();
run_passes![tcx, mir, def_id, 0;
run_passes![tcx, mir, def_id, 0, MirPhase::Const;
// Remove all `EndRegion` statements that are not involved in borrows.
cleanup_post_borrowck::CleanEndRegions,
......@@ -214,7 +229,7 @@ fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
}
let mut mir = tcx.mir_const(def_id).steal();
run_passes![tcx, mir, def_id, 1;
run_passes![tcx, mir, def_id, 1, MirPhase::Validated;
// What we need to run borrowck etc.
qualify_consts::QualifyAndPromoteConstants,
simplify::SimplifyCfg::new("qualify-consts"),
......@@ -232,7 +247,7 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
}
let mut mir = tcx.mir_validated(def_id).steal();
run_passes![tcx, mir, def_id, 2;
run_passes![tcx, mir, def_id, 2, MirPhase::Optimized;
// Remove all things not needed by analysis
no_landing_pads::NoLandingPads,
simplify_branches::SimplifyBranches::new("initial"),
......
// Regression test for #50411: the MIR inliner was causing problems
// here because it would inline promoted code (which had already had
// elaborate-drops invoked on it) and then try to elaboate drops a
// second time. Uncool.
// compile-flags:-Zmir-opt-level=3
// compile-pass
fn main() {
let _ = (0 .. 1).filter(|_| [1].iter().all(|_| true)).count();
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册