@@ -27,15 +27,15 @@ use rustc_hir::def_id::{DefId, LocalDefId};
27
27
use rustc_hir:: intravisit:: { self , NestedVisitorMap , Visitor } ;
28
28
use rustc_index:: vec:: IndexVec ;
29
29
use rustc_middle:: mir:: visit:: Visitor as _;
30
- use rustc_middle:: mir:: { dump_mir , traversal, Body , ConstQualifs , MirPass , MirPhase , Promoted } ;
30
+ use rustc_middle:: mir:: { traversal, Body , ConstQualifs , MirPass , MirPhase , Promoted } ;
31
31
use rustc_middle:: ty:: query:: Providers ;
32
32
use rustc_middle:: ty:: { self , TyCtxt , TypeFoldable } ;
33
33
use rustc_span:: { Span , Symbol } ;
34
34
35
35
#[ macro_use]
36
36
mod pass_manager;
37
37
38
- use pass_manager:: { Lint , MirLint } ;
38
+ use pass_manager:: { self as pm , Lint , MirLint } ;
39
39
40
40
mod abort_unwinding_calls;
41
41
mod add_call_guards;
@@ -174,66 +174,6 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxHashSet<LocalDefId> {
174
174
set
175
175
}
176
176
177
- fn run_passes (
178
- tcx : TyCtxt < ' tcx > ,
179
- body : & mut Body < ' tcx > ,
180
- mir_phase : MirPhase ,
181
- passes : & [ & [ & dyn MirPass < ' tcx > ] ] ,
182
- ) {
183
- let phase_index = mir_phase. phase_index ( ) ;
184
- let validate = tcx. sess . opts . debugging_opts . validate_mir ;
185
-
186
- if body. phase >= mir_phase {
187
- return ;
188
- }
189
-
190
- if validate {
191
- validate:: Validator { when : format ! ( "input to phase {:?}" , mir_phase) , mir_phase }
192
- . run_pass ( tcx, body) ;
193
- }
194
-
195
- let mut index = 0 ;
196
- let mut run_pass = |pass : & dyn MirPass < ' tcx > | {
197
- let run_hooks = |body : & _ , index, is_after| {
198
- let disambiguator = if is_after { "after" } else { "before" } ;
199
- dump_mir (
200
- tcx,
201
- Some ( & format_args ! ( "{:03}-{:03}" , phase_index, index) ) ,
202
- & pass. name ( ) ,
203
- & disambiguator,
204
- body,
205
- |_, _| Ok ( ( ) ) ,
206
- ) ;
207
- } ;
208
- run_hooks ( body, index, false ) ;
209
- pass. run_pass ( tcx, body) ;
210
- run_hooks ( body, index, true ) ;
211
-
212
- if validate {
213
- validate:: Validator {
214
- when : format ! ( "after {} in phase {:?}" , pass. name( ) , mir_phase) ,
215
- mir_phase,
216
- }
217
- . run_pass ( tcx, body) ;
218
- }
219
-
220
- index += 1 ;
221
- } ;
222
-
223
- for pass_group in passes {
224
- for pass in * pass_group {
225
- run_pass ( * pass) ;
226
- }
227
- }
228
-
229
- body. phase = mir_phase;
230
-
231
- if mir_phase == MirPhase :: Optimization {
232
- validate:: Validator { when : format ! ( "end of phase {:?}" , mir_phase) , mir_phase }
233
- . run_pass ( tcx, body) ;
234
- }
235
- }
236
-
237
177
fn mir_const_qualif ( tcx : TyCtxt < ' _ > , def : ty:: WithOptConstParam < LocalDefId > ) -> ConstQualifs {
238
178
let const_kind = tcx. hir ( ) . body_const_context ( def. did ) ;
239
179
@@ -285,19 +225,19 @@ fn mir_const<'tcx>(
285
225
286
226
rustc_middle:: mir:: dump_mir ( tcx, None , "mir_map" , & 0 , & body, |_, _| Ok ( ( ) ) ) ;
287
227
288
- run_passes (
228
+ pm :: run_passes (
289
229
tcx,
290
230
& mut body,
291
- MirPhase :: Const ,
292
- & [ & [
231
+ & [
293
232
// MIR-level lints.
294
233
& Lint ( check_packed_ref:: CheckPackedRef ) ,
295
234
& Lint ( check_const_item_mutation:: CheckConstItemMutation ) ,
296
235
& Lint ( function_item_references:: FunctionItemReferences ) ,
297
236
// What we need to do constant evaluation.
298
237
& simplify:: SimplifyCfg :: new ( "initial" ) ,
299
238
& rustc_peek:: SanityCheck , // Just a lint
300
- ] ] ,
239
+ & marker:: PhaseChange ( MirPhase :: Const ) ,
240
+ ] ,
301
241
) ;
302
242
tcx. alloc_steal_mir ( body)
303
243
}
@@ -324,17 +264,17 @@ fn mir_promoted(
324
264
}
325
265
body. required_consts = required_consts;
326
266
267
+ // What we need to run borrowck etc.
327
268
let promote_pass = promote_consts:: PromoteTemps :: default ( ) ;
328
- let promote: & [ & dyn MirPass < ' tcx > ] = & [
329
- // What we need to run borrowck etc.
330
- & promote_pass,
331
- & simplify:: SimplifyCfg :: new ( "promote-consts" ) ,
332
- ] ;
333
-
334
- let opt_coverage: & [ & dyn MirPass < ' tcx > ] =
335
- if tcx. sess . instrument_coverage ( ) { & [ & coverage:: InstrumentCoverage ] } else { & [ ] } ;
336
-
337
- run_passes ( tcx, & mut body, MirPhase :: ConstPromotion , & [ promote, opt_coverage] ) ;
269
+ pm:: run_passes (
270
+ tcx,
271
+ & mut body,
272
+ & [
273
+ & promote_pass,
274
+ & simplify:: SimplifyCfg :: new ( "promote-consts" ) ,
275
+ & coverage:: InstrumentCoverage ,
276
+ ] ,
277
+ ) ;
338
278
339
279
let promoted = promote_pass. promoted_fragments . into_inner ( ) ;
340
280
( 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>) -
396
336
// Technically we want to not run on regular const items, but oli-obk doesn't know how to
397
337
// conveniently detect that at this point without looking at the HIR.
398
338
hir:: ConstContext :: Const => {
399
- #[ rustfmt:: skip]
400
- let optimizations: & [ & dyn MirPass < ' _ > ] = & [
401
- & const_prop:: ConstProp ,
402
- ] ;
403
-
404
- #[ rustfmt:: skip]
405
- run_passes (
339
+ pm:: run_passes (
406
340
tcx,
407
341
& mut body,
408
- MirPhase :: Optimization ,
409
- & [
410
- optimizations,
411
- ] ,
342
+ & [ & const_prop:: ConstProp , & marker:: PhaseChange ( MirPhase :: Optimization ) ] ,
412
343
) ;
413
344
}
414
345
}
@@ -453,19 +384,23 @@ fn mir_drops_elaborated_and_const_checked<'tcx>(
453
384
let mut body = body. steal ( ) ;
454
385
455
386
// IMPORTANT
456
- remove_false_edges :: RemoveFalseEdges . run_pass ( tcx, & mut body) ;
387
+ pm :: run_passes ( tcx, & mut body, & [ & remove_false_edges :: RemoveFalseEdges ] ) ;
457
388
458
389
// Do a little drop elaboration before const-checking if `const_precise_live_drops` is enabled.
459
- //
460
- // FIXME: Can't use `run_passes` for these, since `run_passes` SILENTLY DOES NOTHING IF THE MIR
461
- // PHASE DOESN'T CHANGE.
462
390
if check_consts:: post_drop_elaboration:: checking_enabled ( & ConstCx :: new ( tcx, & body) ) {
463
- simplify:: SimplifyCfg :: new ( "remove-false-edges" ) . run_pass ( tcx, & mut body) ;
464
- remove_uninit_drops:: RemoveUninitDrops . run_pass ( tcx, & mut body) ;
465
- check_consts:: post_drop_elaboration:: check_live_drops ( tcx, & body) ;
391
+ pm:: run_passes (
392
+ tcx,
393
+ & mut body,
394
+ & [
395
+ & simplify:: SimplifyCfg :: new ( "remove-false-edges" ) ,
396
+ & remove_uninit_drops:: RemoveUninitDrops ,
397
+ ] ,
398
+ ) ;
399
+ check_consts:: post_drop_elaboration:: check_live_drops ( tcx, & body) ; // FIXME: make this a MIR lint
466
400
}
467
401
468
402
run_post_borrowck_cleanup_passes ( tcx, & mut body) ;
403
+ assert ! ( body. phase == MirPhase :: DropLowering ) ;
469
404
tcx. alloc_steal_mir ( body)
470
405
}
471
406
@@ -499,95 +434,65 @@ fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tc
499
434
& deaggregator:: Deaggregator ,
500
435
] ;
501
436
502
- run_passes ( tcx, body, MirPhase :: DropLowering , & [ post_borrowck_cleanup] ) ;
437
+ pm :: run_passes ( tcx, body, post_borrowck_cleanup) ;
503
438
}
504
439
505
440
fn run_optimization_passes < ' tcx > ( tcx : TyCtxt < ' tcx > , body : & mut Body < ' tcx > ) {
506
- let mir_opt_level = tcx. sess . mir_opt_level ( ) ;
507
-
508
441
// Lowering generator control-flow and variables has to happen before we do anything else
509
442
// to them. We run some optimizations before that, because they may be harder to do on the state
510
443
// machine than on MIR with async primitives.
511
- let optimizations_with_generators: & [ & dyn MirPass < ' tcx > ] = & [
512
- & reveal_all:: RevealAll , // has to be done before inlining, since inlined code is in RevealAll mode.
513
- & 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
514
- & normalize_array_len:: NormalizeArrayLen , // has to run after `slice::len` lowering
515
- & unreachable_prop:: UnreachablePropagation ,
516
- & uninhabited_enum_branching:: UninhabitedEnumBranching ,
517
- & simplify:: SimplifyCfg :: new ( "after-uninhabited-enum-branching" ) ,
518
- & inline:: Inline ,
519
- & generator:: StateTransform ,
520
- ] ;
521
-
522
- // Even if we don't do optimizations, we still have to lower generators for codegen.
523
- let no_optimizations_with_generators: & [ & dyn MirPass < ' tcx > ] = & [ & generator:: StateTransform ] ;
524
-
525
- // The main optimizations that we do on MIR.
526
- let optimizations: & [ & dyn MirPass < ' tcx > ] = & [
527
- & remove_storage_markers:: RemoveStorageMarkers ,
528
- & remove_zsts:: RemoveZsts ,
529
- & const_goto:: ConstGoto ,
530
- & remove_unneeded_drops:: RemoveUnneededDrops ,
531
- & match_branches:: MatchBranchSimplification ,
532
- // inst combine is after MatchBranchSimplification to clean up Ne(_1, false)
533
- & multiple_return_terminators:: MultipleReturnTerminators ,
534
- & instcombine:: InstCombine ,
535
- & separate_const_switch:: SeparateConstSwitch ,
536
- & const_prop:: ConstProp ,
537
- & simplify_branches:: SimplifyConstCondition :: new ( "after-const-prop" ) ,
538
- & early_otherwise_branch:: EarlyOtherwiseBranch ,
539
- & simplify_comparison_integral:: SimplifyComparisonIntegral ,
540
- & simplify_try:: SimplifyArmIdentity ,
541
- & simplify_try:: SimplifyBranchSame ,
542
- & dest_prop:: DestinationPropagation ,
543
- & simplify_branches:: SimplifyConstCondition :: new ( "final" ) ,
544
- & remove_noop_landing_pads:: RemoveNoopLandingPads ,
545
- & simplify:: SimplifyCfg :: new ( "final" ) ,
546
- & nrvo:: RenameReturnPlace ,
547
- & const_debuginfo:: ConstDebugInfo ,
548
- & simplify:: SimplifyLocals ,
549
- & multiple_return_terminators:: MultipleReturnTerminators ,
550
- & deduplicate_blocks:: DeduplicateBlocks ,
551
- ] ;
552
-
553
- // Optimizations to run even if mir optimizations have been disabled.
554
- let no_optimizations: & [ & dyn MirPass < ' tcx > ] = & [
555
- // FIXME(#70073): This pass is responsible for both optimization as well as some lints.
556
- & const_prop:: ConstProp ,
557
- ] ;
558
-
559
- // Some cleanup necessary at least for LLVM and potentially other codegen backends.
560
- let pre_codegen_cleanup: & [ & dyn MirPass < ' tcx > ] = & [
561
- & add_call_guards:: CriticalCallEdges ,
562
- // Dump the end result for testing and debugging purposes.
563
- & dump_mir:: Marker ( "PreCodegen" ) ,
564
- ] ;
565
-
566
- // End of pass declarations, now actually run the passes.
567
- // Generator Lowering
568
- #[ rustfmt:: skip]
569
- run_passes (
444
+ pm:: run_passes (
570
445
tcx,
571
446
body,
572
- MirPhase :: GeneratorLowering ,
573
447
& [
574
- if mir_opt_level > 0 {
575
- optimizations_with_generators
576
- } else {
577
- no_optimizations_with_generators
578
- }
448
+ & reveal_all:: RevealAll , // has to be done before inlining, since inlined code is in RevealAll mode.
449
+ & 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
450
+ & normalize_array_len:: NormalizeArrayLen , // has to run after `slice::len` lowering
451
+ & unreachable_prop:: UnreachablePropagation ,
452
+ & uninhabited_enum_branching:: UninhabitedEnumBranching ,
453
+ & simplify:: SimplifyCfg :: new ( "after-uninhabited-enum-branching" ) ,
454
+ & inline:: Inline ,
455
+ & generator:: StateTransform ,
579
456
] ,
580
457
) ;
581
458
582
- // Main optimization passes
583
- #[ rustfmt:: skip]
584
- run_passes (
459
+ assert ! ( body. phase == MirPhase :: GeneratorLowering ) ;
460
+
461
+ // The main optimizations that we do on MIR.
462
+ pm:: run_passes (
585
463
tcx,
586
464
body,
587
- MirPhase :: Optimization ,
588
465
& [
589
- if mir_opt_level > 0 { optimizations } else { no_optimizations } ,
590
- pre_codegen_cleanup,
466
+ & remove_storage_markers:: RemoveStorageMarkers ,
467
+ & remove_zsts:: RemoveZsts ,
468
+ & const_goto:: ConstGoto ,
469
+ & remove_unneeded_drops:: RemoveUnneededDrops ,
470
+ & match_branches:: MatchBranchSimplification ,
471
+ // inst combine is after MatchBranchSimplification to clean up Ne(_1, false)
472
+ & multiple_return_terminators:: MultipleReturnTerminators ,
473
+ & instcombine:: InstCombine ,
474
+ & separate_const_switch:: SeparateConstSwitch ,
475
+ // FIXME(#70073): This pass is responsible for both optimization as well as some lints.
476
+ & const_prop:: ConstProp ,
477
+ & simplify_branches:: SimplifyBranches :: new ( "after-const-prop" ) ,
478
+ & early_otherwise_branch:: EarlyOtherwiseBranch ,
479
+ & simplify_comparison_integral:: SimplifyComparisonIntegral ,
480
+ & simplify_try:: SimplifyArmIdentity ,
481
+ & simplify_try:: SimplifyBranchSame ,
482
+ & dest_prop:: DestinationPropagation ,
483
+ & simplify_branches:: SimplifyBranches :: new ( "final" ) ,
484
+ & remove_noop_landing_pads:: RemoveNoopLandingPads ,
485
+ & simplify:: SimplifyCfg :: new ( "final" ) ,
486
+ & nrvo:: RenameReturnPlace ,
487
+ & const_debuginfo:: ConstDebugInfo ,
488
+ & simplify:: SimplifyLocals ,
489
+ & multiple_return_terminators:: MultipleReturnTerminators ,
490
+ & deduplicate_blocks:: DeduplicateBlocks ,
491
+ // Some cleanup necessary at least for LLVM and potentially other codegen backends.
492
+ & add_call_guards:: CriticalCallEdges ,
493
+ & marker:: PhaseChange ( MirPhase :: Optimization ) ,
494
+ // Dump the end result for testing and debugging purposes.
495
+ & dump_mir:: Marker ( "PreCodegen" ) ,
591
496
] ,
592
497
) ;
593
498
}
0 commit comments