nak: Add support for nir_op_bitcount

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24998>
This commit is contained in:
Daniel Almeida 2023-07-17 13:55:02 -03:00 committed by Marge Bot
parent d133603c7d
commit d27e271ba5
4 changed files with 45 additions and 3 deletions

View file

@ -1481,6 +1481,19 @@ impl SM75Instr {
self.set_field(72..80, op.idx);
}
fn encode_popc(&mut self, op: &OpPopC) {
self.encode_alu(
0x109,
Some(op.dst),
ALUSrc::None,
ALUSrc::from_src(&op.src),
ALUSrc::None,
);
let not_mod = matches!(op.src.src_mod, SrcMod::BNot);
self.set_field(63..64, not_mod)
}
pub fn encode(
instr: &Instr,
sm: u8,
@ -1539,6 +1552,7 @@ impl SM75Instr {
Op::Exit(op) => si.encode_exit(&op),
Op::Bar(op) => si.encode_bar(&op),
Op::S2R(op) => si.encode_s2r(&op),
Op::PopC(op) => si.encode_popc(&op),
_ => panic!("Unhandled instruction"),
}

View file

@ -208,6 +208,14 @@ impl<'a> ShaderFromNir<'a> {
Src::new_imm_u32(0x3f800000),
),
nir_op_bcsel => b.sel(srcs[0], srcs[1], srcs[2]),
nir_op_bit_count => {
let dst = b.alloc_ssa(RegFile::GPR, 1);
b.push_op(OpPopC {
dst: dst.into(),
src: srcs[0],
});
dst
}
nir_op_f2i32 | nir_op_f2u32 => {
let src_bits = usize::from(alu.get_src(0).bit_size());
let dst_bits = alu.def.bit_size();

View file

@ -3135,6 +3135,21 @@ impl fmt::Display for OpFSOut {
}
}
#[repr(C)]
#[derive(SrcsAsSlice, DstsAsSlice)]
pub struct OpPopC {
pub dst: Dst,
#[src_type(ALU)]
pub src: Src,
}
impl fmt::Display for OpPopC {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "POPC {} {}", self.dst, self.src,)
}
}
#[derive(Display, DstsAsSlice, SrcsAsSlice, FromVariants)]
pub enum Op {
FAdd(OpFAdd),
@ -3189,6 +3204,7 @@ pub enum Op {
Swap(OpSwap),
ParCopy(OpParCopy),
FSOut(OpFSOut),
PopC(OpPopC),
}
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
@ -3505,6 +3521,7 @@ impl Instr {
| Op::FSOut(_) => {
panic!("Not a hardware opcode")
}
Op::PopC(_) => Some(15),
}
}
}

View file

@ -182,9 +182,12 @@ impl<'a> LegalizeInstr<'a> {
self.mov_src_if_not_reg(&mut op.low, RegFile::GPR);
self.mov_src_if_not_reg(&mut op.high, RegFile::GPR);
}
Op::F2F(_) | Op::F2I(_) | Op::I2F(_) | Op::Mov(_) | Op::FRnd(_) => {
()
}
Op::F2F(_)
| Op::F2I(_)
| Op::I2F(_)
| Op::Mov(_)
| Op::FRnd(_)
| Op::PopC(_) => (),
Op::Sel(op) => {
let [ref mut src0, ref mut src1] = op.srcs;
if !src_is_reg(src0) && src_is_reg(src1) {