nak: Add a Mem register file

For spilling, we want to be able to treat TLS as if it were a register
file.  It unifies and makes everything easier.  Also add support to
OpCopy to for copying between GPR and Mem.  We cannot, however copy
directly from Mem to Mem.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24998>
This commit is contained in:
Faith Ekstrand 2023-08-28 19:00:27 -05:00 committed by Marge Bot
parent fe7ac83a94
commit 4f05308ad9
4 changed files with 78 additions and 14 deletions

View file

@ -38,6 +38,7 @@ impl<T: Copy> RegTracker<T> {
RegFile::UGPR => &self.ureg[range],
RegFile::Pred => &self.pred[range],
RegFile::UPred => &self.upred[range],
RegFile::Mem => panic!("Not a register"),
}
}
@ -53,6 +54,7 @@ impl<T: Copy> RegTracker<T> {
RegFile::UGPR => &mut self.ureg[range],
RegFile::Pred => &mut self.pred[range],
RegFile::UPred => &mut self.upred[range],
RegFile::Mem => panic!("Not a register"),
}
}
}

View file

@ -39,15 +39,21 @@ pub enum RegFile {
///
/// Uniform predicate registers are 1 bit and uniform across a wave.
UPred = 3,
/// The memory register file
///
/// This is a virtual register file for things which will get spilled to
/// local memory. Each memory location is 32 bits per SIMT channel.
Mem = 4,
}
const NUM_REG_FILES: usize = 4;
const NUM_REG_FILES: usize = 5;
impl RegFile {
/// Returns true if the register file is uniform across a wave
pub fn is_uniform(&self) -> bool {
match self {
RegFile::GPR | RegFile::Pred => false,
RegFile::GPR | RegFile::Pred | RegFile::Mem => false,
RegFile::UGPR | RegFile::UPred => true,
}
}
@ -56,14 +62,14 @@ impl RegFile {
pub fn is_gpr(&self) -> bool {
match self {
RegFile::GPR | RegFile::UGPR => true,
RegFile::Pred | RegFile::UPred => false,
RegFile::Pred | RegFile::UPred | RegFile::Mem => false,
}
}
/// Returns true if the register file is a predicate register file
pub fn is_predicate(&self) -> bool {
match self {
RegFile::GPR | RegFile::UGPR => false,
RegFile::GPR | RegFile::UGPR | RegFile::Mem => false,
RegFile::Pred | RegFile::UPred => true,
}
}
@ -86,6 +92,7 @@ impl RegFile {
0
}
}
RegFile::Mem => 1 << 24,
}
}
}
@ -105,6 +112,7 @@ impl TryFrom<u32> for RegFile {
1 => Ok(RegFile::UGPR),
2 => Ok(RegFile::Pred),
3 => Ok(RegFile::UPred),
4 => Ok(RegFile::Mem),
_ => Err("Invalid register file number"),
}
}
@ -224,6 +232,7 @@ impl<T> PerRegFile<T> {
f(RegFile::UGPR),
f(RegFile::Pred),
f(RegFile::UPred),
f(RegFile::Mem),
],
}
}
@ -285,17 +294,16 @@ impl SSAValue {
/// Returns an SSA value with the given register file and index
pub fn new(file: RegFile, idx: u32) -> SSAValue {
/* Reserve 2 numbers for use for SSARef::comps() */
assert!(idx > 0 && idx < (1 << 30) - 2);
assert!(idx > 0 && idx < (1 << 29) - 2);
let mut packed = idx;
assert!(u8::from(file) < 4);
packed |= u32::from(u8::from(file)) << 30;
assert!(u8::from(file) < 8);
packed |= u32::from(u8::from(file)) << 29;
SSAValue { packed: packed }
}
/// Returns the index of this SSA value
pub fn idx(&self) -> u32 {
self.packed & 0x3fffffff
self.packed & 0x1fffffff
}
/// Returns true if this SSA value is equal to SSAValue::NONE
@ -308,7 +316,7 @@ impl SSAValue {
impl HasRegFile for SSAValue {
/// Returns the register file of this SSA value
fn file(&self) -> RegFile {
RegFile::try_from(self.packed >> 30).unwrap()
RegFile::try_from(self.packed >> 29).unwrap()
}
}
@ -319,6 +327,7 @@ impl fmt::Display for SSAValue {
RegFile::UGPR => write!(f, "US")?,
RegFile::Pred => write!(f, "PS")?,
RegFile::UPred => write!(f, "UPS")?,
RegFile::Mem => write!(f, "MS")?,
}
write!(f, "{}", self.idx())
}
@ -479,6 +488,7 @@ impl RegRef {
RegFile::UGPR => 63,
RegFile::Pred => 7,
RegFile::UPred => 7,
RegFile::Mem => panic!("Mem has no zero index"),
}
}
@ -524,6 +534,7 @@ impl fmt::Display for RegRef {
RegFile::UGPR => write!(f, "UR")?,
RegFile::Pred => write!(f, "P")?,
RegFile::UPred => write!(f, "UP")?,
RegFile::Mem => write!(f, "M")?,
}
write!(f, "{}", self.base_idx())?;
if self.comps() >= 1 {

View file

@ -3,11 +3,19 @@
use crate::nak_ir::*;
struct LowerCopySwap {}
use std::cmp::max;
struct LowerCopySwap {
tls_start: u32,
tls_size: u32,
}
impl LowerCopySwap {
fn new() -> Self {
Self {}
fn new(tls_size: u32) -> Self {
Self {
tls_start: tls_size,
tls_size: tls_size,
}
}
fn lower_copy(&mut self, b: &mut impl Builder, copy: OpCopy) {
@ -35,6 +43,23 @@ impl LowerCopySwap {
quad_lanes: 0xf,
});
}
RegFile::Mem => {
let access = MemAccess {
addr_type: MemAddrType::A32,
mem_type: MemType::B32,
space: MemSpace::Local,
order: MemOrder::Strong,
scope: MemScope::CTA,
};
let addr = self.tls_start + src_reg.base_idx() * 4;
self.tls_size = max(self.tls_size, addr + 4);
b.push_op(OpLd {
dst: copy.dst,
addr: Src::new_zero(),
offset: addr.try_into().unwrap(),
access: access,
});
}
_ => panic!("Cannot copy to GPR"),
},
SrcRef::SSA(_) => panic!("Should be run after RA"),
@ -72,6 +97,29 @@ impl LowerCopySwap {
},
SrcRef::SSA(_) => panic!("Should be run after RA"),
},
RegFile::Mem => match copy.src.src_ref {
SrcRef::Reg(src_reg) => match src_reg.file() {
RegFile::GPR => {
let access = MemAccess {
addr_type: MemAddrType::A32,
mem_type: MemType::B32,
space: MemSpace::Local,
order: MemOrder::Strong,
scope: MemScope::CTA,
};
let addr = self.tls_start + dst_reg.base_idx() * 4;
self.tls_size = max(self.tls_size, addr + 4);
b.push_op(OpSt {
addr: Src::new_zero(),
data: copy.src,
offset: addr.try_into().unwrap(),
access: access,
});
}
_ => panic!("Cannot copy to Mem"),
},
_ => panic!("Cannot copy to Mem"),
},
_ => panic!("Unhandled register file"),
}
}
@ -81,6 +129,7 @@ impl LowerCopySwap {
let y = *swap.dsts[1].as_reg().unwrap();
assert!(x.file() == y.file());
assert!(x.file() != RegFile::Mem);
assert!(x.comps() == 1 && y.comps() == 1);
assert!(swap.srcs[0].src_mod.is_none());
assert!(*swap.srcs[0].src_ref.as_reg().unwrap() == y);
@ -129,7 +178,8 @@ impl LowerCopySwap {
impl Shader {
pub fn lower_copy_swap(&mut self) {
let mut pass = LowerCopySwap::new();
let mut pass = LowerCopySwap::new(self.tls_size);
pass.run(self);
self.tls_size = pass.tls_size;
}
}

View file

@ -154,6 +154,7 @@ impl LopPass {
srcs[src_idx] = match ssa.file() {
RegFile::GPR | RegFile::UGPR => SrcRef::Zero.into(),
RegFile::Pred | RegFile::UPred => SrcRef::True.into(),
RegFile::Mem => panic!("Not a register"),
};
for i in 0..3 {