@@ -205,15 +205,54 @@ impl DefUse {
205
205
/// All of the caveats of `MaybeLiveLocals` apply.
206
206
pub struct MaybeTransitiveLiveLocals < ' a > {
207
207
always_live : & ' a DenseBitSet < Local > ,
208
+ debuginfo_locals : & ' a DenseBitSet < Local > ,
208
209
}
209
210
210
211
impl < ' a > MaybeTransitiveLiveLocals < ' a > {
211
212
/// The `always_alive` set is the set of locals to which all stores should unconditionally be
212
213
/// considered live.
213
214
///
214
215
/// This should include at least all locals that are ever borrowed.
215
- pub fn new ( always_live : & ' a DenseBitSet < Local > ) -> Self {
216
- MaybeTransitiveLiveLocals { always_live }
216
+ pub fn new (
217
+ always_live : & ' a DenseBitSet < Local > ,
218
+ debuginfo_locals : & ' a DenseBitSet < Local > ,
219
+ ) -> Self {
220
+ MaybeTransitiveLiveLocals { always_live, debuginfo_locals }
221
+ }
222
+
223
+ pub fn can_be_removed_if_dead < ' tcx > (
224
+ stmt_kind : & StatementKind < ' tcx > ,
225
+ always_live : & DenseBitSet < Local > ,
226
+ debuginfo_locals : & ' a DenseBitSet < Local > ,
227
+ ) -> Option < Place < ' tcx > > {
228
+ // Compute the place that we are storing to, if any
229
+ let destination = match stmt_kind {
230
+ StatementKind :: Assign ( box ( place, rvalue) ) => ( rvalue. is_safe_to_remove ( )
231
+ && ( !debuginfo_locals. contains ( place. local )
232
+ || ( place. as_local ( ) . is_some ( ) && matches ! ( rvalue, mir:: Rvalue :: Ref ( ..) ) ) ) )
233
+ . then_some ( * place) ,
234
+ StatementKind :: SetDiscriminant { place, .. } | StatementKind :: Deinit ( place) => {
235
+ ( !debuginfo_locals. contains ( place. local ) ) . then_some ( * * place)
236
+ }
237
+ StatementKind :: FakeRead ( _)
238
+ | StatementKind :: StorageLive ( _)
239
+ | StatementKind :: StorageDead ( _)
240
+ | StatementKind :: Retag ( ..)
241
+ | StatementKind :: AscribeUserType ( ..)
242
+ | StatementKind :: PlaceMention ( ..)
243
+ | StatementKind :: Coverage ( ..)
244
+ | StatementKind :: Intrinsic ( ..)
245
+ | StatementKind :: ConstEvalCounter
246
+ | StatementKind :: BackwardIncompatibleDropHint { .. }
247
+ | StatementKind :: Nop => None ,
248
+ } ;
249
+ if let Some ( destination) = destination
250
+ && !destination. is_indirect ( )
251
+ && !always_live. contains ( destination. local )
252
+ {
253
+ return Some ( destination) ;
254
+ }
255
+ None
217
256
}
218
257
}
219
258
@@ -238,32 +277,12 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
238
277
statement : & mir:: Statement < ' tcx > ,
239
278
location : Location ,
240
279
) {
241
- // Compute the place that we are storing to, if any
242
- let destination = match & statement. kind {
243
- StatementKind :: Assign ( assign) => assign. 1 . is_safe_to_remove ( ) . then_some ( assign. 0 ) ,
244
- StatementKind :: SetDiscriminant { place, .. } | StatementKind :: Deinit ( place) => {
245
- Some ( * * place)
246
- }
247
- StatementKind :: FakeRead ( _)
248
- | StatementKind :: StorageLive ( _)
249
- | StatementKind :: StorageDead ( _)
250
- | StatementKind :: Retag ( ..)
251
- | StatementKind :: AscribeUserType ( ..)
252
- | StatementKind :: PlaceMention ( ..)
253
- | StatementKind :: Coverage ( ..)
254
- | StatementKind :: Intrinsic ( ..)
255
- | StatementKind :: ConstEvalCounter
256
- | StatementKind :: BackwardIncompatibleDropHint { .. }
257
- | StatementKind :: Nop => None ,
258
- } ;
259
- if let Some ( destination) = destination {
260
- if !destination. is_indirect ( )
261
- && !state. contains ( destination. local )
262
- && !self . always_live . contains ( destination. local )
263
- {
264
- // This store is dead
265
- return ;
266
- }
280
+ if let Some ( destination) =
281
+ Self :: can_be_removed_if_dead ( & statement. kind , & self . always_live , & self . debuginfo_locals )
282
+ && !state. contains ( destination. local )
283
+ {
284
+ // This store is dead
285
+ return ;
267
286
}
268
287
TransferFunction ( state) . visit_statement ( statement, location) ;
269
288
}
0 commit comments