diff --git a/src/nouveau/compiler/nak_assign_regs.rs b/src/nouveau/compiler/nak_assign_regs.rs index 017b6cc26e0..cbaea0b3eef 100644 --- a/src/nouveau/compiler/nak_assign_regs.rs +++ b/src/nouveau/compiler/nak_assign_regs.rs @@ -177,7 +177,7 @@ impl RegAllocator { self.file } - fn reg_is_used(&self, reg: u32) -> bool { + pub fn reg_is_used(&self, reg: u32) -> bool { self.used.get(reg.try_into().unwrap()) } @@ -850,7 +850,7 @@ impl AssignRegsBlock { dsts_killed: &KillSet, pcopy: &mut OpParCopy, ) -> Option> { - match &instr.op { + match &mut instr.op { Op::Undef(undef) => { if let Dst::SSA(ssa) = undef.dst { assert!(ssa.comps() == 1); @@ -893,6 +893,51 @@ impl AssignRegsBlock { None } + Op::ParCopy(pcopy) => { + for (_, src) in pcopy.dsts_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); + + // Try to propagate sources if possible + for (dst, src) in pcopy.dsts_srcs.iter_mut() { + let SrcRef::Reg(src_reg) = src.src_ref else { + continue; + }; + debug_assert!(src_reg.comps() == 1); + + let Dst::SSA(dst_vec) = dst else { + continue; + }; + debug_assert!(dst_vec.comps() == 1); + let dst_ssa = &dst_vec[0]; + + if dst_ssa.file() != src_reg.file() { + continue; + } + + let ra = &mut self.ra[src_reg.file()]; + if !ra.reg_is_used(src_reg.base_idx()) { + ra.assign_reg(*dst_ssa, src_reg.base_idx()); + *dst = src_reg.into(); + } + } + + for (dst, _) in pcopy.dsts_srcs.iter_mut() { + if let Dst::SSA(dst_vec) = dst { + debug_assert!(dst_vec.comps() == 1); + *dst = self.alloc_scalar(ip, sum, dst_vec[0]).into(); + } + } + + self.ra.free_killed(dsts_killed); + Some(instr) + } _ => { for file in self.ra.values_mut() { instr_assign_regs_file(