From 548cb292cf18439f2d7aa1484af3326dc1728b9b Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Mon, 10 Apr 2023 17:23:24 -0500 Subject: [PATCH] nak: Add separate True and False source types Part-of: --- src/nouveau/compiler/nak.rs | 1 + src/nouveau/compiler/nak_encode_sm75.rs | 25 +++++-- src/nouveau/compiler/nak_from_nir.rs | 27 ++++--- src/nouveau/compiler/nak_ir.rs | 96 +++++++++++++++++++++++-- src/nouveau/compiler/nak_legalize.rs | 2 +- 5 files changed, 126 insertions(+), 25 deletions(-) diff --git a/src/nouveau/compiler/nak.rs b/src/nouveau/compiler/nak.rs index 9a8fbde0e69..5ca3844b3f4 100644 --- a/src/nouveau/compiler/nak.rs +++ b/src/nouveau/compiler/nak.rs @@ -331,6 +331,7 @@ pub extern "C" fn nak_compile_shader( s.assign_regs_trivial(); s.lower_vec_split(); + s.lower_mov_predicate(); s.calc_instr_deps(); println!("NAK IR:\n{}", &s); diff --git a/src/nouveau/compiler/nak_encode_sm75.rs b/src/nouveau/compiler/nak_encode_sm75.rs index 825b6da47cd..9df8799312c 100644 --- a/src/nouveau/compiler/nak_encode_sm75.rs +++ b/src/nouveau/compiler/nak_encode_sm75.rs @@ -157,9 +157,20 @@ impl SM75Instr { } } - fn set_pred_src(&mut self, range: Range, not_bit: isize, src: Src) { + fn set_pred_src( + &mut self, + range: Range, + not_bit: isize, + src: Src, + default: bool, + ) { match src.src_ref { - SrcRef::Zero => { + SrcRef::True => { + assert!(default); + self.set_pred_reg(range, RegRef::zero(RegFile::Pred, 1)); + } + SrcRef::False => { + assert!(!default); self.set_pred_reg(range, RegRef::zero(RegFile::Pred, 1)); } SrcRef::Reg(reg) => self.set_pred_reg(range, reg), @@ -455,7 +466,7 @@ impl SM75Instr { } self.set_pred_dst(81..84, op.overflow); - self.set_pred_src(84..87, -1, op.carry); + self.set_pred_src(84..87, -1, op.carry, false); } fn set_int_cmp_op(&mut self, range: Range, op: IntCmpOp) { @@ -566,7 +577,7 @@ impl SM75Instr { ALUSrc::None, ); - self.set_pred_src(87..90, 90, op.cond); + self.set_pred_src(87..90, 90, op.cond, true); } fn encode_plop3(&mut self, op: &OpPLop3) { @@ -574,13 +585,13 @@ impl SM75Instr { self.set_field(64..67, op.op.lut & 0x7); self.set_field(72..77, op.op.lut >> 3); - self.set_pred_src(68..71, 71, op.srcs[2]); + self.set_pred_src(68..71, 71, op.srcs[2], true); - self.set_pred_src(77..80, 80, op.srcs[1]); + self.set_pred_src(77..80, 80, op.srcs[1], true); self.set_pred_dst(81..84, op.dst); self.set_field(84..87, 7_u8); /* Def1 */ - self.set_pred_src(87..90, 90, op.srcs[0]); + self.set_pred_src(87..90, 90, op.srcs[0], true); } fn set_mem_access(&mut self, access: &MemAccess) { diff --git a/src/nouveau/compiler/nak_from_nir.rs b/src/nouveau/compiler/nak_from_nir.rs index a4c20f0aba5..9d138c49648 100644 --- a/src/nouveau/compiler/nak_from_nir.rs +++ b/src/nouveau/compiler/nak_from_nir.rs @@ -238,7 +238,7 @@ impl<'a> ShaderFromNir<'a> { dst: sum[0].into(), overflow: carry.into(), srcs: [x[0].into(), y[0].into(), Src::new_zero()], - carry: Src::new_zero(), + carry: SrcRef::False.into(), }))); self.instrs.push(Instr::new(Op::IAdd3(OpIAdd3 { dst: sum[1].into(), @@ -260,7 +260,7 @@ impl<'a> ShaderFromNir<'a> { LogicOp::new_lut(&|x, y, _| x & y), srcs[0], srcs[1], - Src::new_zero(), + Src::new_imm_bool(true), )); } else { self.instrs.push(Instr::new_lop3( @@ -320,8 +320,8 @@ impl<'a> ShaderFromNir<'a> { dst, LogicOp::new_lut(&|x, _, _| !x), srcs[0], - Src::new_zero(), - Src::new_zero(), + Src::new_imm_bool(true), + Src::new_imm_bool(true), )); } else { self.instrs.push(Instr::new_lop3( @@ -340,7 +340,7 @@ impl<'a> ShaderFromNir<'a> { LogicOp::new_lut(&|x, y, _| x | y), srcs[0], srcs[1], - Src::new_zero(), + Src::new_imm_bool(true), )); } else { self.instrs.push(Instr::new_lop3( @@ -508,13 +508,18 @@ impl<'a> ShaderFromNir<'a> { let dst = self.get_dst(&load_const.def); let mut srcs = Vec::new(); for c in 0..load_const.def.num_components { - assert!(load_const.def.bit_size == 32); - let imm_u32 = unsafe { load_const.values()[c as usize].u32_ }; - srcs.push(if imm_u32 == 0 { - Src::new_zero() + if load_const.def.bit_size == 1 { + let imm_b1 = unsafe { load_const.values()[c as usize].b }; + srcs.push(Src::new_imm_bool(imm_b1)); } else { - Src::new_imm_u32(imm_u32) - }); + assert!(load_const.def.bit_size == 32); + let imm_u32 = unsafe { load_const.values()[c as usize].u32_ }; + srcs.push(if imm_u32 == 0 { + Src::new_zero() + } else { + Src::new_imm_u32(imm_u32) + }); + } } self.instrs.push(Instr::new_vec(dst, &srcs)); } diff --git a/src/nouveau/compiler/nak_ir.rs b/src/nouveau/compiler/nak_ir.rs index 4381e8ac595..0c4e6be6e09 100644 --- a/src/nouveau/compiler/nak_ir.rs +++ b/src/nouveau/compiler/nak_ir.rs @@ -277,6 +277,8 @@ pub struct CBufRef { #[derive(Clone, Copy)] pub enum SrcRef { Zero, + True, + False, Imm32(u32), CBuf(CBufRef), SSA(SSAValue), @@ -300,7 +302,11 @@ impl SrcRef { pub fn get_reg(&self) -> Option<&RegRef> { match self { - SrcRef::Zero | SrcRef::Imm32(_) | SrcRef::SSA(_) => None, + SrcRef::Zero + | SrcRef::True + | SrcRef::False + | SrcRef::Imm32(_) + | SrcRef::SSA(_) => None, SrcRef::CBuf(cb) => match &cb.buf { CBuf::Binding(_) | CBuf::BindlessSSA(_) => None, CBuf::BindlessGPR(reg) => Some(reg), @@ -311,7 +317,11 @@ impl SrcRef { pub fn get_ssa(&self) -> Option<&SSAValue> { match self { - SrcRef::Zero | SrcRef::Imm32(_) | SrcRef::Reg(_) => None, + SrcRef::Zero + | SrcRef::True + | SrcRef::False + | SrcRef::Imm32(_) + | SrcRef::Reg(_) => None, SrcRef::CBuf(cb) => match &cb.buf { CBuf::Binding(_) | CBuf::BindlessGPR(_) => None, CBuf::BindlessSSA(ssa) => Some(ssa), @@ -337,6 +347,8 @@ impl fmt::Display for SrcRef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { SrcRef::Zero => write!(f, "ZERO")?, + SrcRef::True => write!(f, "TRUE")?, + SrcRef::False => write!(f, "FALSE")?, SrcRef::Imm32(u) => write!(f, "{:#x}", u)?, SrcRef::CBuf(r) => { match r.buf { @@ -451,6 +463,10 @@ impl Src { SrcRef::Imm32(u).into() } + pub fn new_imm_bool(b: bool) -> Src { + Src::from(if b { SrcRef::True } else { SrcRef::False }) + } + pub fn new_cbuf(idx: u8, offset: u16) -> Src { SrcRef::CBuf(CBufRef { buf: CBuf::Binding(idx), @@ -498,12 +514,25 @@ impl Src { pub fn is_uniform(&self) -> bool { match self.src_ref { - SrcRef::Zero | SrcRef::Imm32(_) | SrcRef::CBuf(_) => true, + SrcRef::Zero + | SrcRef::True + | SrcRef::False + | SrcRef::Imm32(_) + | SrcRef::CBuf(_) => true, SrcRef::SSA(ssa) => ssa.is_uniform(), SrcRef::Reg(reg) => reg.is_uniform(), } } + pub fn is_predicate(&self) -> bool { + match self.src_ref { + SrcRef::Zero | SrcRef::Imm32(_) | SrcRef::CBuf(_) => false, + SrcRef::True | SrcRef::False => true, + SrcRef::SSA(ssa) => ssa.is_predicate(), + SrcRef::Reg(reg) => reg.is_predicate(), + } + } + pub fn is_zero(&self) -> bool { match self.src_ref { SrcRef::Zero => true, @@ -514,7 +543,10 @@ impl Src { pub fn is_reg_or_zero(&self) -> bool { match self.src_ref { SrcRef::Zero | SrcRef::SSA(_) | SrcRef::Reg(_) => true, - SrcRef::Imm32(_) | SrcRef::CBuf(_) => false, + SrcRef::True + | SrcRef::False + | SrcRef::Imm32(_) + | SrcRef::CBuf(_) => false, } } } @@ -660,6 +692,12 @@ impl LogicOp { } } + pub fn new_const(val: bool) -> LogicOp { + LogicOp { + lut: if val { !0 } else { 0 }, + } + } + pub fn eval< T: BitAnd + BitOr + Copy + Not, >( @@ -1614,7 +1652,7 @@ impl Instr { dst: dst, overflow: Dst::None, srcs: [Src::new_zero(), x, y], - carry: Src::new_zero(), + carry: Src::new_imm_bool(false), })) } @@ -1675,6 +1713,7 @@ impl Instr { } pub fn new_plop3(dst: Dst, op: LogicOp, x: Src, y: Src, z: Src) -> Instr { + assert!(x.is_predicate() && y.is_predicate() && z.is_predicate()); Instr::new(Op::PLop3(OpPLop3 { dst: dst, srcs: [x, y, z], @@ -1974,7 +2013,7 @@ impl Shader { dst: mov.dst, overflow: Dst::None, srcs: [Src::new_zero(), mov.src, Src::new_zero()], - carry: Src::new_zero(), + carry: Src::new_imm_bool(false), }))] } Op::Vec(vec) => { @@ -2029,6 +2068,51 @@ impl Shader { } }) } + + pub fn lower_mov_predicate(&mut self) { + self.map_instrs(&|instr: Instr, _| -> Vec { + match &instr.op { + Op::Mov(mov) => { + assert!(mov.src.src_mod.is_none()); + match mov.src.src_ref { + SrcRef::True => { + vec![Instr::new_isetp( + mov.dst, + IntCmpType::I32, + IntCmpOp::Eq, + Src::new_zero(), + Src::new_zero(), + )] + } + SrcRef::False => { + vec![Instr::new_isetp( + mov.dst, + IntCmpType::I32, + IntCmpOp::Ne, + Src::new_zero(), + Src::new_zero(), + )] + } + SrcRef::Reg(reg) => { + if reg.is_predicate() { + vec![Instr::new_plop3( + mov.dst, + LogicOp::new_lut(&|x, _, _| x), + mov.src, + Src::new_imm_bool(true), + Src::new_imm_bool(true), + )] + } else { + vec![instr] + } + } + _ => vec![instr], + } + } + _ => vec![instr], + } + }) + } } impl fmt::Display for Shader { diff --git a/src/nouveau/compiler/nak_legalize.rs b/src/nouveau/compiler/nak_legalize.rs index 054ef696e21..4994563a82c 100644 --- a/src/nouveau/compiler/nak_legalize.rs +++ b/src/nouveau/compiler/nak_legalize.rs @@ -12,7 +12,7 @@ struct LegalizeInstr<'a> { fn src_is_reg(src: &Src) -> bool { match src.src_ref { - SrcRef::Zero | SrcRef::SSA(_) => true, + SrcRef::Zero | SrcRef::True | SrcRef::False | SrcRef::SSA(_) => true, SrcRef::Imm32(_) | SrcRef::CBuf(_) => false, SrcRef::Reg(_) => panic!("Not in SSA form"), }