(&mut self)
| 283 | } |
| 284 | |
| 285 | fn compute_best_values(&mut self) { |
| 286 | let sorted_values = self.topo_sorted_values(); |
| 287 | |
| 288 | let best = &mut self.value_to_best_value; |
| 289 | |
| 290 | // We can't make random decisions inside the fixpoint loop below because |
| 291 | // that could cause values to change on every iteration of the loop, |
| 292 | // which would make the loop never terminate. So in chaos testing |
| 293 | // mode we need a form of making suboptimal decisions that is fully |
| 294 | // deterministic. We choose to simply make the worst decision we know |
| 295 | // how to do instead of the best. |
| 296 | let use_worst = self.ctrl_plane.get_decision(); |
| 297 | |
| 298 | trace!( |
| 299 | "Computing the {} values for each eclass", |
| 300 | if use_worst { |
| 301 | "worst (chaos mode)" |
| 302 | } else { |
| 303 | "best" |
| 304 | } |
| 305 | ); |
| 306 | |
| 307 | // Because the values are topologically sorted, we know that we will see |
| 308 | // defs before uses, so an instruction's operands' costs will already be |
| 309 | // computed by the time we are computing the cost for the current value |
| 310 | // and its instruction. |
| 311 | for value in sorted_values.iter().copied() { |
| 312 | let def = self.func.dfg.value_def(value); |
| 313 | trace!("computing best for value {:?} def {:?}", value, def); |
| 314 | |
| 315 | match def { |
| 316 | // Pick the best of the two options based on min-cost. This |
| 317 | // works because each element of `best` is a `(cost, value)` |
| 318 | // tuple; `cost` comes first so the natural comparison works |
| 319 | // based on cost, and breaks ties based on value number. |
| 320 | ValueDef::Union(x, y) => { |
| 321 | debug_assert!(!best[x].1.is_reserved_value()); |
| 322 | debug_assert!(!best[y].1.is_reserved_value()); |
| 323 | best[value] = if use_worst { |
| 324 | core::cmp::max(best[x], best[y]) |
| 325 | } else { |
| 326 | core::cmp::min(best[x], best[y]) |
| 327 | }; |
| 328 | trace!( |
| 329 | " -> best of union({:?}, {:?}) = {:?}", |
| 330 | best[x], best[y], best[value] |
| 331 | ); |
| 332 | } |
| 333 | |
| 334 | ValueDef::Param(_, _) => { |
| 335 | best[value] = BestEntry(Cost::zero(), value); |
| 336 | } |
| 337 | |
| 338 | // If the Inst is inserted into the layout (which is, |
| 339 | // at this point, only the side-effecting skeleton), |
| 340 | // then it must be computed and thus we give it zero |
| 341 | // cost. |
| 342 | ValueDef::Result(inst, _) => { |
no test coverage detected