mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-26 15:00:10 +01:00
nak: Add a builder
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24998>
This commit is contained in:
parent
063c9f41fa
commit
2d69a2c1d7
6 changed files with 835 additions and 718 deletions
|
|
@ -6,6 +6,7 @@
|
|||
mod bitset;
|
||||
mod bitview;
|
||||
mod nak_assign_regs;
|
||||
mod nak_builder;
|
||||
mod nak_calc_instr_deps;
|
||||
mod nak_encode_sm75;
|
||||
mod nak_from_nir;
|
||||
|
|
|
|||
|
|
@ -272,9 +272,8 @@ impl RegFileAllocation {
|
|||
let reg = self.used.next_unset(next_reg.into());
|
||||
|
||||
/* Ensure we're properly aligned */
|
||||
let reg = match u8::try_from(reg.next_multiple_of(align.into())) {
|
||||
Ok(r) => r,
|
||||
Err(_) => return None,
|
||||
let Ok(reg) = u8::try_from(reg.next_multiple_of(align.into())) else {
|
||||
return None;
|
||||
};
|
||||
|
||||
if !self.is_reg_in_bounds(reg, comps) {
|
||||
|
|
|
|||
281
src/nouveau/compiler/nak_builder.rs
Normal file
281
src/nouveau/compiler/nak_builder.rs
Normal file
|
|
@ -0,0 +1,281 @@
|
|||
/*
|
||||
* Copyright © 2022 Collabora, Ltd.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
use crate::nak_ir::*;
|
||||
|
||||
pub trait Builder {
|
||||
fn push_instr(&mut self, instr: Box<Instr>);
|
||||
|
||||
fn push_op(&mut self, op: impl Into<Op>) {
|
||||
self.push_instr(Instr::new_boxed(op));
|
||||
}
|
||||
|
||||
fn predicate<'a>(&'a mut self, pred: Pred) -> PredicatedBuilder<'a, Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
PredicatedBuilder {
|
||||
b: self,
|
||||
pred: pred,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SSABuilder: Builder {
|
||||
fn alloc_ssa(&mut self, file: RegFile, comps: u8) -> SSARef;
|
||||
|
||||
fn fadd(&mut self, x: Src, y: Src) -> SSARef {
|
||||
let dst = self.alloc_ssa(RegFile::GPR, 1);
|
||||
self.push_op(OpFAdd {
|
||||
dst: dst.into(),
|
||||
srcs: [x, y],
|
||||
saturate: false,
|
||||
rnd_mode: FRndMode::NearestEven,
|
||||
});
|
||||
dst
|
||||
}
|
||||
|
||||
fn fmul(&mut self, x: Src, y: Src) -> SSARef {
|
||||
let dst = self.alloc_ssa(RegFile::GPR, 1);
|
||||
self.push_op(OpFMul {
|
||||
dst: dst.into(),
|
||||
srcs: [x, y],
|
||||
saturate: false,
|
||||
rnd_mode: FRndMode::NearestEven,
|
||||
});
|
||||
dst
|
||||
}
|
||||
|
||||
fn fset(&mut self, cmp_op: FloatCmpOp, x: Src, y: Src) -> SSARef {
|
||||
let dst = self.alloc_ssa(RegFile::GPR, 1);
|
||||
self.push_op(OpFSet {
|
||||
dst: dst.into(),
|
||||
cmp_op: cmp_op,
|
||||
srcs: [x, y],
|
||||
});
|
||||
dst
|
||||
}
|
||||
|
||||
fn fsetp(&mut self, cmp_op: FloatCmpOp, x: Src, y: Src) -> SSARef {
|
||||
let dst = self.alloc_ssa(RegFile::Pred, 1);
|
||||
self.push_op(OpFSetP {
|
||||
dst: dst.into(),
|
||||
set_op: PredSetOp::And,
|
||||
cmp_op: cmp_op,
|
||||
srcs: [x, y],
|
||||
accum: SrcRef::True.into(),
|
||||
});
|
||||
dst
|
||||
}
|
||||
|
||||
fn iabs(&mut self, i: Src) -> SSARef {
|
||||
let dst = self.alloc_ssa(RegFile::GPR, 1);
|
||||
self.push_op(OpIAbs {
|
||||
dst: dst.into(),
|
||||
src: i,
|
||||
});
|
||||
dst
|
||||
}
|
||||
|
||||
fn iadd(&mut self, x: Src, y: Src) -> SSARef {
|
||||
let dst = self.alloc_ssa(RegFile::GPR, 1);
|
||||
self.push_op(OpIAdd3 {
|
||||
dst: dst.into(),
|
||||
overflow: Dst::None,
|
||||
srcs: [Src::new_zero(), x, y],
|
||||
carry: Src::new_imm_bool(false),
|
||||
});
|
||||
dst
|
||||
}
|
||||
|
||||
fn ineg(&mut self, i: Src) -> SSARef {
|
||||
let dst = self.alloc_ssa(RegFile::GPR, 1);
|
||||
self.push_op(OpINeg {
|
||||
dst: dst.into(),
|
||||
src: i,
|
||||
});
|
||||
dst
|
||||
}
|
||||
|
||||
fn isetp(
|
||||
&mut self,
|
||||
cmp_type: IntCmpType,
|
||||
cmp_op: IntCmpOp,
|
||||
x: Src,
|
||||
y: Src,
|
||||
) -> SSARef {
|
||||
let dst = self.alloc_ssa(RegFile::Pred, 1);
|
||||
self.push_op(OpISetP {
|
||||
dst: dst.into(),
|
||||
set_op: PredSetOp::And,
|
||||
cmp_op: cmp_op,
|
||||
cmp_type: cmp_type,
|
||||
srcs: [x, y],
|
||||
accum: SrcRef::True.into(),
|
||||
});
|
||||
dst
|
||||
}
|
||||
|
||||
fn lop2(&mut self, op: LogicOp, x: Src, y: Src) -> SSARef {
|
||||
/* Only uses x and y */
|
||||
assert!(op.eval(0x5, 0x3, 0x0) == op.eval(0x5, 0x3, 0xf));
|
||||
assert!(x.is_predicate() == y.is_predicate());
|
||||
if x.is_predicate() {
|
||||
let dst = self.alloc_ssa(RegFile::Pred, 1);
|
||||
self.push_op(OpPLop3 {
|
||||
dsts: [dst.into(), Dst::None],
|
||||
srcs: [x, y, Src::new_imm_bool(true)],
|
||||
ops: [op, LogicOp::new_const(false)],
|
||||
});
|
||||
dst
|
||||
} else {
|
||||
let dst = self.alloc_ssa(RegFile::GPR, 1);
|
||||
self.push_op(OpLop3 {
|
||||
dst: dst.into(),
|
||||
srcs: [x, y, Src::new_zero()],
|
||||
op: op,
|
||||
});
|
||||
dst
|
||||
}
|
||||
}
|
||||
|
||||
fn mov(&mut self, src: Src) -> SSARef {
|
||||
assert!(!src.is_predicate());
|
||||
let dst = self.alloc_ssa(RegFile::GPR, 1);
|
||||
self.push_op(OpMov {
|
||||
dst: dst.into(),
|
||||
src: src,
|
||||
quad_lanes: 0xf,
|
||||
});
|
||||
dst
|
||||
}
|
||||
|
||||
fn mufu(&mut self, op: MuFuOp, src: Src) -> SSARef {
|
||||
let dst = self.alloc_ssa(RegFile::GPR, 1);
|
||||
self.push_op(OpMuFu {
|
||||
dst: dst.into(),
|
||||
op: op,
|
||||
src: src,
|
||||
});
|
||||
dst
|
||||
}
|
||||
|
||||
fn sel(&mut self, cond: Src, x: Src, y: Src) -> SSARef {
|
||||
assert!(cond.src_ref.is_predicate());
|
||||
assert!(x.is_predicate() == y.is_predicate());
|
||||
if x.is_predicate() {
|
||||
let dst = self.alloc_ssa(RegFile::Pred, 1);
|
||||
self.push_op(OpPLop3 {
|
||||
dsts: [dst.into(), Dst::None],
|
||||
srcs: [cond, x, y],
|
||||
ops: [
|
||||
LogicOp::new_lut(&|c, x, y| (c & x) | (!c & y)),
|
||||
LogicOp::new_const(false),
|
||||
],
|
||||
});
|
||||
dst
|
||||
} else {
|
||||
let dst = self.alloc_ssa(RegFile::GPR, 1);
|
||||
self.push_op(OpSel {
|
||||
dst: dst.into(),
|
||||
cond: cond,
|
||||
srcs: [x, y],
|
||||
});
|
||||
dst
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct InstrBuilder {
|
||||
instrs: MappedInstrs,
|
||||
}
|
||||
|
||||
impl InstrBuilder {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
instrs: MappedInstrs::None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_vec(self) -> Vec<Box<Instr>> {
|
||||
match self.instrs {
|
||||
MappedInstrs::None => Vec::new(),
|
||||
MappedInstrs::One(i) => vec![i],
|
||||
MappedInstrs::Many(v) => v,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_mapped_instrs(self) -> MappedInstrs {
|
||||
self.instrs
|
||||
}
|
||||
}
|
||||
|
||||
impl Builder for InstrBuilder {
|
||||
fn push_instr(&mut self, instr: Box<Instr>) {
|
||||
self.instrs.push(instr);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SSAInstrBuilder<'a> {
|
||||
b: InstrBuilder,
|
||||
alloc: &'a mut SSAValueAllocator,
|
||||
}
|
||||
|
||||
impl<'a> SSAInstrBuilder<'a> {
|
||||
pub fn new(alloc: &'a mut SSAValueAllocator) -> Self {
|
||||
Self {
|
||||
b: InstrBuilder::new(),
|
||||
alloc: alloc,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_vec(self) -> Vec<Box<Instr>> {
|
||||
self.b.as_vec()
|
||||
}
|
||||
|
||||
pub fn as_mapped_instrs(self) -> MappedInstrs {
|
||||
self.b.as_mapped_instrs()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Builder for SSAInstrBuilder<'a> {
|
||||
fn push_instr(&mut self, instr: Box<Instr>) {
|
||||
self.b.push_instr(instr);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SSABuilder for SSAInstrBuilder<'a> {
|
||||
fn alloc_ssa(&mut self, file: RegFile, comps: u8) -> SSARef {
|
||||
if comps == 1 {
|
||||
self.alloc.alloc(file).into()
|
||||
} else {
|
||||
let mut vec = Vec::new();
|
||||
for _ in 0..comps {
|
||||
vec.push(self.alloc.alloc(file));
|
||||
}
|
||||
vec.try_into().unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PredicatedBuilder<'a, T: Builder> {
|
||||
b: &'a mut T,
|
||||
pred: Pred,
|
||||
}
|
||||
|
||||
impl<'a, T: Builder> Builder for PredicatedBuilder<'a, T> {
|
||||
fn push_instr(&mut self, instr: Box<Instr>) {
|
||||
let mut instr = instr;
|
||||
assert!(instr.pred.is_true());
|
||||
instr.pred = self.pred;
|
||||
self.b.push_instr(instr);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: SSABuilder> SSABuilder for PredicatedBuilder<'a, T> {
|
||||
fn alloc_ssa(&mut self, file: RegFile, comps: u8) -> SSARef {
|
||||
self.b.alloc_ssa(file, comps)
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -5,6 +5,9 @@
|
|||
|
||||
extern crate nak_ir_proc;
|
||||
|
||||
pub use crate::nak_builder::{
|
||||
Builder, InstrBuilder, SSABuilder, SSAInstrBuilder,
|
||||
};
|
||||
use nak_ir_proc::*;
|
||||
use std::fmt;
|
||||
use std::iter::Zip;
|
||||
|
|
@ -650,14 +653,6 @@ impl 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),
|
||||
offset: offset,
|
||||
})
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn fabs(&self) -> Src {
|
||||
Src {
|
||||
src_ref: self.src_ref,
|
||||
|
|
@ -3046,6 +3041,7 @@ pub enum Op {
|
|||
FSOut(OpFSOut),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
|
||||
pub enum PredRef {
|
||||
None,
|
||||
SSA(SSAValue),
|
||||
|
|
@ -3099,6 +3095,7 @@ impl fmt::Display for PredRef {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Pred {
|
||||
pub pred_ref: PredRef,
|
||||
pub pred_inv: bool,
|
||||
|
|
@ -3245,87 +3242,6 @@ impl Instr {
|
|||
Box::new(Instr::new(op))
|
||||
}
|
||||
|
||||
pub fn new_fadd(dst: Dst, x: Src, y: Src) -> Instr {
|
||||
OpFAdd {
|
||||
dst: dst,
|
||||
srcs: [x, y],
|
||||
saturate: false,
|
||||
rnd_mode: FRndMode::NearestEven,
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn new_fmul(dst: Dst, x: Src, y: Src) -> Instr {
|
||||
OpFMul {
|
||||
dst: dst,
|
||||
srcs: [x, y],
|
||||
saturate: false,
|
||||
rnd_mode: FRndMode::NearestEven,
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn new_fset(dst: Dst, cmp_op: FloatCmpOp, x: Src, y: Src) -> Instr {
|
||||
OpFSet {
|
||||
dst: dst,
|
||||
cmp_op: cmp_op,
|
||||
srcs: [x, y],
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn new_fsetp(dst: Dst, cmp_op: FloatCmpOp, x: Src, y: Src) -> Instr {
|
||||
OpFSetP {
|
||||
dst: dst,
|
||||
set_op: PredSetOp::And,
|
||||
cmp_op: cmp_op,
|
||||
srcs: [x, y],
|
||||
accum: SrcRef::True.into(),
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn new_mufu(dst: Dst, op: MuFuOp, src: Src) -> Instr {
|
||||
OpMuFu {
|
||||
dst: dst,
|
||||
op: op,
|
||||
src: src,
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn new_iadd(dst: Dst, x: Src, y: Src) -> Instr {
|
||||
OpIAdd3 {
|
||||
dst: dst,
|
||||
overflow: Dst::None,
|
||||
srcs: [Src::new_zero(), x, y],
|
||||
carry: Src::new_imm_bool(false),
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn new_i2f(dst: Dst, src: Src) -> Instr {
|
||||
OpI2F {
|
||||
dst: dst,
|
||||
src: src,
|
||||
dst_type: FloatType::F32,
|
||||
src_type: IntType::I32,
|
||||
rnd_mode: FRndMode::NearestEven,
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn new_u2f(dst: Dst, src: Src) -> Instr {
|
||||
OpI2F {
|
||||
dst: dst,
|
||||
src: src,
|
||||
dst_type: FloatType::F32,
|
||||
src_type: IntType::U32,
|
||||
rnd_mode: FRndMode::NearestEven,
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn new_isetp(
|
||||
dst: Dst,
|
||||
cmp_type: IntCmpType,
|
||||
|
|
@ -3387,15 +3303,6 @@ impl Instr {
|
|||
.into()
|
||||
}
|
||||
|
||||
pub fn new_sel(dst: Dst, sel: Src, x: Src, y: Src) -> Instr {
|
||||
OpSel {
|
||||
dst: dst,
|
||||
cond: sel,
|
||||
srcs: [x, y],
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
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());
|
||||
OpPLop3 {
|
||||
|
|
@ -3406,80 +3313,6 @@ impl Instr {
|
|||
.into()
|
||||
}
|
||||
|
||||
pub fn new_ld(
|
||||
dst: Dst,
|
||||
access: MemAccess,
|
||||
addr: Src,
|
||||
offset: i32,
|
||||
) -> Instr {
|
||||
OpLd {
|
||||
dst: dst,
|
||||
addr: addr,
|
||||
offset: offset,
|
||||
access: access,
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn new_st(
|
||||
access: MemAccess,
|
||||
addr: Src,
|
||||
offset: i32,
|
||||
data: Src,
|
||||
) -> Instr {
|
||||
OpSt {
|
||||
addr: addr,
|
||||
data: data,
|
||||
offset: offset,
|
||||
access: access,
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn new_ald(dst: Dst, attr_addr: u16, vtx: Src, offset: Src) -> Instr {
|
||||
OpALd {
|
||||
dst: dst,
|
||||
vtx: vtx,
|
||||
offset: offset,
|
||||
access: AttrAccess {
|
||||
addr: attr_addr,
|
||||
comps: dst.as_ssa().unwrap().comps(),
|
||||
patch: false,
|
||||
out_load: false,
|
||||
flags: 0,
|
||||
},
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn new_ast(attr_addr: u16, data: Src, vtx: Src, offset: Src) -> Instr {
|
||||
OpASt {
|
||||
vtx: vtx,
|
||||
offset: offset,
|
||||
data: data,
|
||||
access: AttrAccess {
|
||||
addr: attr_addr,
|
||||
comps: data.src_ref.as_ssa().unwrap().comps(),
|
||||
patch: false,
|
||||
out_load: false,
|
||||
flags: 0,
|
||||
},
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn new_bra(block: u32) -> Instr {
|
||||
OpBra { target: block }.into()
|
||||
}
|
||||
|
||||
pub fn new_exit() -> Instr {
|
||||
OpExit {}.into()
|
||||
}
|
||||
|
||||
pub fn new_s2r(dst: Dst, idx: u8) -> Instr {
|
||||
OpS2R { dst: dst, idx: idx }.into()
|
||||
}
|
||||
|
||||
pub fn new_swap(x: RegRef, y: RegRef) -> Instr {
|
||||
assert!(x.file() == y.file());
|
||||
OpSwap {
|
||||
|
|
@ -3489,13 +3322,6 @@ impl Instr {
|
|||
.into()
|
||||
}
|
||||
|
||||
pub fn new_fs_out(srcs: &[Src]) -> Instr {
|
||||
OpFSOut {
|
||||
srcs: srcs.to_vec(),
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn dsts(&self) -> &[Dst] {
|
||||
self.op.dsts_as_slice()
|
||||
}
|
||||
|
|
@ -3626,6 +3452,25 @@ pub enum MappedInstrs {
|
|||
Many(Vec<Box<Instr>>),
|
||||
}
|
||||
|
||||
impl MappedInstrs {
|
||||
pub fn push(&mut self, i: Box<Instr>) {
|
||||
match self {
|
||||
MappedInstrs::None => {
|
||||
*self = MappedInstrs::One(i);
|
||||
}
|
||||
MappedInstrs::One(_) => {
|
||||
*self = match std::mem::replace(self, MappedInstrs::None) {
|
||||
MappedInstrs::One(o) => MappedInstrs::Many(vec![o, i]),
|
||||
_ => panic!("Not a One"),
|
||||
};
|
||||
}
|
||||
MappedInstrs::Many(v) => {
|
||||
v.push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BasicBlock {
|
||||
pub id: u32,
|
||||
pub instrs: Vec<Box<Instr>>,
|
||||
|
|
|
|||
|
|
@ -99,9 +99,8 @@ impl LopPass {
|
|||
_ => return,
|
||||
};
|
||||
|
||||
let entry = match self.ssa_lop.get(&ssa) {
|
||||
Some(e) => e,
|
||||
None => return,
|
||||
let Some(entry) = self.ssa_lop.get(&ssa) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let entry_use_count = *self.use_counts.get(&ssa).unwrap();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue