nak: Properly handle OpFSOut in RA and liveness
That one's a bit magic because it exists to ensure that each output GPR ends up in the right register at the end of the shader. We tried to handle it as a simple lowering before but it's easier and safer to handle it directly in RA and liveness. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24998>
This commit is contained in:
committed by
Marge Bot
parent
c47488341e
commit
ecf5c4c13b
@@ -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(
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
})
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user