|
30 | 30 | //! Applying the optimisation can create a lot of new MIR, so we bound the instruction |
31 | 31 | //! cost by `MAX_COST`. |
32 | 32 |
|
| 33 | +use std::cell::OnceCell; |
| 34 | + |
33 | 35 | use rustc_arena::DroplessArena; |
34 | 36 | use rustc_const_eval::const_eval::DummyMachine; |
35 | 37 | use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, Projectable}; |
@@ -82,15 +84,7 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading { |
82 | 84 | loop_headers: loop_headers(body), |
83 | 85 | entry_states: IndexVec::from_elem(ConditionSet::BOTTOM, &body.basic_blocks), |
84 | 86 | opportunities: Vec::new(), |
85 | | - costs: body |
86 | | - .basic_blocks |
87 | | - .iter_enumerated() |
88 | | - .map(|(bb, bbdata)| { |
89 | | - let mut cost = CostChecker::new(tcx, typing_env, None, body); |
90 | | - cost.visit_basic_block_data(bb, bbdata); |
91 | | - cost.cost() |
92 | | - }) |
93 | | - .collect(), |
| 87 | + costs: IndexVec::from_elem(OnceCell::new(), &body.basic_blocks), |
94 | 88 | }; |
95 | 89 |
|
96 | 90 | for (bb, bbdata) in traversal::postorder(body) { |
@@ -166,7 +160,7 @@ struct TOFinder<'a, 'tcx> { |
166 | 160 | arena: &'a DroplessArena, |
167 | 161 | opportunities: Vec<ThreadingOpportunity>, |
168 | 162 | /// Pre-computed cost of duplicating each block. |
169 | | - costs: IndexVec<BasicBlock, usize>, |
| 163 | + costs: IndexVec<BasicBlock, OnceCell<usize>>, |
170 | 164 | } |
171 | 165 |
|
172 | 166 | /// Singly-linked list to represent chains of blocks. This is cheap to copy, and is converted to |
@@ -334,13 +328,22 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { |
334 | 328 | cond.chain = BBChain::cons(self.arena, bb, cond.chain); |
335 | 329 | // Remove conditions for which the duplication cost is too high. |
336 | 330 | // This is required to keep the size of the `ConditionSet` tractable. |
337 | | - let cost = cond.cost + self.costs[head]; |
| 331 | + let cost = cond.cost + self.cost(head); |
338 | 332 | cond.cost = cost; |
339 | 333 | cost <= MAX_COST |
340 | 334 | }); |
341 | 335 | ConditionSet(state) |
342 | 336 | } |
343 | 337 |
|
| 338 | + fn cost(&self, bb: BasicBlock) -> usize { |
| 339 | + *self.costs[bb].get_or_init(|| { |
| 340 | + let bbdata = &self.body[bb]; |
| 341 | + let mut cost = CostChecker::new(self.tcx, self.typing_env, None, self.body); |
| 342 | + cost.visit_basic_block_data(bb, bbdata); |
| 343 | + cost.cost() |
| 344 | + }) |
| 345 | + } |
| 346 | + |
344 | 347 | /// Remove all conditions in the state that alias given place. |
345 | 348 | fn flood_state( |
346 | 349 | &self, |
|
0 commit comments