Module: Mesa Branch: main Commit: dca65f62c8d2d3b76cd974802852b5d8441344f2 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=dca65f62c8d2d3b76cd974802852b5d8441344f2
Author: Faith Ekstrand <faith.ekstr...@collabora.com> Date: Fri Dec 1 13:22:44 2023 -0600 nak: Add support for spilling barriers Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26463> --- src/nouveau/compiler/nak_assign_regs.rs | 18 ++++++++++---- src/nouveau/compiler/nak_lower_copy_swap.rs | 20 +++++++++++++++ src/nouveau/compiler/nak_lower_par_copies.rs | 7 +++--- src/nouveau/compiler/nak_spill_values.rs | 37 ++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 8 deletions(-) diff --git a/src/nouveau/compiler/nak_assign_regs.rs b/src/nouveau/compiler/nak_assign_regs.rs index c4b5752785b..9bda8a4cae4 100644 --- a/src/nouveau/compiler/nak_assign_regs.rs +++ b/src/nouveau/compiler/nak_assign_regs.rs @@ -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); diff --git a/src/nouveau/compiler/nak_lower_copy_swap.rs b/src/nouveau/compiler/nak_lower_copy_swap.rs index 476310cc457..e6300426bef 100644 --- a/src/nouveau/compiler/nak_lower_copy_swap.rs +++ b/src/nouveau/compiler/nak_lower_copy_swap.rs @@ -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 => { diff --git a/src/nouveau/compiler/nak_lower_par_copies.rs b/src/nouveau/compiler/nak_lower_par_copies.rs index 28176da3c28..c28f7a98d61 100644 --- a/src/nouveau/compiler/nak_lower_par_copies.rs +++ b/src/nouveau/compiler/nak_lower_par_copies.rs @@ -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()); diff --git a/src/nouveau/compiler/nak_spill_values.rs b/src/nouveau/compiler/nak_spill_values.rs index ea8240da355..9c398f3aa26 100644 --- a/src/nouveau/compiler/nak_spill_values.rs +++ b/src/nouveau/compiler/nak_spill_values.rs @@ -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), }