@@ -31,10 +31,10 @@ use crate::transform::MirPass;
31
31
use rustc_index:: vec:: { Idx , IndexVec } ;
32
32
use rustc_middle:: mir:: visit:: { MutVisitor , MutatingUseContext , PlaceContext , Visitor } ;
33
33
use rustc_middle:: mir:: * ;
34
- use rustc_middle:: ty:: ParamEnv ;
35
34
use rustc_middle:: ty:: TyCtxt ;
36
35
use smallvec:: SmallVec ;
37
- use std:: { borrow:: Cow , convert:: TryInto } ;
36
+ use std:: borrow:: Cow ;
37
+ use std:: convert:: TryInto ;
38
38
39
39
pub struct SimplifyCfg {
40
40
label : String ,
@@ -326,7 +326,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyLocals {
326
326
327
327
pub fn simplify_locals < ' tcx > ( body : & mut Body < ' tcx > , tcx : TyCtxt < ' tcx > ) {
328
328
// First, we're going to get a count of *actual* uses for every `Local`.
329
- let mut used_locals = UsedLocals :: new ( body, tcx ) ;
329
+ let mut used_locals = UsedLocals :: new ( body) ;
330
330
331
331
// Next, we're going to remove any `Local` with zero actual uses. When we remove those
332
332
// `Locals`, we're also going to subtract any uses of other `Locals` from the `used_locals`
@@ -336,8 +336,7 @@ pub fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) {
336
336
remove_unused_definitions ( & mut used_locals, body) ;
337
337
338
338
// Finally, we'll actually do the work of shrinking `body.local_decls` and remapping the `Local`s.
339
- let arg_count = body. arg_count . try_into ( ) . unwrap ( ) ;
340
- let map = make_local_map ( & mut body. local_decls , & used_locals, arg_count) ;
339
+ let map = make_local_map ( & mut body. local_decls , & used_locals) ;
341
340
342
341
// Only bother running the `LocalUpdater` if we actually found locals to remove.
343
342
if map. iter ( ) . any ( Option :: is_none) {
@@ -350,61 +349,54 @@ pub fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) {
350
349
}
351
350
352
351
/// Construct the mapping while swapping out unused stuff out from the `vec`.
353
- fn make_local_map < ' tcx , V > (
352
+ fn make_local_map < V > (
354
353
local_decls : & mut IndexVec < Local , V > ,
355
- used_locals : & UsedLocals < ' tcx > ,
356
- arg_count : u32 ,
354
+ used_locals : & UsedLocals ,
357
355
) -> IndexVec < Local , Option < Local > > {
358
- let mut map: IndexVec < Local , Option < Local > > = IndexVec :: from_elem ( None , local_decls) ;
356
+ let mut map: IndexVec < Local , Option < Local > > = IndexVec :: from_elem ( None , & * local_decls) ;
359
357
let mut used = Local :: new ( 0 ) ;
360
358
361
359
for alive_index in local_decls. indices ( ) {
362
- // When creating the local map treat the `RETURN_PLACE` and arguments as used.
363
- if alive_index. as_u32 ( ) <= arg_count || used_locals. is_used ( alive_index) {
364
- map[ alive_index] = Some ( used) ;
365
- if alive_index != used {
366
- local_decls. swap ( alive_index, used) ;
367
- }
368
- used. increment_by ( 1 ) ;
360
+ // `is_used` treats the `RETURN_PLACE` and arguments as used.
361
+ if !used_locals. is_used ( alive_index) {
362
+ continue ;
369
363
}
364
+
365
+ map[ alive_index] = Some ( used) ;
366
+ if alive_index != used {
367
+ local_decls. swap ( alive_index, used) ;
368
+ }
369
+ used. increment_by ( 1 ) ;
370
370
}
371
371
local_decls. truncate ( used. index ( ) ) ;
372
372
map
373
373
}
374
374
375
375
/// Keeps track of used & unused locals.
376
- struct UsedLocals < ' tcx > {
376
+ struct UsedLocals {
377
377
increment : bool ,
378
+ arg_count : u32 ,
378
379
use_count : IndexVec < Local , u32 > ,
379
- is_static : bool ,
380
- local_decls : IndexVec < Local , LocalDecl < ' tcx > > ,
381
- param_env : ParamEnv < ' tcx > ,
382
- tcx : TyCtxt < ' tcx > ,
383
380
}
384
381
385
- impl UsedLocals < ' tcx > {
382
+ impl UsedLocals {
386
383
/// Determines which locals are used & unused in the given body.
387
- fn new ( body : & Body < ' tcx > , tcx : TyCtxt < ' tcx > ) -> Self {
388
- let def_id = body. source . def_id ( ) ;
389
- let is_static = tcx. is_static ( def_id) ;
390
- let param_env = tcx. param_env ( def_id) ;
391
- let local_decls = body. local_decls . clone ( ) ;
384
+ fn new ( body : & Body < ' _ > ) -> Self {
392
385
let mut this = Self {
393
386
increment : true ,
387
+ arg_count : body. arg_count . try_into ( ) . unwrap ( ) ,
394
388
use_count : IndexVec :: from_elem ( 0 , & body. local_decls ) ,
395
- is_static,
396
- local_decls,
397
- param_env,
398
- tcx,
399
389
} ;
400
390
this. visit_body ( body) ;
401
391
this
402
392
}
403
393
404
394
/// Checks if local is used.
395
+ ///
396
+ /// Return place and arguments are always considered used.
405
397
fn is_used ( & self , local : Local ) -> bool {
406
398
trace ! ( "is_used({:?}): use_count: {:?}" , local, self . use_count[ local] ) ;
407
- self . use_count [ local] != 0
399
+ local . as_u32 ( ) <= self . arg_count || self . use_count [ local] != 0
408
400
}
409
401
410
402
/// Updates the use counts to reflect the removal of given statement.
@@ -432,7 +424,7 @@ impl UsedLocals<'tcx> {
432
424
}
433
425
}
434
426
435
- impl Visitor < ' tcx > for UsedLocals < ' tcx > {
427
+ impl Visitor < ' _ > for UsedLocals {
436
428
fn visit_statement ( & mut self , statement : & Statement < ' tcx > , location : Location ) {
437
429
match statement. kind {
438
430
StatementKind :: LlvmInlineAsm ( ..)
@@ -459,21 +451,7 @@ impl Visitor<'tcx> for UsedLocals<'tcx> {
459
451
}
460
452
}
461
453
462
- fn visit_local ( & mut self , local : & Local , ctx : PlaceContext , _location : Location ) {
463
- debug ! ( "local: {:?} is_static: {:?}, ctx: {:?}" , local, self . is_static, ctx) ;
464
- // Do not count _0 as a used in `return;` if it is a ZST.
465
- let return_place = * local == RETURN_PLACE
466
- && matches ! ( ctx, PlaceContext :: NonMutatingUse ( visit:: NonMutatingUseContext :: Move ) ) ;
467
- if !self . is_static && return_place {
468
- let ty = self . local_decls [ * local] . ty ;
469
- let param_env_and = self . param_env . and ( ty) ;
470
- if let Ok ( layout) = self . tcx . layout_of ( param_env_and) {
471
- debug ! ( "layout.is_zst: {:?}" , layout. is_zst( ) ) ;
472
- if layout. is_zst ( ) {
473
- return ;
474
- }
475
- }
476
- }
454
+ fn visit_local ( & mut self , local : & Local , _ctx : PlaceContext , _location : Location ) {
477
455
if self . increment {
478
456
self . use_count [ * local] += 1 ;
479
457
} else {
@@ -484,10 +462,7 @@ impl Visitor<'tcx> for UsedLocals<'tcx> {
484
462
}
485
463
486
464
/// Removes unused definitions. Updates the used locals to reflect the changes made.
487
- fn remove_unused_definitions < ' a , ' tcx > (
488
- used_locals : & ' a mut UsedLocals < ' tcx > ,
489
- body : & mut Body < ' tcx > ,
490
- ) {
465
+ fn remove_unused_definitions < ' a , ' tcx > ( used_locals : & ' a mut UsedLocals , body : & mut Body < ' tcx > ) {
491
466
// The use counts are updated as we remove the statements. A local might become unused
492
467
// during the retain operation, leading to a temporary inconsistency (storage statements or
493
468
// definitions referencing the local might remain). For correctness it is crucial that this
0 commit comments