Module: Mesa Branch: main Commit: a59553507405c1d28d5967791c7bb7c0ae45f6b2 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=a59553507405c1d28d5967791c7bb7c0ae45f6b2
Author: Faith Ekstrand <faith.ekstr...@collabora.com> Date: Fri Dec 1 18:42:24 2023 -0600 nak: Force RA to allocate bar_in/out to the same register OpBreak and OpBSsy aren't very SSA friendly as they require bar_in and bar_out to be assigned the same register. We need to encure that RA knows about this restriction. For now, we just special-case these two instructions. In the future we may want a more generic mechanism for this but it's not worth it for just two instructions. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26463> --- src/nouveau/compiler/nak_assign_regs.rs | 48 +++++++++++++++++++++++++++++++++ src/nouveau/compiler/nak_builder.rs | 1 + src/nouveau/compiler/nak_legalize.rs | 48 +++++++++++++++++++++++++++------ 3 files changed, 89 insertions(+), 8 deletions(-) diff --git a/src/nouveau/compiler/nak_assign_regs.rs b/src/nouveau/compiler/nak_assign_regs.rs index 4901dd9c204..fe4de103c26 100644 --- a/src/nouveau/compiler/nak_assign_regs.rs +++ b/src/nouveau/compiler/nak_assign_regs.rs @@ -801,6 +801,12 @@ fn instr_assign_regs_file( } impl PerRegFile<RegAllocator> { + pub fn assign_reg(&mut self, ssa: SSAValue, reg: RegRef) { + assert!(reg.file() == ssa.file()); + assert!(reg.comps() == 1); + self[ssa.file()].assign_reg(ssa, reg.base_idx()); + } + pub fn free_killed(&mut self, killed: &KillSet) { for ssa in killed.iter() { self[ssa.file()].free_ssa(*ssa); @@ -927,6 +933,48 @@ impl AssignRegsBlock { None } + Op::Break(op) => { + for src in op.srcs_as_mut_slice() { + if let SrcRef::SSA(ssa) = src.src_ref { + assert!(ssa.comps() == 1); + let reg = self.get_scalar(ssa[0]); + src.src_ref = reg.into(); + } + } + + self.ra.free_killed(srcs_killed); + + if let Dst::SSA(ssa) = &op.bar_out { + let reg = *op.bar_in.src_ref.as_reg().unwrap(); + self.ra.assign_reg(ssa[0], reg); + op.bar_out = reg.into(); + } + + self.ra.free_killed(dsts_killed); + + Some(instr) + } + Op::BSSy(op) => { + for src in op.srcs_as_mut_slice() { + if let SrcRef::SSA(ssa) = src.src_ref { + assert!(ssa.comps() == 1); + let reg = self.get_scalar(ssa[0]); + src.src_ref = reg.into(); + } + } + + self.ra.free_killed(srcs_killed); + + if let Dst::SSA(ssa) = &op.bar_out { + let reg = *op.bar_in.src_ref.as_reg().unwrap(); + self.ra.assign_reg(ssa[0], reg); + op.bar_out = reg.into(); + } + + self.ra.free_killed(dsts_killed); + + Some(instr) + } Op::Copy(copy) => { if let SrcRef::SSA(src_vec) = ©.src.src_ref { debug_assert!(src_vec.comps() == 1); diff --git a/src/nouveau/compiler/nak_builder.rs b/src/nouveau/compiler/nak_builder.rs index f06665703a5..6f54069bfec 100644 --- a/src/nouveau/compiler/nak_builder.rs +++ b/src/nouveau/compiler/nak_builder.rs @@ -426,6 +426,7 @@ impl<'a> SSAInstrBuilder<'a> { self.b.as_vec() } + #[allow(dead_code)] pub fn as_mapped_instrs(self) -> MappedInstrs { self.b.as_mapped_instrs() } diff --git a/src/nouveau/compiler/nak_legalize.rs b/src/nouveau/compiler/nak_legalize.rs index f8297249597..e7d2113bebc 100644 --- a/src/nouveau/compiler/nak_legalize.rs +++ b/src/nouveau/compiler/nak_legalize.rs @@ -4,6 +4,7 @@ */ use crate::nak_ir::*; +use crate::nak_liveness::{BlockLiveness, Liveness, SimpleLiveness}; use std::collections::{HashMap, HashSet}; @@ -68,7 +69,12 @@ fn swap_srcs_if_not_reg(x: &mut Src, y: &mut Src) { } } -fn legalize_instr(b: &mut impl SSABuilder, instr: &mut Instr) { +fn legalize_instr( + b: &mut impl SSABuilder, + bl: &impl BlockLiveness, + ip: usize, + instr: &mut Instr, +) { match &mut instr.op { Op::FAdd(op) => { let [ref mut src0, ref mut src1] = op.srcs; @@ -255,11 +261,27 @@ fn legalize_instr(b: &mut impl SSABuilder, instr: &mut Instr) { copy_src_if_not_reg(b, &mut op.handle, RegFile::GPR); copy_src_if_cbuf(b, &mut op.stream, RegFile::GPR); } + Op::Break(op) => { + let bar_in = op.bar_in.src_ref.as_ssa().unwrap(); + if !op.bar_out.is_none() && bl.is_live_after_ip(&bar_in[0], ip) { + let gpr = b.bmov_to_gpr(op.bar_in); + let tmp = b.bmov_to_bar(gpr.into()); + op.bar_in = tmp.into(); + } + } + Op::BSSy(op) => { + let bar_in = op.bar_in.src_ref.as_ssa().unwrap(); + if !op.bar_out.is_none() && bl.is_live_after_ip(&bar_in[0], ip) { + let gpr = b.bmov_to_gpr(op.bar_in); + let tmp = b.bmov_to_bar(gpr.into()); + op.bar_in = tmp.into(); + } + } Op::OutFinal(op) => { copy_src_if_not_reg(b, &mut op.handle, RegFile::GPR); } Op::Ldc(_) => (), // Nothing to do - Op::Break(_) | Op::BSSy(_) | Op::BSync(_) => (), + Op::BSync(_) => (), Op::Vote(_) => (), // Nothing to do Op::Copy(_) => (), // Nothing to do _ => { @@ -331,11 +353,21 @@ fn legalize_instr(b: &mut impl SSABuilder, instr: &mut Instr) { impl Shader { pub fn legalize(&mut self) { - self.map_instrs(|mut instr, ssa_alloc| -> MappedInstrs { - let mut b = SSAInstrBuilder::new(ssa_alloc); - legalize_instr(&mut b, &mut instr); - b.push_instr(instr); - b.as_mapped_instrs() - }); + for f in &mut self.functions { + let live = SimpleLiveness::for_function(f); + + for (bi, b) in f.blocks.iter_mut().enumerate() { + let bl = live.block_live(bi); + + let mut instrs = Vec::new(); + for (ip, mut instr) in b.instrs.drain(..).enumerate() { + let mut b = SSAInstrBuilder::new(&mut f.ssa_alloc); + legalize_instr(&mut b, bl, ip, &mut instr); + b.push_instr(instr); + instrs.append(&mut b.as_vec()); + } + b.instrs = instrs; + } + } } }