|
1 | 1 | use std::ops::RangeInclusive;
|
2 | 2 |
|
3 |
| -use rustc_middle::mir::{ |
4 |
| - self, BasicBlock, CallReturnPlaces, Location, SwitchTargets, TerminatorEdges, |
5 |
| -}; |
| 3 | +use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges}; |
6 | 4 |
|
7 | 5 | use super::visitor::ResultsVisitor;
|
8 | 6 | use super::{Analysis, Effect, EffectIndex, Results, SwitchIntTarget};
|
@@ -115,18 +113,18 @@ impl Direction for Backward {
|
115 | 113 | }
|
116 | 114 |
|
117 | 115 | mir::TerminatorKind::SwitchInt { targets: _, ref discr } => {
|
118 |
| - let mut applier = BackwardSwitchIntEdgeEffectsApplier { |
119 |
| - body, |
120 |
| - pred, |
121 |
| - exit_state, |
122 |
| - block, |
123 |
| - propagate: &mut propagate, |
124 |
| - effects_applied: false, |
125 |
| - }; |
126 |
| - |
127 |
| - analysis.apply_switch_int_edge_effects(pred, discr, &mut applier); |
128 |
| - |
129 |
| - if !applier.effects_applied { |
| 116 | + if let Some(mut data) = analysis.get_switch_int_data(block, discr) { |
| 117 | + let values = &body.basic_blocks.switch_sources()[&(block, pred)]; |
| 118 | + let targets = |
| 119 | + values.iter().map(|&value| SwitchIntTarget { value, target: block }); |
| 120 | + |
| 121 | + let mut tmp = None; |
| 122 | + for target in targets { |
| 123 | + let tmp = opt_clone_from_or_clone(&mut tmp, exit_state); |
| 124 | + analysis.apply_switch_int_edge_effect(&mut data, tmp, target); |
| 125 | + propagate(pred, tmp); |
| 126 | + } |
| 127 | + } else { |
130 | 128 | propagate(pred, exit_state)
|
131 | 129 | }
|
132 | 130 | }
|
@@ -245,37 +243,6 @@ impl Direction for Backward {
|
245 | 243 | }
|
246 | 244 | }
|
247 | 245 |
|
248 |
| -struct BackwardSwitchIntEdgeEffectsApplier<'mir, 'tcx, D, F> { |
249 |
| - body: &'mir mir::Body<'tcx>, |
250 |
| - pred: BasicBlock, |
251 |
| - exit_state: &'mir mut D, |
252 |
| - block: BasicBlock, |
253 |
| - propagate: &'mir mut F, |
254 |
| - effects_applied: bool, |
255 |
| -} |
256 |
| - |
257 |
| -impl<D, F> super::SwitchIntEdgeEffects<D> for BackwardSwitchIntEdgeEffectsApplier<'_, '_, D, F> |
258 |
| -where |
259 |
| - D: Clone, |
260 |
| - F: FnMut(BasicBlock, &D), |
261 |
| -{ |
262 |
| - fn apply(&mut self, mut apply_edge_effect: impl FnMut(&mut D, SwitchIntTarget)) { |
263 |
| - assert!(!self.effects_applied); |
264 |
| - |
265 |
| - let values = &self.body.basic_blocks.switch_sources()[&(self.block, self.pred)]; |
266 |
| - let targets = values.iter().map(|&value| SwitchIntTarget { value, target: self.block }); |
267 |
| - |
268 |
| - let mut tmp = None; |
269 |
| - for target in targets { |
270 |
| - let tmp = opt_clone_from_or_clone(&mut tmp, self.exit_state); |
271 |
| - apply_edge_effect(tmp, target); |
272 |
| - (self.propagate)(self.pred, tmp); |
273 |
| - } |
274 |
| - |
275 |
| - self.effects_applied = true; |
276 |
| - } |
277 |
| -} |
278 |
| - |
279 | 246 | /// Dataflow that runs from the entry of a block (the first statement), to its exit (terminator).
|
280 | 247 | pub struct Forward;
|
281 | 248 |
|
@@ -324,23 +291,27 @@ impl Direction for Forward {
|
324 | 291 | }
|
325 | 292 | }
|
326 | 293 | TerminatorEdges::SwitchInt { targets, discr } => {
|
327 |
| - let mut applier = ForwardSwitchIntEdgeEffectsApplier { |
328 |
| - exit_state, |
329 |
| - targets, |
330 |
| - propagate, |
331 |
| - effects_applied: false, |
332 |
| - }; |
333 |
| - |
334 |
| - analysis.apply_switch_int_edge_effects(block, discr, &mut applier); |
335 |
| - |
336 |
| - let ForwardSwitchIntEdgeEffectsApplier { |
337 |
| - exit_state, |
338 |
| - mut propagate, |
339 |
| - effects_applied, |
340 |
| - .. |
341 |
| - } = applier; |
342 |
| - |
343 |
| - if !effects_applied { |
| 294 | + if let Some(mut data) = analysis.get_switch_int_data(block, discr) { |
| 295 | + let mut tmp = None; |
| 296 | + for (value, target) in targets.iter() { |
| 297 | + let tmp = opt_clone_from_or_clone(&mut tmp, exit_state); |
| 298 | + analysis.apply_switch_int_edge_effect(&mut data, tmp, SwitchIntTarget { |
| 299 | + value: Some(value), |
| 300 | + target, |
| 301 | + }); |
| 302 | + propagate(target, tmp); |
| 303 | + } |
| 304 | + |
| 305 | + // Once we get to the final, "otherwise" branch, there is no need to preserve |
| 306 | + // `exit_state`, so pass it directly to `apply_switch_int_edge_effect` to save |
| 307 | + // a clone of the dataflow state. |
| 308 | + let otherwise = targets.otherwise(); |
| 309 | + analysis.apply_switch_int_edge_effect(&mut data, exit_state, SwitchIntTarget { |
| 310 | + value: None, |
| 311 | + target: otherwise, |
| 312 | + }); |
| 313 | + propagate(otherwise, exit_state); |
| 314 | + } else { |
344 | 315 | for target in targets.all_targets() {
|
345 | 316 | propagate(*target, exit_state);
|
346 | 317 | }
|
@@ -455,39 +426,6 @@ impl Direction for Forward {
|
455 | 426 | }
|
456 | 427 | }
|
457 | 428 |
|
458 |
| -struct ForwardSwitchIntEdgeEffectsApplier<'mir, D, F> { |
459 |
| - exit_state: &'mir mut D, |
460 |
| - targets: &'mir SwitchTargets, |
461 |
| - propagate: F, |
462 |
| - |
463 |
| - effects_applied: bool, |
464 |
| -} |
465 |
| - |
466 |
| -impl<D, F> super::SwitchIntEdgeEffects<D> for ForwardSwitchIntEdgeEffectsApplier<'_, D, F> |
467 |
| -where |
468 |
| - D: Clone, |
469 |
| - F: FnMut(BasicBlock, &D), |
470 |
| -{ |
471 |
| - fn apply(&mut self, mut apply_edge_effect: impl FnMut(&mut D, SwitchIntTarget)) { |
472 |
| - assert!(!self.effects_applied); |
473 |
| - |
474 |
| - let mut tmp = None; |
475 |
| - for (value, target) in self.targets.iter() { |
476 |
| - let tmp = opt_clone_from_or_clone(&mut tmp, self.exit_state); |
477 |
| - apply_edge_effect(tmp, SwitchIntTarget { value: Some(value), target }); |
478 |
| - (self.propagate)(target, tmp); |
479 |
| - } |
480 |
| - |
481 |
| - // Once we get to the final, "otherwise" branch, there is no need to preserve `exit_state`, |
482 |
| - // so pass it directly to `apply_edge_effect` to save a clone of the dataflow state. |
483 |
| - let otherwise = self.targets.otherwise(); |
484 |
| - apply_edge_effect(self.exit_state, SwitchIntTarget { value: None, target: otherwise }); |
485 |
| - (self.propagate)(otherwise, self.exit_state); |
486 |
| - |
487 |
| - self.effects_applied = true; |
488 |
| - } |
489 |
| -} |
490 |
| - |
491 | 429 | /// An analogue of `Option::get_or_insert_with` that stores a clone of `val` into `opt`, but uses
|
492 | 430 | /// the more efficient `clone_from` if `opt` was `Some`.
|
493 | 431 | ///
|
|
0 commit comments