Skip to content

Commit cdc3d6d

Browse files
authored
Rollup merge of rust-lang#55244 - wesleywiser:issue-50411, r=nikomatsakis
Don't rerun MIR passes when inlining Fixes rust-lang#50411 r? @nikomatsakis I updated your commit message with additional details. Let me know if any of that is incorrect. I also added the appropriate `compile-flags` directive to the test. Thanks for you help on this! cc @RalfJung related to your PR rust-lang#55086
2 parents 298dcd5 + 4655866 commit cdc3d6d

File tree

5 files changed

+120
-72
lines changed

5 files changed

+120
-72
lines changed

src/librustc/mir/mod.rs

+36
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,38 @@ impl<'tcx> HasLocalDecls<'tcx> for Mir<'tcx> {
6969
}
7070
}
7171

72+
/// The various "big phases" that MIR goes through.
73+
///
74+
/// Warning: ordering of variants is significant
75+
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)]
76+
pub enum MirPhase {
77+
Build = 0,
78+
Const = 1,
79+
Validated = 2,
80+
Optimized = 3,
81+
}
82+
83+
impl MirPhase {
84+
/// Gets the index of the current MirPhase within the set of all MirPhases.
85+
pub fn phase_index(&self) -> usize {
86+
*self as usize
87+
}
88+
}
89+
7290
/// Lowered representation of a single function.
7391
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
7492
pub struct Mir<'tcx> {
7593
/// List of basic blocks. References to basic block use a newtyped index type `BasicBlock`
7694
/// that indexes into this vector.
7795
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
7896

97+
/// Records how far through the "desugaring and optimization" process this particular
98+
/// MIR has traversed. This is particularly useful when inlining, since in that context
99+
/// we instantiate the promoted constants and add them to our promoted vector -- but those
100+
/// promoted items have already been optimized, whereas ours have not. This field allows
101+
/// us to see the difference and forego optimization on the inlined promoted items.
102+
pub phase: MirPhase,
103+
79104
/// List of source scopes; these are referenced by statements
80105
/// and used for debuginfo. Indexed by a `SourceScope`.
81106
pub source_scopes: IndexVec<SourceScope, SourceScopeData>,
@@ -151,6 +176,7 @@ impl<'tcx> Mir<'tcx> {
151176
);
152177

