diff --git a/src/nouveau/compiler/nak_assign_regs.rs b/src/nouveau/compiler/nak_assign_regs.rs index 689d50253af..d16ad55d8bb 100644 --- a/src/nouveau/compiler/nak_assign_regs.rs +++ b/src/nouveau/compiler/nak_assign_regs.rs @@ -177,6 +177,10 @@ impl RegAllocator { self.file } + pub fn num_regs_used(&self) -> u32 { + self.ssa_reg.len().try_into().unwrap() + } + pub fn reg_is_used(&self, reg: u32) -> bool { self.used.get(reg.try_into().unwrap()) } @@ -992,6 +996,30 @@ impl AssignRegsBlock { Some(instr) } } + Op::FSOut(out) => { + for src in out.srcs.iter_mut() { + if let SrcRef::SSA(src_vec) = src.src_ref { + debug_assert!(src_vec.comps() == 1); + let src_ssa = &src_vec[0]; + src.src_ref = self.get_scalar(*src_ssa).into(); + } + } + + self.ra.free_killed(srcs_killed); + assert!(dsts_killed.is_empty()); + + // This should be the last instruction and its sources should + // be the last free GPRs. + debug_assert!(self.ra[RegFile::GPR].num_regs_used() == 0); + + for (i, src) in out.srcs.iter().enumerate() { + let reg = u32::try_from(i).unwrap(); + let dst = RegRef::new(RegFile::GPR, reg, 1); + pcopy.push(dst.into(), *src); + } + + None + } _ => { for file in self.ra.values_mut() { instr_assign_regs_file( diff --git a/src/nouveau/compiler/nak_ir.rs b/src/nouveau/compiler/nak_ir.rs index 03c4d2ffffd..f3f9b8c2590 100644 --- a/src/nouveau/compiler/nak_ir.rs +++ b/src/nouveau/compiler/nak_ir.rs @@ -4314,15 +4314,6 @@ impl Shader { dst: neg.dst, srcs: [Src::new_zero(), neg.src.ineg(), Src::new_zero()], })), - Op::FSOut(out) => { - let mut pcopy = OpParCopy::new(); - for (i, src) in out.srcs.iter().enumerate() { - let dst = - RegRef::new(RegFile::GPR, i.try_into().unwrap(), 1); - pcopy.push(dst.into(), *src); - } - MappedInstrs::One(Instr::new_boxed(pcopy)) - } _ => MappedInstrs::One(instr), } }) diff --git a/src/nouveau/compiler/nak_liveness.rs b/src/nouveau/compiler/nak_liveness.rs index ac27a51b8a2..a2012c9d2fa 100644 --- a/src/nouveau/compiler/nak_liveness.rs +++ b/src/nouveau/compiler/nak_liveness.rs @@ -209,6 +209,15 @@ pub trait Liveness { max_live = PerRegFile::new_with(|file| { max(max_live[file], live_at_instr[file]) }); + + if let Op::FSOut(fs_out) = &instr.op { + // This should be the last instruction. Everything should + // be dead once we've processed it. + debug_assert!(live.count(RegFile::GPR) == 0); + let num_gprs_out = fs_out.srcs.len().try_into().unwrap(); + max_live[RegFile::GPR] = + max(max_live[RegFile::GPR], num_gprs_out); + } } assert!(block_live_out.len() == bb_idx);