@@ -248,6 +248,7 @@ impl Direction for Backward {
248248 ) ;
249249 propagate ( pred, & tmp) ;
250250 }
251+
251252 mir:: TerminatorKind :: InlineAsm {
252253 destination : Some ( dest) , ref operands, ..
253254 } if dest == bb => {
@@ -266,6 +267,23 @@ impl Direction for Backward {
266267 propagate ( pred, & tmp) ;
267268 }
268269
270+ mir:: TerminatorKind :: SwitchInt { targets : _, ref discr, switch_ty : _ } => {
271+ let mut applier = BackwardSwitchIntEdgeEffectsApplier {
272+ pred,
273+ exit_state,
274+ values : & body. switch_sources ( ) [ bb] [ pred] ,
275+ bb,
276+ propagate : & mut propagate,
277+ effects_applied : false ,
278+ } ;
279+
280+ analysis. apply_switch_int_edge_effects ( pred, discr, & mut applier) ;
281+
282+ if !applier. effects_applied {
283+ propagate ( pred, exit_state)
284+ }
285+ }
286+
269287 // Ignore dead unwinds.
270288 mir:: TerminatorKind :: Call { cleanup : Some ( unwind) , .. }
271289 | mir:: TerminatorKind :: Assert { cleanup : Some ( unwind) , .. }
@@ -286,6 +304,37 @@ impl Direction for Backward {
286304 }
287305}
288306
307+ struct BackwardSwitchIntEdgeEffectsApplier < ' a , D , F > {
308+ pred : BasicBlock ,
309+ exit_state : & ' a mut D ,
310+ values : & ' a [ Option < u128 > ] ,
311+ bb : BasicBlock ,
312+ propagate : & ' a mut F ,
313+
314+ effects_applied : bool ,
315+ }
316+
317+ impl < D , F > super :: SwitchIntEdgeEffects < D > for BackwardSwitchIntEdgeEffectsApplier < ' _ , D , F >
318+ where
319+ D : Clone ,
320+ F : FnMut ( BasicBlock , & D ) ,
321+ {
322+ fn apply ( & mut self , mut apply_edge_effect : impl FnMut ( & mut D , SwitchIntTarget ) ) {
323+ assert ! ( !self . effects_applied) ;
324+
325+ let targets = self . values . iter ( ) . map ( |& value| SwitchIntTarget { value, target : self . bb } ) ;
326+
327+ let mut tmp = None ;
328+ for target in targets {
329+ let tmp = opt_clone_from_or_clone ( & mut tmp, self . exit_state ) ;
330+ apply_edge_effect ( tmp, target) ;
331+ ( self . propagate ) ( self . pred , tmp) ;
332+ }
333+
334+ self . effects_applied = true ;
335+ }
336+ }
337+
289338/// Dataflow that runs from the entry of a block (the first statement), to its exit (terminator).
290339pub struct Forward ;
291340
@@ -528,7 +577,7 @@ impl Direction for Forward {
528577 }
529578
530579 SwitchInt { ref targets, ref discr, switch_ty : _ } => {
531- let mut applier = SwitchIntEdgeEffectApplier {
580+ let mut applier = ForwardSwitchIntEdgeEffectsApplier {
532581 exit_state,
533582 targets,
534583 propagate,
@@ -537,8 +586,11 @@ impl Direction for Forward {
537586
538587 analysis. apply_switch_int_edge_effects ( bb, discr, & mut applier) ;
539588
540- let SwitchIntEdgeEffectApplier {
541- exit_state, mut propagate, effects_applied, ..
589+ let ForwardSwitchIntEdgeEffectsApplier {
590+ exit_state,
591+ mut propagate,
592+ effects_applied,
593+ ..
542594 } = applier;
543595
544596 if !effects_applied {
@@ -551,15 +603,15 @@ impl Direction for Forward {
551603 }
552604}
553605
554- struct SwitchIntEdgeEffectApplier < ' a , D , F > {
606+ struct ForwardSwitchIntEdgeEffectsApplier < ' a , D , F > {
555607 exit_state : & ' a mut D ,
556608 targets : & ' a SwitchTargets ,
557609 propagate : F ,
558610
559611 effects_applied : bool ,
560612}
561613
562- impl < D , F > super :: SwitchIntEdgeEffects < D > for SwitchIntEdgeEffectApplier < ' _ , D , F >
614+ impl < D , F > super :: SwitchIntEdgeEffects < D > for ForwardSwitchIntEdgeEffectsApplier < ' _ , D , F >
563615where
564616 D : Clone ,
565617 F : FnMut ( BasicBlock , & D ) ,
0 commit comments