153178
Mir {
179+
phase: MirPhase::Build,
154180
basic_blocks,
155181
source_scopes,
156182
source_scope_local_data,
@@ -368,6 +394,7 @@ pub enum Safety {
368394
}
369395

370396
impl_stable_hash_for!(struct Mir<'tcx> {
397+
phase,
371398
basic_blocks,
372399
source_scopes,
373400
source_scope_local_data,
@@ -616,6 +643,13 @@ impl_stable_hash_for!(enum self::ImplicitSelfKind {
616643
None
617644
});
618645

646+
impl_stable_hash_for!(enum self::MirPhase {
647+
Build,
648+
Const,
649+
Validated,
650+
Optimized,
651+
});
652+
619653
mod binding_form_impl {
620654
use ich::StableHashingContext;
621655
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
@@ -2786,6 +2820,7 @@ pub enum ClosureOutlivesSubject<'tcx> {
27862820

27872821
CloneTypeFoldableAndLiftImpls! {
27882822
BlockTailInfo,
2823+
MirPhase,
27892824
Mutability,
27902825
SourceInfo,
27912826
UpvarDecl,
@@ -2798,6 +2833,7 @@ CloneTypeFoldableAndLiftImpls! {
27982833

27992834
BraceStructTypeFoldableImpl! {
28002835
impl<'tcx> TypeFoldable<'tcx> for Mir<'tcx> {
2836+
phase,
28012837
basic_blocks,
28022838
source_scopes,
28032839
source_scope_local_data,

src/librustc_mir/dataflow/impls/borrows.rs

-1
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,6 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
184184
}
185185

186186
crate fn borrows(&self) -> &IndexVec<BorrowIndex, BorrowData<'tcx>> { &self.borrow_set.borrows }
187-
pub fn scope_tree(&self) -> &Lrc<region::ScopeTree> { &self.scope_tree }
188187

189188
pub fn location(&self, idx: BorrowIndex) -> &Location {
190189
&self.borrow_set.borrows[idx].reserve_location

src/librustc_mir/dataflow/mod.rs

-14
Original file line numberDiff line numberDiff line change
@@ -724,20 +724,6 @@ impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
724724
}
725725
}
726726
}
727-
728-
pub fn new_from_sets(mir: &'a Mir<'tcx>,
729-
dead_unwinds: &'a BitSet<mir::BasicBlock>,
730-
sets: AllSets<D::Idx>,
731-
denotation: D) -> Self {
732-
DataflowAnalysis {
733-
mir,
734-
dead_unwinds,
735-
flow_state: DataflowState {
736-
sets: sets,
737-
operator: denotation,
738-
}
739-
}
740-
}
741727
}
742728

743729
impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation

src/librustc_mir/transform/mod.rs

+73-57
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use borrow_check::nll::type_check;
1212
use build;
1313
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
14-
use rustc::mir::{Mir, Promoted};
14+
use rustc::mir::{Mir, MirPhase, Promoted};
1515
use rustc::ty::TyCtxt;
1616
use rustc::ty::query::Providers;
1717
use rustc::ty::steal::Steal;
@@ -155,53 +155,69 @@ pub trait MirPass {
155155
mir: &mut Mir<'tcx>);
156156
}
157157

158-
pub macro run_passes($tcx:ident, $mir:ident, $def_id:ident, $suite_index:expr; $($pass:expr,)*) {{
159-
let suite_index: usize = $suite_index;
160-
let run_passes = |mir: &mut _, promoted| {
158+
pub fn run_passes(
159+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
160+
mir: &mut Mir<'tcx>,
161+
def_id: DefId,
162+
mir_phase: MirPhase,
163+
passes: &[&dyn MirPass],
164+
) {
165+
let phase_index = mir_phase.phase_index();
166+
167+
let run_passes = |mir: &mut Mir<'tcx>, promoted| {
168+
if mir.phase >= mir_phase {
169+
return;
170+
}
171+
161172
let source = MirSource {
162-
def_id: $def_id,
163-
promoted
173+
def_id,
174+
promoted,
164175
};
165176
let mut index = 0;
166177
let mut run_pass = |pass: &dyn MirPass| {
167178
let run_hooks = |mir: &_, index, is_after| {
168-
dump_mir::on_mir_pass($tcx, &format_args!("{:03}-{:03}", suite_index, index),
179+
dump_mir::on_mir_pass(tcx, &format_args!("{:03}-{:03}", phase_index, index),
169180
&pass.name(), source, mir, is_after);
170181
};
171182
run_hooks(mir, index, false);
172-
pass.run_pass($tcx, source, mir);
183+
pass.run_pass(tcx, source, mir);
173184
run_hooks(mir, index, true);
174185

175186
index += 1;
176187
};
177-
$(run_pass(&$pass);)*
188+
189+
for pass in passes {
190+
run_pass(*pass);
191+
}
192+
193+
mir.phase = mir_phase;
178194
};
179195

180-
run_passes(&mut $mir, None);
196+
run_passes(mir, None);
181197

182-
for (index, promoted_mir) in $mir.promoted.iter_enumerated_mut() {
198+
for (index, promoted_mir) in mir.promoted.iter_enumerated_mut() {
183199
run_passes(promoted_mir, Some(index));
184200

185-
// Let's make sure we don't miss any nested instances
186-
assert!(promoted_mir.promoted.is_empty());
201+
//Let's make sure we don't miss any nested instances
202+
assert!(promoted_mir.promoted.is_empty())
187203
}
188-
}}
204+
}
189205

190206
fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Mir<'tcx>> {
191207
// Unsafety check uses the raw mir, so make sure it is run
192208
let _ = tcx.unsafety_check_result(def_id);
193209

194210
let mut mir = tcx.mir_built(def_id).steal();
195-
run_passes![tcx, mir, def_id, 0;
211+
run_passes(tcx, &mut mir, def_id, MirPhase::Const, &[
196212
// Remove all `EndRegion` statements that are not involved in borrows.
197-
cleanup_post_borrowck::CleanEndRegions,
213+
&cleanup_post_borrowck::CleanEndRegions,
198214

199215
// What we need to do constant evaluation.
200-
simplify::SimplifyCfg::new("initial"),
201-
type_check::TypeckMir,
202-
rustc_peek::SanityCheck,
203-
uniform_array_move_out::UniformArrayMoveOut,
204-
];
216+
&simplify::SimplifyCfg::new("initial"),
217+
&type_check::TypeckMir,
218+
&rustc_peek::SanityCheck,
219+
&uniform_array_move_out::UniformArrayMoveOut,
220+
]);
205221
tcx.alloc_steal_mir(mir)
206222
}
207223

@@ -214,11 +230,11 @@ fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
214230
}
215231

216232
let mut mir = tcx.mir_const(def_id).steal();
217-
run_passes![tcx, mir, def_id, 1;
233+
run_passes(tcx, &mut mir, def_id, MirPhase::Validated, &[
218234
// What we need to run borrowck etc.
219-
qualify_consts::QualifyAndPromoteConstants,
220-
simplify::SimplifyCfg::new("qualify-consts"),
221-
];
235+
&qualify_consts::QualifyAndPromoteConstants,
236+
&simplify::SimplifyCfg::new("qualify-consts"),
237+
]);
222238
tcx.alloc_steal_mir(mir)
223239
}
224240

@@ -232,59 +248,59 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
232248
}
233249

