From a0bf406057805f2e67e33a15471aff99561e8dd8 Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Fri, 1 Sep 2023 16:59:06 -0500 Subject: [PATCH] nak/spill: Tweak the construction of S sets Instead of just taking live-in \ W, consider anything previously spilled to be spilled. This lets us avoid a bunch of redundant spills because we now allow spills to persist across blocks even if the value is in W. In the loop header case, however, we still need to add in live-in \ W or else we can end up in cases where a value is neither in W nor S. Part-of: --- src/nouveau/compiler/nak_spill_values.rs | 37 ++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/src/nouveau/compiler/nak_spill_values.rs b/src/nouveau/compiler/nak_spill_values.rs index 5ce2909dadf..f9b364200e2 100644 --- a/src/nouveau/compiler/nak_spill_values.rs +++ b/src/nouveau/compiler/nak_spill_values.rs @@ -508,11 +508,42 @@ fn spill_values( p_s.iter().filter(|ssa| bl.is_live_in(ssa)).cloned(), ) } else { - HashSet::from_iter( - bl.iter_live_in().filter(|ssa| !w.contains(ssa)).cloned(), - ) + let mut s = HashSet::new(); + for p_idx in &preds { + if *p_idx >= b_idx { + continue; + } + + // We diverge a bit from Braun and Hack here. They assume that + // S is is a subset of W which is clearly bogus. Instead, we + // take the union of all forward edge predecessor S_out and + // intersect with live-in for the current block. + for ssa in ssa_state_out[*p_idx].s.iter() { + if bl.is_live_in(ssa) { + s.insert(*ssa); + } + } + } + + // The loop header heuristic sometimes drops stuff from W that has + // never been spilled so we need to make sure everything live-in + // which isn't in W is included in the spill set so that it gets + // properly spilled when we spill across CF edges. + if blocks.is_loop_header(b_idx) { + for ssa in bl.iter_live_in() { + if !w.contains(ssa) { + s.insert(*ssa); + } + } + } + + s }; + for ssa in bl.iter_live_in() { + debug_assert!(w.contains(ssa) || s.contains(ssa)); + } + let mut b = SSAState { w: w, s: s }; assert!(ssa_state_in.len() == b_idx);