@@ -205,15 +205,54 @@ impl DefUse {
205205/// All of the caveats of `MaybeLiveLocals` apply.
206206pub struct MaybeTransitiveLiveLocals < ' a > {
207207 always_live : & ' a DenseBitSet < Local > ,
208+ debuginfo_locals : & ' a DenseBitSet < Local > ,
208209}
209210
210211impl < ' a > MaybeTransitiveLiveLocals < ' a > {
211212 /// The `always_alive` set is the set of locals to which all stores should unconditionally be
212213 /// considered live.
213214 ///
214215 /// 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
217256 }
218257}
219258
@@ -238,32 +277,12 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
238277 statement : & mir:: Statement < ' tcx > ,
239278 location : Location ,
240279 ) {
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 ;
267286 }
268287 TransferFunction ( state) . visit_statement ( statement, location) ;
269288 }
0 commit comments