|
1 | 1 | use super::*;
|
| 2 | +use crate::mir::visit::Visitor; |
2 | 3 |
|
3 | 4 | /// Preorder traversal of a graph.
|
4 | 5 | ///
|
@@ -232,6 +233,90 @@ pub fn postorder<'a, 'tcx>(
|
232 | 233 | reverse_postorder(body).rev()
|
233 | 234 | }
|
234 | 235 |
|
| 236 | +struct UsedLocals(BitSet<Local>); |
| 237 | + |
| 238 | +impl<'tcx> Visitor<'tcx> for UsedLocals { |
| 239 | + fn visit_local( |
| 240 | + &mut self, |
| 241 | + local: Local, |
| 242 | + _ctx: crate::mir::visit::PlaceContext, |
| 243 | + _location: Location, |
| 244 | + ) { |
| 245 | + self.0.insert(local); |
| 246 | + } |
| 247 | +} |
| 248 | + |
| 249 | +struct MonoReachablePostorder<'a, 'tcx> { |
| 250 | + basic_blocks: &'a IndexSlice<BasicBlock, BasicBlockData<'tcx>>, |
| 251 | + visited: BitSet<BasicBlock>, |
| 252 | + visit_stack: Vec<(BasicBlock, Successors<'a>)>, |
| 253 | + locals: UsedLocals, |
| 254 | + tcx: TyCtxt<'tcx>, |
| 255 | + instance: Instance<'tcx>, |
| 256 | +} |
| 257 | + |
| 258 | +impl<'a, 'tcx> MonoReachablePostorder<'a, 'tcx> { |
| 259 | + fn new( |
| 260 | + body: &'a Body<'tcx>, |
| 261 | + tcx: TyCtxt<'tcx>, |
| 262 | + instance: Instance<'tcx>, |
| 263 | + ) -> MonoReachablePostorder<'a, 'tcx> { |
| 264 | + let basic_blocks = &body.basic_blocks; |
| 265 | + let mut po = MonoReachablePostorder { |
| 266 | + basic_blocks, |
| 267 | + visited: BitSet::new_empty(basic_blocks.len()), |
| 268 | + visit_stack: Vec::new(), |
| 269 | + locals: UsedLocals(BitSet::new_empty(body.local_decls.len())), |
| 270 | + tcx, |
| 271 | + instance, |
| 272 | + }; |
| 273 | + |
| 274 | + po.visit(START_BLOCK); |
| 275 | + po.traverse_successor(); |
| 276 | + po |
| 277 | + } |
| 278 | + |
| 279 | + fn visit(&mut self, bb: BasicBlock) { |
| 280 | + if !self.visited.insert(bb) { |
| 281 | + return; |
| 282 | + } |
| 283 | + let data = &self.basic_blocks[bb]; |
| 284 | + self.locals.visit_basic_block_data(bb, data); |
| 285 | + let successors = data.mono_successors(self.tcx, self.instance); |
| 286 | + self.visit_stack.push((bb, successors)); |
| 287 | + } |
| 288 | + |
| 289 | + fn traverse_successor(&mut self) { |
| 290 | + while let Some(bb) = self.visit_stack.last_mut().and_then(|(_, iter)| iter.next_back()) { |
| 291 | + self.visit(bb); |
| 292 | + } |
| 293 | + } |
| 294 | +} |
| 295 | + |
| 296 | +impl<'tcx> Iterator for MonoReachablePostorder<'_, 'tcx> { |
| 297 | + type Item = BasicBlock; |
| 298 | + |
| 299 | + fn next(&mut self) -> Option<BasicBlock> { |
| 300 | + let (bb, _) = self.visit_stack.pop()?; |
| 301 | + self.traverse_successor(); |
| 302 | + Some(bb) |
| 303 | + } |
| 304 | +} |
| 305 | + |
| 306 | +pub fn mono_reachable_reverse_postorder<'a, 'tcx>( |
| 307 | + body: &'a Body<'tcx>, |
| 308 | + tcx: TyCtxt<'tcx>, |
| 309 | + instance: Instance<'tcx>, |
| 310 | +) -> (Vec<BasicBlock>, BitSet<Local>) { |
| 311 | + let mut iter = MonoReachablePostorder::new(body, tcx, instance); |
| 312 | + let mut items = Vec::with_capacity(body.basic_blocks.len()); |
| 313 | + while let Some(block) = iter.next() { |
| 314 | + items.push(block); |
| 315 | + } |
| 316 | + items.reverse(); |
| 317 | + (items, iter.locals.0) |
| 318 | +} |
| 319 | + |
235 | 320 | /// Returns an iterator over all basic blocks reachable from the `START_BLOCK` in no particular
|
236 | 321 | /// order.
|
237 | 322 | ///
|
@@ -358,14 +443,8 @@ impl<'a, 'tcx> Iterator for MonoReachable<'a, 'tcx> {
|
358 | 443 |
|
359 | 444 | let data = &self.body[idx];
|
360 | 445 |
|
361 |
| - if let Some((bits, targets)) = |
362 |
| - Body::try_const_mono_switchint(self.tcx, self.instance, data) |
363 |
| - { |
364 |
| - let target = targets.target_for_value(bits); |
365 |
| - self.add_work([target]); |
366 |
| - } else { |
367 |
| - self.add_work(data.terminator().successors()); |
368 |
| - } |
| 446 | + let targets = data.mono_successors(self.tcx, self.instance); |
| 447 | + self.add_work(targets); |
369 | 448 |
|
370 | 449 | return Some((idx, data));
|
371 | 450 | }
|
|
0 commit comments