nak: Implement Foldable for OpShf

Also add an assert for an invalid combination on Maxwell.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30275>
This commit is contained in:
Faith Ekstrand
2024-07-19 18:06:51 -05:00
committed by Marge Bot
parent ebc1c052ab
commit 9321a785cf
2 changed files with 85 additions and 2 deletions

View File

@@ -566,6 +566,40 @@ fn test_op_iadd3x() {
}
}
#[test]
fn test_op_shf() {
let sm = &RunSingleton::get().sm;
let types = [IntType::U32, IntType::I32, IntType::U64, IntType::I64];
for i in 0..32 {
let op = OpShf {
dst: Dst::None,
low: 0.into(),
high: 0.into(),
shift: 0.into(),
data_type: types[i & 0x3],
right: i & 0x4 != 0,
wrap: i & 0x8 != 0,
dst_high: i & 0x10 != 0,
};
if sm.sm() < 70 && !(op.dst_high || op.right) {
continue;
}
let shift_idx = op.src_idx(&op.shift);
let mut a = Acorn::new();
test_foldable_op_with(op, &mut |i| {
if i == shift_idx {
a.get_uint(6) as u32
} else {
a.get_u32()
}
});
}
}
#[test]
fn test_op_prmt() {
let op = OpPrmt {

View File

@@ -2071,7 +2071,7 @@ impl fmt::Display for ImageDim {
}
}
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum IntType {
U8,
I8,
@@ -3616,7 +3616,7 @@ impl fmt::Display for ShflOp {
}
#[repr(C)]
#[derive(SrcsAsSlice, DstsAsSlice)]
#[derive(Clone, SrcsAsSlice, DstsAsSlice)]
pub struct OpShf {
#[dst_type(GPR)]
pub dst: Dst,
@@ -3636,6 +3636,55 @@ pub struct OpShf {
pub dst_high: bool,
}
impl Foldable for OpShf {
fn fold(&self, sm: &dyn ShaderModel, f: &mut OpFoldData<'_>) {
let low = f.get_u32_src(self, &self.low);
let high = f.get_u32_src(self, &self.high);
let shift = f.get_u32_src(self, &self.shift);
let bits: u32 = self.data_type.bits().try_into().unwrap();
let shift = if self.wrap {
shift & (bits - 1)
} else {
min(shift, bits)
};
let x = u64::from(low) | (u64::from(high) << 32);
let shifted = if sm.sm() < 70
&& self.dst_high
&& self.data_type != IntType::I64
{
if self.right {
x.checked_shr(shift).unwrap_or(0) as u64
} else {
x.checked_shl(shift).unwrap_or(0) as u64
}
} else if self.data_type.is_signed() {
if self.right {
(x as i64).checked_shr(shift).unwrap_or(0) as u64
} else {
(x as i64).checked_shl(shift).unwrap_or(0) as u64
}
} else {
if self.right {
x.checked_shr(shift).unwrap_or(0) as u64
} else {
x.checked_shl(shift).unwrap_or(0) as u64
}
};
let dst = if sm.sm() < 70 && !self.right {
(shifted >> 32) as u32
} else if self.dst_high {
(shifted >> 32) as u32
} else {
shifted as u32
};
f.set_u32_dst(self, &self.dst, dst);
}
}
impl DisplayOp for OpShf {
fn fmt_op(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "shf")?;