Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix 5916 interpreter wrong for vall true #6708

Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion cranelift/filetests/filetests/runtests/simd-valltrue.clif
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ block0(v0: i8x16):
; run: %vall_true_i8x16([0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]) == 0
; run: %vall_true_i8x16([-1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]) == 0
; run: %vall_true_i8x16([-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1]) == 1

; run: %vall_true_i8x16(0xffffffffffffffffffffffffffffff00) == 0
; run: %vall_true_i8x16(0x00ffffffffffffffffffffffffffffff) == 0
; run: %vall_true_i8x16(0xffffffffffffff00ffffffffffffffff) == 0
; run: %vall_true_i8x16(0x01010101010101010101010101010101) == 1
; run: %vall_true_i8x16(0xffffffffffffffffffffffffffffffff) == 1
; run: %vall_true_i8x16(0xe66021830506f2fffdfebfc8c8c8c8c8) == 1

function %vall_true_i16x8(i16x8) -> i8 {
block0(v0: i16x8):
Expand Down Expand Up @@ -46,3 +51,4 @@ block0(v0: i64x2):
; run: %vall_true_i64x2([0 0]) == 0
; run: %vall_true_i64x2([-1 0]) == 0
; run: %vall_true_i64x2([-1 -1]) == 1
; run: %vall_true_i64x2([0xffffffff_00000000 -1]) == 1
17 changes: 9 additions & 8 deletions cranelift/interpreter/src/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1040,12 +1040,13 @@ where
let any = fold_vector(arg(0), ctrl_ty, init.clone(), |acc, lane| acc.or(lane))?;
assign(DataValue::bool(any != init, false, types::I8)?)
}
Opcode::VallTrue => {
let lane_ty = ctrl_ty.lane_type();
let init = DataValue::bool(true, true, lane_ty)?;
let all = fold_vector(arg(0), ctrl_ty, init.clone(), |acc, lane| acc.and(lane))?;
assign(DataValue::bool(all == init, false, types::I8)?)
}
Opcode::VallTrue => assign(DataValue::bool(
!(arg(0).iter_lanes(ctrl_ty)?.try_fold(false, |acc, lane| {
Ok::<bool, ValueError>(acc | lane.is_zero()?)
})?),
false,
types::I8,
)?),
Opcode::SwidenLow | Opcode::SwidenHigh | Opcode::UwidenLow | Opcode::UwidenHigh => {
let new_type = ctrl_ty.merge_lanes().unwrap();
let conv_type = match inst.opcode() {
Expand Down Expand Up @@ -1434,11 +1435,11 @@ fn fcmp(code: FloatCC, left: &DataValue, right: &DataValue) -> ValueResult<bool>
})
}

type SimdVec<DataValue> = SmallVec<[DataValue; 4]>;
pub type SimdVec<DataValue> = SmallVec<[DataValue; 4]>;

/// Converts a SIMD vector value into a Rust array of [Value] for processing.
/// If `x` is a scalar, it will be returned as a single-element array.
fn extractlanes(x: &DataValue, vector_type: types::Type) -> ValueResult<SimdVec<DataValue>> {
pub fn extractlanes(x: &DataValue, vector_type: types::Type) -> ValueResult<SimdVec<DataValue>> {
let lane_type = vector_type.lane_type();
let mut lanes = SimdVec::new();
// Wrap scalar values as a single-element vector and return.
Expand Down
99 changes: 98 additions & 1 deletion cranelift/interpreter/src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use cranelift_codegen::ir::immediates::{Ieee32, Ieee64};
use cranelift_codegen::ir::{types, Type};
use thiserror::Error;

use crate::step::{extractlanes, SimdVec};

pub type ValueResult<T> = Result<T, ValueError>;

pub trait DataValueExt: Sized {
Expand Down Expand Up @@ -89,6 +91,9 @@ pub trait DataValueExt: Sized {
fn trailing_zeros(self) -> ValueResult<Self>;
fn reverse_bits(self) -> ValueResult<Self>;
fn swap_bytes(self) -> ValueResult<Self>;

// An iterator over the lanes of a SIMD type
fn iter_lanes(&self, ty: Type) -> ValueResult<DataValueIterator>;
}

#[derive(Error, Debug, PartialEq)]
Expand Down Expand Up @@ -484,9 +489,15 @@ impl DataValueExt for DataValue {

fn is_zero(&self) -> ValueResult<bool> {
match self {
DataValue::I8(f) => Ok(*f == 0),
DataValue::I16(f) => Ok(*f == 0),
DataValue::I32(f) => Ok(*f == 0),
DataValue::I64(f) => Ok(*f == 0),
DataValue::I128(f) => Ok(*f == 0),
DataValue::F32(f) => Ok(f.is_zero()),
DataValue::F64(f) => Ok(f.is_zero()),
_ => Err(ValueError::InvalidType(ValueTypeClass::Float, self.ty())),
DataValue::V64(_) => Err(ValueError::InvalidType(ValueTypeClass::Float, self.ty())),
DataValue::V128(_) => Err(ValueError::InvalidType(ValueTypeClass::Float, self.ty())),
ms140569 marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down Expand Up @@ -808,4 +819,90 @@ impl DataValueExt for DataValue {
fn swap_bytes(self) -> ValueResult<Self> {
unary_match!(swap_bytes(&self); [I16, I32, I64, I128])
}

fn iter_lanes(&self, ty: Type) -> ValueResult<DataValueIterator> {
DataValueIterator::new(self, ty)
}
}

/// Iterator for DataValue's
pub struct DataValueIterator {
ty: Type,
v: SimdVec<DataValue>,
idx: usize,
}

impl DataValueIterator {
fn new(dv: &DataValue, ty: Type) -> Result<Self, ValueError> {
match extractlanes(dv, ty) {
Ok(v) => return Ok(Self { ty, v, idx: 0 }),
Err(err) => return Err(err),
}
}
}

impl Iterator for DataValueIterator {
type Item = DataValue;

fn next(&mut self) -> Option<Self::Item> {
if self.idx >= self.ty.lane_count() as usize {
return None;
}

let dv = self.v[self.idx].clone();
self.idx += 1;
Some(dv)
}
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn test_iterator_v128() {
let dv = DataValue::V128([99, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
assert_eq!(simd_sum(dv, types::I8X16), 219);
}

#[test]
fn test_iterator_v128_empty() {
let dv = DataValue::V128([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
assert_eq!(simd_sum(dv, types::I8X16), 0);
}

#[test]
fn test_iterator_v128_ones() {
let dv = DataValue::V128([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]);
assert_eq!(simd_sum(dv, types::I8X16), 16);
}

#[test]
fn test_iterator_v64_empty() {
let dv = DataValue::V64([0, 0, 0, 0, 0, 0, 0, 0]);
assert_eq!(simd_sum(dv, types::I8X8), 0);
}
#[test]
fn test_iterator_v64_ones() {
let dv = DataValue::V64([1, 1, 1, 1, 1, 1, 1, 1]);
assert_eq!(simd_sum(dv, types::I8X8), 8);
}
#[test]
fn test_iterator_v64() {
let dv = DataValue::V64([10, 20, 30, 40, 50, 60, 70, 80]);
assert_eq!(simd_sum(dv, types::I8X8), 360);
}

fn simd_sum(dv: DataValue, ty: types::Type) -> i128 {
let itr = dv.iter_lanes(ty).unwrap();

itr.map(|e| {
if let Some(v) = e.into_int_signed().ok() {
v
} else {
0
}
})
.sum()
}
}