nak: Add support for spilling barriers

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26463>
This commit is contained in:
Faith Ekstrand 2023-12-01 13:22:44 -06:00 committed by Marge Bot
parent 7cd9680554
commit dca65f62c8
4 changed files with 74 additions and 8 deletions

View file

@ -1154,7 +1154,10 @@ impl Shader {
let mut live = SimpleLiveness::for_function(f);
let mut max_live = live.calc_max_live(f);
let spill_files = [RegFile::Pred];
// We want at least one temporary GPR reserved for parallel copies.
let mut tmp_gprs = 1_u8;
let spill_files = [RegFile::Pred, RegFile::Bar];
for file in spill_files {
let num_regs = file.num_regs(self.info.sm);
if max_live[file] > num_regs {
@ -1163,14 +1166,19 @@ impl Shader {
// Re-calculate liveness after we spill
live = SimpleLiveness::for_function(f);
max_live = live.calc_max_live(f);
match file {
RegFile::Bar => {
tmp_gprs = max(tmp_gprs, 2);
}
_ => (),
}
}
}
// An instruction can have at most 4 vector sources/destinations. In
// order to ensure we always succeed at allocation, regardless of
// arbitrary choices, we need at least 16 GPRs. We also want at least
// one temporary GPR reserved for parallel copies.
let mut tmp_gprs = 1_u8;
// arbitrary choices, we need at least 16 GPRs.
let mut gpr_limit = max(max_live[RegFile::GPR], 16);
let mut total_gprs = gpr_limit + u32::from(tmp_gprs);
@ -1179,7 +1187,7 @@ impl Shader {
// If we're spilling GPRs, we need to reserve 2 GPRs for OpParCopy
// lowering because it needs to be able lower Mem copies which
// require a temporary
tmp_gprs = 2_u8;
tmp_gprs = max(tmp_gprs, 2);
total_gprs = max_gprs;
gpr_limit = total_gprs - u32::from(tmp_gprs);

View file

@ -43,6 +43,13 @@ impl LowerCopySwap {
quad_lanes: 0xf,
});
}
RegFile::Bar => {
b.push_op(OpBMov {
dst: copy.dst,
src: copy.src,
clear: false,
});
}
RegFile::Mem => {
let access = MemAccess {
mem_type: MemType::B32,
@ -96,6 +103,19 @@ impl LowerCopySwap {
},
SrcRef::SSA(_) => panic!("Should be run after RA"),
},
RegFile::Bar => match copy.src.src_ref {
SrcRef::Reg(src_reg) => match src_reg.file() {
RegFile::GPR => {
b.push_op(OpBMov {
dst: copy.dst,
src: copy.src,
clear: false,
});
}
_ => panic!("Cannot copy to Bar"),
},
_ => panic!("Cannot copy to Bar"),
},
RegFile::Mem => match copy.src.src_ref {
SrcRef::Reg(src_reg) => match src_reg.file() {
RegFile::GPR => {

View file

@ -62,7 +62,8 @@ impl CopyGraph {
fn copy_needs_tmp(dst: &RegRef, src: &SrcRef) -> bool {
if let Some(src_reg) = src.as_reg() {
dst.file() == RegFile::Mem && src_reg.file() == RegFile::Mem
(dst.file() == RegFile::Mem && src_reg.file() == RegFile::Mem)
|| (dst.file() == RegFile::Bar && src_reg.file() == RegFile::Bar)
} else {
false
}
@ -78,7 +79,7 @@ fn cycle_use_swap(pc: &OpParCopy, file: RegFile) -> bool {
true
}
}
RegFile::Mem => {
RegFile::Bar | RegFile::Mem => {
let tmp = &pc.tmp.expect("This copy needs a temporary");
assert!(tmp.comps() >= 2, "Memory cycles need 2 temporaries");
false
@ -230,7 +231,7 @@ fn lower_par_copy(pc: OpParCopy) -> MappedInstrs {
let j_reg = *vals[j].as_reg().unwrap();
debug_assert!(j_reg.file() == file);
if file == RegFile::Mem {
if file == RegFile::Bar || file == RegFile::Mem {
let copy_tmp = pc_tmp.comp(1);
b.copy_to(copy_tmp.into(), j_reg.into());
b.copy_to(p_reg.into(), copy_tmp.into());

View file

@ -138,6 +138,39 @@ impl Spill for SpillPred {
}
}
struct SpillBar {}
impl SpillBar {
fn new() -> Self {
Self {}
}
}
impl Spill for SpillBar {
fn spill_file(&self, file: RegFile) -> RegFile {
assert!(file == RegFile::Bar);
RegFile::GPR
}
fn spill(&self, dst: SSAValue, src: Src) -> Box<Instr> {
assert!(dst.file() == RegFile::GPR);
Instr::new_boxed(OpBMov {
dst: dst.into(),
src: src.into(),
clear: false,
})
}
fn fill(&self, dst: Dst, src: SSAValue) -> Box<Instr> {
assert!(src.file() == RegFile::GPR);
Instr::new_boxed(OpBMov {
dst: dst.into(),
src: src.into(),
clear: false,
})
}
}
struct SpillGPR {}
impl SpillGPR {
@ -864,6 +897,10 @@ impl Function {
let spill = SpillPred::new();
spill_values(self, file, limit, spill);
}
RegFile::Bar => {
let spill = SpillBar::new();
spill_values(self, file, limit, spill);
}
_ => panic!("Don't know how to spill {} registers", file),
}