Find the block where a pure instruction first becomes available, defined as the block that is closest to the root where all of its arguments are available. In the unusual case where a pure instruction has no arguments (e.g. get_return_address), we can place it anywhere, so it is available in the entry block. This function does not compute available blocks recursively. All of the instruction's arg
(&self, inst: Inst)
| 295 | /// All of the instruction's arguments must have had their available |
| 296 | /// blocks assigned already. |
| 297 | fn get_available_block(&self, inst: Inst) -> Block { |
| 298 | // Side-effecting instructions have different rules for where |
| 299 | // they become available, so this function does not apply. |
| 300 | debug_assert!(is_pure_for_egraph(self.func, inst)); |
| 301 | |
| 302 | // Note that the def-point of all arguments to an instruction |
| 303 | // in SSA lie on a line of direct ancestors in the domtree, and |
| 304 | // so do their available-blocks. This means that for any pair of |
| 305 | // arguments, their available blocks are either the same or one |
| 306 | // strictly dominates the other. We just need to find any argument |
| 307 | // whose available block is deepest in the domtree. |
| 308 | self.func.dfg.insts[inst] |
| 309 | .arguments(&self.func.dfg.value_lists) |
| 310 | .iter() |
| 311 | .map(|&v| { |
| 312 | let block = self.available_block[v]; |
| 313 | debug_assert!(!block.is_reserved_value()); |
| 314 | block |
| 315 | }) |
| 316 | .max_by(|&x, &y| { |
| 317 | if self.domtree.block_dominates(x, y) { |
| 318 | Ordering::Less |
| 319 | } else { |
| 320 | debug_assert!(self.domtree.block_dominates(y, x)); |
| 321 | Ordering::Greater |
| 322 | } |
| 323 | }) |
| 324 | .unwrap_or(self.func.layout.entry_block().unwrap()) |
| 325 | } |
| 326 | |
| 327 | fn depth_of_block_in_gvn_map(&self, block: Block) -> usize { |
| 328 | log::trace!( |
no test coverage detected