|
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}; |
@@ -81,15 +83,7 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading { |
81 | 83 | loop_headers: loop_headers(body), |
82 | 84 | entry_states: IndexVec::from_elem(ConditionSet::BOTTOM, &body.basic_blocks), |
83 | 85 | opportunities: Vec::new(), |
84 | | - costs: body |
85 | | - .basic_blocks |
86 | | - .iter_enumerated() |
87 | | - .map(|(bb, bbdata)| { |
88 | | - let mut cost = CostChecker::new(tcx, typing_env, None, body); |
89 | | - cost.visit_basic_block_data(bb, bbdata); |
90 | | - cost.cost() |
91 | | - }) |
92 | | - .collect(), |
| 86 | + costs: IndexVec::from_elem(OnceCell::new(), &body.basic_blocks), |
93 | 87 | }; |
94 | 88 |
|
95 | 89 | for (bb, bbdata) in traversal::postorder(body) { |
@@ -165,7 +159,7 @@ struct TOFinder<'a, 'tcx> { |
165 | 159 | arena: &'a DroplessArena, |
166 | 160 | opportunities: Vec<ThreadingOpportunity>, |
167 | 161 | /// Pre-computed cost of duplicating each block. |
168 | | - costs: IndexVec<BasicBlock, usize>, |
| 162 | + costs: IndexVec<BasicBlock, OnceCell<usize>>, |
169 | 163 | } |
170 | 164 |
|
171 | 165 | /// Singly-linked list to represent chains of blocks. This is cheap to copy, and is converted to |
@@ -333,13 +327,22 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { |
333 | 327 | cond.chain = BBChain::cons(self.arena, bb, cond.chain); |
334 | 328 | // Remove conditions for which the duplication cost is too high. |
335 | 329 | // This is required to keep the size of the `ConditionSet` tractable. |
336 | | - let cost = cond.cost + self.costs[head]; |
| 330 | + let cost = cond.cost + self.cost(head); |
337 | 331 | cond.cost = cost; |
338 | 332 | cost <= MAX_COST |
339 | 333 | }); |
340 | 334 | ConditionSet(state) |
341 | 335 | } |
342 | 336 |
|
| 337 | + fn cost(&self, bb: BasicBlock) -> usize { |
| 338 | + *self.costs[bb].get_or_init(|| { |
| 339 | + let bbdata = &self.body[bb]; |
| 340 | + let mut cost = CostChecker::new(self.tcx, self.typing_env, None, self.body); |
| 341 | + cost.visit_basic_block_data(bb, bbdata); |
| 342 | + cost.cost() |
| 343 | + }) |
| 344 | + } |
| 345 | + |
343 | 346 | /// Remove all conditions in the state that alias given place. |
344 | 347 | fn flood_state( |
345 | 348 | &self, |
|
0 commit comments