@@ -31,10 +31,10 @@ use crate::transform::MirPass;
3131use rustc_index:: vec:: { Idx , IndexVec } ;
3232use rustc_middle:: mir:: visit:: { MutVisitor , MutatingUseContext , PlaceContext , Visitor } ;
3333use rustc_middle:: mir:: * ;
34- use rustc_middle:: ty:: ParamEnv ;
3534use rustc_middle:: ty:: TyCtxt ;
3635use smallvec:: SmallVec ;
37- use std:: { borrow:: Cow , convert:: TryInto } ;
36+ use std:: borrow:: Cow ;
37+ use std:: convert:: TryInto ;
3838
3939pub struct SimplifyCfg {
4040 label : String ,
@@ -326,7 +326,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyLocals {
326326
327327pub fn simplify_locals < ' tcx > ( body : & mut Body < ' tcx > , tcx : TyCtxt < ' tcx > ) {
328328 // 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) ;
330330
331331 // Next, we're going to remove any `Local` with zero actual uses. When we remove those
332332 // `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>) {
336336 remove_unused_definitions ( & mut used_locals, body) ;
337337
338338 // 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) ;
341340
342341 // Only bother running the `LocalUpdater` if we actually found locals to remove.
343342 if map. iter ( ) . any ( Option :: is_none) {
@@ -350,61 +349,54 @@ pub fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) {
350349}
351350
352351/// 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 > (
354353 local_decls : & mut IndexVec < Local , V > ,
355- used_locals : & UsedLocals < ' tcx > ,
356- arg_count : u32 ,
354+ used_locals : & UsedLocals ,
357355) -> 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) ;
359357 let mut used = Local :: new ( 0 ) ;
360358
361359 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 ;
369363 }
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 ) ;
370370 }
371371 local_decls. truncate ( used. index ( ) ) ;
372372 map
373373}
374374
375375/// Keeps track of used & unused locals.
376- struct UsedLocals < ' tcx > {
376+ struct UsedLocals {
377377 increment : bool ,
378+ arg_count : u32 ,
378379 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 > ,
383380}
384381
385- impl UsedLocals < ' tcx > {
382+ impl UsedLocals {
386383 /// 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 {
392385 let mut this = Self {
393386 increment : true ,
387+ arg_count : body. arg_count . try_into ( ) . unwrap ( ) ,
394388 use_count : IndexVec :: from_elem ( 0 , & body. local_decls ) ,
395- is_static,
396- local_decls,
397- param_env,
398- tcx,
399389 } ;
400390 this. visit_body ( body) ;
401391 this
402392 }
403393
404394 /// Checks if local is used.
395+ ///
396+ /// Return place and arguments are always considered used.
405397 fn is_used ( & self , local : Local ) -> bool {
406398 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
408400 }
409401
410402 /// Updates the use counts to reflect the removal of given statement.
@@ -432,7 +424,7 @@ impl UsedLocals<'tcx> {
432424 }
433425}
434426
435- impl Visitor < ' tcx > for UsedLocals < ' tcx > {
427+ impl Visitor < ' _ > for UsedLocals {
436428 fn visit_statement ( & mut self , statement : & Statement < ' tcx > , location : Location ) {
437429 match statement. kind {
438430 StatementKind :: LlvmInlineAsm ( ..)
@@ -459,21 +451,7 @@ impl Visitor<'tcx> for UsedLocals<'tcx> {
459451 }
460452 }
461453
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 ) {
477455 if self . increment {
478456 self . use_count [ * local] += 1 ;
479457 } else {
@@ -484,10 +462,7 @@ impl Visitor<'tcx> for UsedLocals<'tcx> {
484462}
485463
486464/// 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 > ) {
491466 // The use counts are updated as we remove the statements. A local might become unused
492467 // during the retain operation, leading to a temporary inconsistency (storage statements or
493468 // definitions referencing the local might remain). For correctness it is crucial that this
0 commit comments