diff --git a/cranelift/codegen/src/ir/types.rs b/cranelift/codegen/src/ir/types.rs index 2d9c7e709e..709c5bb08d 100644 --- a/cranelift/codegen/src/ir/types.rs +++ b/cranelift/codegen/src/ir/types.rs @@ -80,23 +80,24 @@ impl Type { } /// Get the (minimum, maximum) values represented by each lane in the type. - pub fn bounds(self, signed: bool) -> (i128, i128) { + /// Note that these are returned as unsigned 'bit patterns'. + pub fn bounds(self, signed: bool) -> (u128, u128) { if signed { match self.lane_type() { - I8 => (i8::MIN as i128, i8::MAX as i128), - I16 => (i16::MIN as i128, i16::MAX as i128), - I32 => (i32::MIN as i128, i32::MAX as i128), - I64 => (i64::MIN as i128, i64::MAX as i128), - I128 => (i128::MIN, i128::MAX), + I8 => (i8::MIN as u128, i8::MAX as u128), + I16 => (i16::MIN as u128, i16::MAX as u128), + I32 => (i32::MIN as u128, i32::MAX as u128), + I64 => (i64::MIN as u128, i64::MAX as u128), + I128 => (i128::MIN as u128, i128::MAX as u128), _ => unimplemented!(), } } else { match self.lane_type() { - I8 => (u8::MIN as i128, u8::MAX as i128), - I16 => (u16::MIN as i128, u16::MAX as i128), - I32 => (u32::MIN as i128, u32::MAX as i128), - I64 => (u64::MIN as i128, u64::MAX as i128), - I128 => (u128::MIN as i128, u128::MAX as i128), + I8 => (u8::MIN as u128, u8::MAX as u128), + I16 => (u16::MIN as u128, u16::MAX as u128), + I32 => (u32::MIN as u128, u32::MAX as u128), + I64 => (u64::MIN as u128, u64::MAX as u128), + I128 => (u128::MIN, u128::MAX), _ => unimplemented!(), } } diff --git a/cranelift/interpreter/src/step.rs b/cranelift/interpreter/src/step.rs index 6a86eb1cb6..31f85a8bdc 100644 --- a/cranelift/interpreter/src/step.rs +++ b/cranelift/interpreter/src/step.rs @@ -782,16 +782,15 @@ where Opcode::Snarrow | Opcode::Unarrow | Opcode::Uunarrow => { let arg0 = extractlanes(&arg(0)?, ctrl_ty.lane_type())?; let arg1 = extractlanes(&arg(1)?, ctrl_ty.lane_type())?; - let mut new_vec = SimdVec::new(); let new_type = ctrl_ty.split_lanes().unwrap(); let (min, max) = new_type.bounds(inst.opcode() == Opcode::Snarrow); - let mut min: V = Value::int(min, ctrl_ty.lane_type())?; - let mut max: V = Value::int(max, ctrl_ty.lane_type())?; + let mut min: V = Value::int(min as i128, ctrl_ty.lane_type())?; + let mut max: V = Value::int(max as i128, ctrl_ty.lane_type())?; if inst.opcode() == Opcode::Uunarrow { min = min.convert(ValueConversionKind::ToUnsigned)?; max = max.convert(ValueConversionKind::ToUnsigned)?; } - for mut lane in arg0.into_iter().chain(arg1) { + let narrow = |mut lane: V| -> ValueResult { if inst.opcode() == Opcode::Uunarrow { lane = lane.convert(ValueConversionKind::ToUnsigned)?; } @@ -801,8 +800,13 @@ where if inst.opcode() == Opcode::Unarrow || inst.opcode() == Opcode::Uunarrow { lane = lane.convert(ValueConversionKind::ToUnsigned)?; } - new_vec.push(lane); - } + Ok(lane) + }; + let new_vec = arg0 + .into_iter() + .chain(arg1) + .map(|lane| narrow(lane)) + .collect::>>()?; assign(vectorizelanes(&new_vec, new_type)?) } Opcode::Sextend => assign(Value::convert(