mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-29 01:30:08 +01:00
nak: Fix repair_ssa() for back-edges
In the presence of nested loops, there is no guarantee that we can handle back-edges in a single pass. Instead, use a bitset as a worlist and repair until we're out of missing sources. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24998>
This commit is contained in:
parent
5839be3c4d
commit
2ff6a36e2a
1 changed files with 31 additions and 8 deletions
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright © 2023 Collabora, Ltd.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use crate::bitset::BitSet;
|
||||
use crate::nak_ir::*;
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
|
@ -24,6 +25,7 @@ fn get_ssa_or_phi(
|
|||
ssa_alloc: &mut SSAValueAllocator,
|
||||
phi_alloc: &mut PhiAllocator,
|
||||
blocks: &[DefTrackerBlock],
|
||||
needs_src: &mut BitSet,
|
||||
b_idx: usize,
|
||||
ssa: SSAValue,
|
||||
) -> SSAValue {
|
||||
|
|
@ -41,8 +43,9 @@ fn get_ssa_or_phi(
|
|||
// it later if it's not needed
|
||||
all_same = false;
|
||||
} else {
|
||||
let p_ssa =
|
||||
get_ssa_or_phi(ssa_alloc, phi_alloc, blocks, *p_idx, ssa);
|
||||
let p_ssa = get_ssa_or_phi(
|
||||
ssa_alloc, phi_alloc, blocks, needs_src, *p_idx, ssa,
|
||||
);
|
||||
if *pred_ssa.get_or_insert(p_ssa) != p_ssa {
|
||||
all_same = false;
|
||||
}
|
||||
|
|
@ -64,6 +67,7 @@ fn get_ssa_or_phi(
|
|||
};
|
||||
for p_idx in &b.pred {
|
||||
if *p_idx >= b_idx {
|
||||
needs_src.insert(*p_idx);
|
||||
continue;
|
||||
}
|
||||
// The earlier recursive call ensured this exists
|
||||
|
|
@ -164,6 +168,7 @@ impl Function {
|
|||
let phi_alloc = &mut self.phi_alloc;
|
||||
|
||||
let mut blocks = Vec::new();
|
||||
let mut needs_src = BitSet::new();
|
||||
for b_idx in 0..cfg.len() {
|
||||
assert!(blocks.len() == b_idx);
|
||||
blocks.push(DefTrackerBlock {
|
||||
|
|
@ -177,7 +182,12 @@ impl Function {
|
|||
instr.for_each_ssa_use_mut(|ssa| {
|
||||
if num_defs.get(ssa).cloned().unwrap_or(0) > 1 {
|
||||
*ssa = get_ssa_or_phi(
|
||||
ssa_alloc, phi_alloc, &blocks, b_idx, *ssa,
|
||||
ssa_alloc,
|
||||
phi_alloc,
|
||||
&blocks,
|
||||
&mut needs_src,
|
||||
b_idx,
|
||||
*ssa,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
@ -190,8 +200,15 @@ impl Function {
|
|||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Populate phi sources for any back-edges
|
||||
loop {
|
||||
let Some(b_idx) = needs_src.next_set(0) else {
|
||||
break;
|
||||
};
|
||||
needs_src.remove(b_idx);
|
||||
|
||||
// Populate phi sources for any back-edges
|
||||
for s_idx in &blocks[b_idx].succ {
|
||||
if *s_idx <= b_idx {
|
||||
let s = &blocks[*s_idx];
|
||||
|
|
@ -202,10 +219,16 @@ impl Function {
|
|||
// set for s and so no new phis should need to be added.
|
||||
// RefCell's dynamic borrow checks will assert this.
|
||||
for phi in s.phis.borrow_mut().iter_mut() {
|
||||
let b_ssa = get_ssa_or_phi(
|
||||
ssa_alloc, phi_alloc, &blocks, b_idx, phi.orig,
|
||||
);
|
||||
phi.srcs.insert(b_idx, b_ssa);
|
||||
phi.srcs.entry(b_idx).or_insert_with(|| {
|
||||
get_ssa_or_phi(
|
||||
ssa_alloc,
|
||||
phi_alloc,
|
||||
&blocks,
|
||||
&mut needs_src,
|
||||
b_idx,
|
||||
phi.orig,
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue