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:
committed by
Marge Bot
parent
ea0ae395a9
commit
a0bf406057
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user