234250
let mut mir = tcx.mir_validated(def_id).steal();
235-
run_passes![tcx, mir, def_id, 2;
251+
run_passes(tcx, &mut mir, def_id, MirPhase::Optimized, &[
236252
// Remove all things not needed by analysis
237-
no_landing_pads::NoLandingPads,
238-
simplify_branches::SimplifyBranches::new("initial"),
239-
remove_noop_landing_pads::RemoveNoopLandingPads,
253+
&no_landing_pads::NoLandingPads,
254+
&simplify_branches::SimplifyBranches::new("initial"),
255+
&remove_noop_landing_pads::RemoveNoopLandingPads,
240256
// Remove all `AscribeUserType` statements.
241-
cleanup_post_borrowck::CleanAscribeUserType,
257+
&cleanup_post_borrowck::CleanAscribeUserType,
242258
// Remove all `FakeRead` statements and the borrows that are only
243259
// used for checking matches
244-
cleanup_post_borrowck::CleanFakeReadsAndBorrows,
245-
simplify::SimplifyCfg::new("early-opt"),
260+
&cleanup_post_borrowck::CleanFakeReadsAndBorrows,
261+
&simplify::SimplifyCfg::new("early-opt"),
246262

247263
// These next passes must be executed together
248-
add_call_guards::CriticalCallEdges,
249-
elaborate_drops::ElaborateDrops,
250-
no_landing_pads::NoLandingPads,
264+
&add_call_guards::CriticalCallEdges,
265+
&elaborate_drops::ElaborateDrops,
266+
&no_landing_pads::NoLandingPads,
251267
// AddValidation needs to run after ElaborateDrops and before EraseRegions, and it needs
252268
// an AllCallEdges pass right before it.
253-
add_call_guards::AllCallEdges,
254-
add_validation::AddValidation,
269+
&add_call_guards::AllCallEdges,
270+
&add_validation::AddValidation,
255271
// AddMovesForPackedDrops needs to run after drop
256272
// elaboration.
257-
add_moves_for_packed_drops::AddMovesForPackedDrops,
273+
&add_moves_for_packed_drops::AddMovesForPackedDrops,
258274

259-
simplify::SimplifyCfg::new("elaborate-drops"),
275+
&simplify::SimplifyCfg::new("elaborate-drops"),
260276

261277
// No lifetime analysis based on borrowing can be done from here on out.
262278

263279
// From here on out, regions are gone.
264-
erase_regions::EraseRegions,
280+
&erase_regions::EraseRegions,
265281

266-
lower_128bit::Lower128Bit,
282+
&lower_128bit::Lower128Bit,
267283

268284

269285
// Optimizations begin.
270-
uniform_array_move_out::RestoreSubsliceArrayMoveOut,
271-
inline::Inline,
286+
&uniform_array_move_out::RestoreSubsliceArrayMoveOut,
287+
&inline::Inline,
272288

273289
// Lowering generator control-flow and variables
274290
// has to happen before we do anything else to them.
275-
generator::StateTransform,
276-
277-
instcombine::InstCombine,
278-
const_prop::ConstProp,
279-
simplify_branches::SimplifyBranches::new("after-const-prop"),
280-
deaggregator::Deaggregator,
281-
copy_prop::CopyPropagation,
282-
remove_noop_landing_pads::RemoveNoopLandingPads,
283-
simplify::SimplifyCfg::new("final"),
284-
simplify::SimplifyLocals,
285-
286-
add_call_guards::CriticalCallEdges,
287-
dump_mir::Marker("PreCodegen"),
288-
];
291+
&generator::StateTransform,
292+
293+
&instcombine::InstCombine,
294+
&const_prop::ConstProp,
295+
&simplify_branches::SimplifyBranches::new("after-const-prop"),
296+
&deaggregator::Deaggregator,
297+
&copy_prop::CopyPropagation,
298+
&remove_noop_landing_pads::RemoveNoopLandingPads,
299+
&simplify::SimplifyCfg::new("final"),
300+
&simplify::SimplifyLocals,
301+
302+
&add_call_guards::CriticalCallEdges,
303+
&dump_mir::Marker("PreCodegen"),
304+
]);
289305
tcx.alloc_mir(mir)
290306
}

src/test/ui/issues/issue-50411.rs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Regression test for #50411: the MIR inliner was causing problems
2+
// here because it would inline promoted code (which had already had
3+
// elaborate-drops invoked on it) and then try to elaboate drops a
4+
// second time. Uncool.
5+
6+
// compile-flags:-Zmir-opt-level=3
7+
// compile-pass
8+
9+
fn main() {
10+
let _ = (0 .. 1).filter(|_| [1].iter().all(|_| true)).count();
11+
}

0 commit comments

Comments
 (0)