@@ -30,6 +30,8 @@ impl<'tcx> crate::MirPass<'tcx> for CopyProp {
30
30
31
31
let typing_env = body. typing_env ( tcx) ;
32
32
let ssa = SsaLocals :: new ( tcx, body, typing_env) ;
33
+ debug ! ( borrowed_locals = ?ssa. borrowed_locals( ) ) ;
34
+ debug ! ( copy_classes = ?ssa. copy_classes( ) ) ;
33
35
34
36
let fully_moved = fully_moved_locals ( & ssa, body) ;
35
37
debug ! ( ?fully_moved) ;
@@ -43,14 +45,8 @@ impl<'tcx> crate::MirPass<'tcx> for CopyProp {
43
45
44
46
let any_replacement = ssa. copy_classes ( ) . iter_enumerated ( ) . any ( |( l, & h) | l != h) ;
45
47
46
- Replacer {
47
- tcx,
48
- copy_classes : ssa. copy_classes ( ) ,
49
- fully_moved,
50
- borrowed_locals : ssa. borrowed_locals ( ) ,
51
- storage_to_remove,
52
- }
53
- . visit_body_preserves_cfg ( body) ;
48
+ Replacer { tcx, copy_classes : ssa. copy_classes ( ) , fully_moved, storage_to_remove }
49
+ . visit_body_preserves_cfg ( body) ;
54
50
55
51
if any_replacement {
56
52
crate :: simplify:: remove_unused_definitions ( body) ;
@@ -102,7 +98,6 @@ struct Replacer<'a, 'tcx> {
102
98
tcx : TyCtxt < ' tcx > ,
103
99
fully_moved : DenseBitSet < Local > ,
104
100
storage_to_remove : DenseBitSet < Local > ,
105
- borrowed_locals : & ' a DenseBitSet < Local > ,
106
101
copy_classes : & ' a IndexSlice < Local , Local > ,
107
102
}
108
103
@@ -111,34 +106,27 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
111
106
self . tcx
112
107
}
113
108
109
+ #[ tracing:: instrument( level = "trace" , skip( self ) ) ]
114
110
fn visit_local ( & mut self , local : & mut Local , ctxt : PlaceContext , _: Location ) {
115
111
let new_local = self . copy_classes [ * local] ;
116
- // We must not unify two locals that are borrowed. But this is fine if one is borrowed and
117
- // the other is not. We chose to check the original local, and not the target. That way, if
118
- // the original local is borrowed and the target is not, we do not pessimize the whole class.
119
- if self . borrowed_locals . contains ( * local) {
120
- return ;
121
- }
122
112
match ctxt {
123
113
// Do not modify the local in storage statements.
124
114
PlaceContext :: NonUse ( NonUseContext :: StorageLive | NonUseContext :: StorageDead ) => { }
125
- // The local should have been marked as non-SSA.
126
- PlaceContext :: MutatingUse ( _) => assert_eq ! ( * local, new_local) ,
127
115
// We access the value.
128
116
_ => * local = new_local,
129
117
}
130
118
}
131
119
132
- fn visit_place ( & mut self , place : & mut Place < ' tcx > , _: PlaceContext , loc : Location ) {
120
+ #[ tracing:: instrument( level = "trace" , skip( self ) ) ]
121
+ fn visit_place ( & mut self , place : & mut Place < ' tcx > , ctxt : PlaceContext , loc : Location ) {
133
122
if let Some ( new_projection) = self . process_projection ( place. projection , loc) {
134
123
place. projection = self . tcx ( ) . mk_place_elems ( & new_projection) ;
135
124
}
136
125
137
- // Any non-mutating use context is ok.
138
- let ctxt = PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Copy ) ;
139
126
self . visit_local ( & mut place. local , ctxt, loc)
140
127
}
141
128
129
+ #[ tracing:: instrument( level = "trace" , skip( self ) ) ]
142
130
fn visit_operand ( & mut self , operand : & mut Operand < ' tcx > , loc : Location ) {
143
131
if let Operand :: Move ( place) = * operand
144
132
// A move out of a projection of a copy is equivalent to a copy of the original
@@ -151,6 +139,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
151
139
self . super_operand ( operand, loc) ;
152
140
}
153
141
142
+ #[ tracing:: instrument( level = "trace" , skip( self ) ) ]
154
143
fn visit_statement ( & mut self , stmt : & mut Statement < ' tcx > , loc : Location ) {
155
144
// When removing storage statements, we need to remove both (#107511).
156
145
if let StatementKind :: StorageLive ( l) | StatementKind :: StorageDead ( l) = stmt. kind
0 commit comments