Tracks a usage of `bit` as part of the expression at `dst`.
(&mut self, dst: OutputExprId, has_side_effects: bool, bit: Bit)
| 312 | |
| 313 | /// Tracks a usage of `bit` as part of the expression at `dst`. |
| 314 | fn add_bit_use(&mut self, dst: OutputExprId, has_side_effects: bool, bit: Bit) { |
| 315 | let Bit::Expr(expr) = bit |
| 316 | else { |
| 317 | return; |
| 318 | }; |
| 319 | |
| 320 | if self.loads.contains_key(&expr.id) { |
| 321 | // Handle direct usages of loads. |
| 322 | let for_expr = self.uses.entry(dst).or_default(); |
| 323 | let for_load = for_expr.entry(expr.id).or_default(); |
| 324 | for_load.update(expr.offset, has_side_effects); |
| 325 | } |
| 326 | else if let Some(usage) = self.uses.get(&expr.id) { |
| 327 | // Handle indirect usages of loads. |
| 328 | let prev_usage = usage.clone(); |
| 329 | let for_expr = self.uses.entry(dst).or_default(); |
| 330 | for (load_expr_id, prev_use) in prev_usage { |
| 331 | let for_load = for_expr.entry(load_expr_id).or_default(); |
| 332 | for_load.has_side_effect |= has_side_effects; |
| 333 | // Since this usage was not constant propagated back to the original load, we |
| 334 | // conservatively assume that this bit may depend on any of the bits loaded in the |
| 335 | // previous use. |
| 336 | for_load.max_bit = for_load.max_bit.max(prev_use.max_bit); |
| 337 | for_load.min_bit = for_load.min_bit.min(prev_use.min_bit); |
| 338 | } |
| 339 | } |
| 340 | } |
| 341 | |
| 342 | /// Returns the number of bits we need from `load` to compute `var`. |
| 343 | fn get_used_bits(&self, value: const_eval::Value, load: OutputExprId) -> (u8, u8) { |