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: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24998>
This commit is contained in:
Faith Ekstrand
2023-09-01 16:59:06 -05:00
committed by Marge Bot
parent ea0ae395a9
commit a0bf406057
+34 -3
View File
@@ -508,11 +508,42 @@ fn spill_values<S: Spill>(
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);