cranelift-interpreter: Fix incorrect scalar_to_vector result (#6133)

* The `vectorizelanes` function performs a check to see whether there
is a single value provided in an array, and if so returns it as a
scalar.

While elsewhere in the interpreter this behaviour is relied
upon, it yields an incorrect result when attempting to convert a
scalar to a vector.

The original `vectorizelanes` remains untouched, however, an
unconditional variant `vectorizelanes_all` was added.

* A test was added under `filetests/runtests/issue5911.clif`.

Fixes #5911
This commit is contained in:
Jan-Justin van Tonder
2023-04-04 14:14:16 +02:00
committed by GitHub
parent c85bf27ff8
commit c475735f5e
3 changed files with 22 additions and 9 deletions

View File

@@ -934,14 +934,15 @@ where
Opcode::Bitcast | Opcode::ScalarToVector => {
let input_ty = inst_context.type_of(inst_context.args()[0]).unwrap();
let arg0 = extractlanes(&arg(0)?, input_ty)?;
assign(vectorizelanes(
&arg0
.into_iter()
.map(|x| V::convert(x, ValueConversionKind::Exact(ctrl_ty.lane_type())))
.collect::<ValueResult<SimdVec<V>>>()?,
ctrl_ty,
)?)
let lanes = &arg0
.into_iter()
.map(|x| V::convert(x, ValueConversionKind::Exact(ctrl_ty.lane_type())))
.collect::<ValueResult<SimdVec<V>>>()?;
assign(match inst.opcode() {
Opcode::Bitcast => vectorizelanes(lanes, ctrl_ty)?,
Opcode::ScalarToVector => vectorizelanes_all(lanes, ctrl_ty)?,
_ => unreachable!(),
})
}
Opcode::Ireduce => assign(Value::convert(
arg(0)?,
@@ -1552,9 +1553,17 @@ where
{
// If the array is only one element, return it as a scalar.
if x.len() == 1 {
return Ok(x[0].clone());
Ok(x[0].clone())
} else {
vectorizelanes_all(x, vector_type)
}
}
/// Convert a Rust array of [Value] back into a `Value::vector`.
fn vectorizelanes_all<V>(x: &[V], vector_type: types::Type) -> ValueResult<V>
where
V: Value,
{
let lane_type = vector_type.lane_type();
let iterations = match lane_type {
types::I8 => 1,