|
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