Fix simd_cast
This commit is contained in:
parent
aa803f4fa6
commit
b806070a88
@ -68,6 +68,7 @@ unsafe fn test_simd() {
|
||||
test_mm256_movemask_epi8();
|
||||
test_mm_add_epi8();
|
||||
test_mm_add_pd();
|
||||
test_mm_cvtepi8_epi16();
|
||||
|
||||
let mask1 = _mm_movemask_epi8(dbg!(_mm_setr_epi8(255u8 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)));
|
||||
assert_eq!(mask1, 1);
|
||||
@ -170,6 +171,18 @@ pub unsafe fn assert_eq_m128d(a: __m128d, b: __m128d) {
|
||||
}
|
||||
}
|
||||
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
unsafe fn test_mm_cvtepi8_epi16() {
|
||||
let a = _mm_set1_epi8(10);
|
||||
let r = _mm_cvtepi8_epi16(a);
|
||||
let e = _mm_set1_epi16(10);
|
||||
assert_eq_m128i(r, e);
|
||||
let a = _mm_set1_epi8(-10);
|
||||
let r = _mm_cvtepi8_epi16(a);
|
||||
let e = _mm_set1_epi16(-10);
|
||||
assert_eq_m128i(r, e);
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum LoopState {
|
||||
Continue(()),
|
||||
|
39
src/base.rs
39
src/base.rs
@ -436,7 +436,6 @@ fn trans_stmt<'a, 'tcx: 'a>(
|
||||
let discr = trans_get_discriminant(fx, place, fx.layout_of(to_ty));
|
||||
lval.write_cvalue(fx, discr);
|
||||
} else {
|
||||
let from_clif_ty = fx.clif_type(from_ty).unwrap();
|
||||
let to_clif_ty = fx.clif_type(to_ty).unwrap();
|
||||
let from = operand.load_scalar(fx);
|
||||
|
||||
@ -447,43 +446,7 @@ fn trans_stmt<'a, 'tcx: 'a>(
|
||||
_ => panic!("{}", from_ty),
|
||||
};
|
||||
|
||||
let res = if from_clif_ty.is_int() && to_clif_ty.is_int() {
|
||||
// int-like -> int-like
|
||||
crate::common::clif_intcast(
|
||||
fx,
|
||||
from,
|
||||
to_clif_ty,
|
||||
signed,
|
||||
)
|
||||
} else if from_clif_ty.is_int() && to_clif_ty.is_float() {
|
||||
// int-like -> float
|
||||
if signed {
|
||||
fx.bcx.ins().fcvt_from_sint(to_clif_ty, from)
|
||||
} else {
|
||||
fx.bcx.ins().fcvt_from_uint(to_clif_ty, from)
|
||||
}
|
||||
} else if from_clif_ty.is_float() && to_clif_ty.is_int() {
|
||||
// float -> int-like
|
||||
let from = operand.load_scalar(fx);
|
||||
if signed {
|
||||
fx.bcx.ins().fcvt_to_sint_sat(to_clif_ty, from)
|
||||
} else {
|
||||
fx.bcx.ins().fcvt_to_uint_sat(to_clif_ty, from)
|
||||
}
|
||||
} else if from_clif_ty.is_float() && to_clif_ty.is_float() {
|
||||
// float -> float
|
||||
match (from_clif_ty, to_clif_ty) {
|
||||
(types::F32, types::F64) => {
|
||||
fx.bcx.ins().fpromote(types::F64, from)
|
||||
}
|
||||
(types::F64, types::F32) => {
|
||||
fx.bcx.ins().fdemote(types::F32, from)
|
||||
}
|
||||
_ => from,
|
||||
}
|
||||
} else {
|
||||
unimpl!("rval misc {:?} {:?}", from_ty, to_ty)
|
||||
};
|
||||
let res = clif_int_or_float_cast(fx, from, to_clif_ty, signed);
|
||||
lval.write_cvalue(fx, CValue::by_val(res, dest_layout));
|
||||
}
|
||||
}
|
||||
|
93
src/cast.rs
Normal file
93
src/cast.rs
Normal file
@ -0,0 +1,93 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
pub fn clif_intcast<'a, 'tcx: 'a>(
|
||||
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
||||
val: Value,
|
||||
to: Type,
|
||||
signed: bool,
|
||||
) -> Value {
|
||||
let from = fx.bcx.func.dfg.value_type(val);
|
||||
match (from, to) {
|
||||
// equal
|
||||
(_, _) if from == to => val,
|
||||
|
||||
// extend
|
||||
(_, types::I128) => {
|
||||
let wider = if from == types::I64 {
|
||||
val
|
||||
} else if signed {
|
||||
fx.bcx.ins().sextend(types::I64, val)
|
||||
} else {
|
||||
fx.bcx.ins().uextend(types::I64, val)
|
||||
};
|
||||
let zero = fx.bcx.ins().iconst(types::I64, 0);
|
||||
fx.bcx.ins().iconcat(wider, zero)
|
||||
}
|
||||
(_, _) if to.wider_or_equal(from) => {
|
||||
if signed {
|
||||
fx.bcx.ins().sextend(to, val)
|
||||
} else {
|
||||
fx.bcx.ins().uextend(to, val)
|
||||
}
|
||||
}
|
||||
|
||||
// reduce
|
||||
(types::I128, _) => {
|
||||
let (lsb, _msb) = fx.bcx.ins().isplit(val);
|
||||
if to == types::I64 {
|
||||
lsb
|
||||
} else {
|
||||
fx.bcx.ins().ireduce(to, lsb)
|
||||
}
|
||||
}
|
||||
(_, _) => {
|
||||
fx.bcx.ins().ireduce(to, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clif_int_or_float_cast(
|
||||
fx: &mut FunctionCx<'_, '_, impl Backend>,
|
||||
from: Value,
|
||||
to_ty: Type,
|
||||
signed: bool,
|
||||
) -> Value {
|
||||
let from_ty = fx.bcx.func.dfg.value_type(from);
|
||||
|
||||
if from_ty.is_int() && to_ty.is_int() {
|
||||
// int-like -> int-like
|
||||
clif_intcast(
|
||||
fx,
|
||||
from,
|
||||
to_ty,
|
||||
signed,
|
||||
)
|
||||
} else if from_ty.is_int() && to_ty.is_float() {
|
||||
// int-like -> float
|
||||
if signed {
|
||||
fx.bcx.ins().fcvt_from_sint(to_ty, from)
|
||||
} else {
|
||||
fx.bcx.ins().fcvt_from_uint(to_ty, from)
|
||||
}
|
||||
} else if from_ty.is_float() && to_ty.is_int() {
|
||||
// float -> int-like
|
||||
if signed {
|
||||
fx.bcx.ins().fcvt_to_sint_sat(to_ty, from)
|
||||
} else {
|
||||
fx.bcx.ins().fcvt_to_uint_sat(to_ty, from)
|
||||
}
|
||||
} else if from_ty.is_float() && to_ty.is_float() {
|
||||
// float -> float
|
||||
match (from_ty, to_ty) {
|
||||
(types::F32, types::F64) => {
|
||||
fx.bcx.ins().fpromote(types::F64, from)
|
||||
}
|
||||
(types::F64, types::F32) => {
|
||||
fx.bcx.ins().fdemote(types::F32, from)
|
||||
}
|
||||
_ => from,
|
||||
}
|
||||
} else {
|
||||
unreachable!("cast value from {:?} to {:?}", from_ty, to_ty);
|
||||
}
|
||||
}
|
@ -73,52 +73,6 @@ pub fn codegen_select(bcx: &mut FunctionBuilder, cond: Value, lhs: Value, rhs: V
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clif_intcast<'a, 'tcx: 'a>(
|
||||
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
||||
val: Value,
|
||||
to: Type,
|
||||
signed: bool,
|
||||
) -> Value {
|
||||
let from = fx.bcx.func.dfg.value_type(val);
|
||||
match (from, to) {
|
||||
// equal
|
||||
(_, _) if from == to => val,
|
||||
|
||||
// extend
|
||||
(_, types::I128) => {
|
||||
let wider = if from == types::I64 {
|
||||
val
|
||||
} else if signed {
|
||||
fx.bcx.ins().sextend(types::I64, val)
|
||||
} else {
|
||||
fx.bcx.ins().uextend(types::I64, val)
|
||||
};
|
||||
let zero = fx.bcx.ins().iconst(types::I64, 0);
|
||||
fx.bcx.ins().iconcat(wider, zero)
|
||||
}
|
||||
(_, _) if to.wider_or_equal(from) => {
|
||||
if signed {
|
||||
fx.bcx.ins().sextend(to, val)
|
||||
} else {
|
||||
fx.bcx.ins().uextend(to, val)
|
||||
}
|
||||
}
|
||||
|
||||
// reduce
|
||||
(types::I128, _) => {
|
||||
let (lsb, _msb) = fx.bcx.ins().isplit(val);
|
||||
if to == types::I64 {
|
||||
lsb
|
||||
} else {
|
||||
fx.bcx.ins().ireduce(to, lsb)
|
||||
}
|
||||
}
|
||||
(_, _) => {
|
||||
fx.bcx.ins().ireduce(to, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_normal_value_imm(func: &Function, val: Value) -> Option<i64> {
|
||||
if let ValueDef::Result(inst, 0 /*param*/) = func.dfg.value_def(val) {
|
||||
if let InstructionData::UnaryImm {
|
||||
|
@ -853,8 +853,27 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>(
|
||||
ret.write_cvalue(fx, val);
|
||||
};
|
||||
|
||||
simd_cast, (c x) {
|
||||
ret.write_cvalue(fx, x.unchecked_cast_to(ret.layout()));
|
||||
simd_cast, (c a) {
|
||||
let (lane_layout, lane_count) = lane_type_and_count(fx, a.layout(), intrinsic);
|
||||
let (ret_lane_layout, ret_lane_count) = lane_type_and_count(fx, ret.layout(), intrinsic);
|
||||
assert_eq!(lane_count, ret_lane_count);
|
||||
|
||||
let ret_lane_ty = fx.clif_type(ret_lane_layout.ty).unwrap();
|
||||
|
||||
let signed = match lane_layout.ty.sty {
|
||||
ty::Uint(..) => false,
|
||||
ty::Int(..) => true,
|
||||
ty::Float(..) => false, // `signed` is unused for floats
|
||||
_ => panic!("{}", lane_layout.ty),
|
||||
};
|
||||
|
||||
for lane in 0..lane_count {
|
||||
let lane = mir::Field::new(lane.try_into().unwrap());
|
||||
|
||||
let a_lane = a.value_field(fx, lane).load_scalar(fx);
|
||||
let res = clif_int_or_float_cast(fx, a_lane, ret_lane_ty, signed);
|
||||
ret.place_field(fx, lane).write_cvalue(fx, CValue::by_val(res, ret_lane_layout));
|
||||
}
|
||||
};
|
||||
|
||||
simd_eq, (c x, c y) {
|
||||
|
@ -33,6 +33,7 @@ mod allocator;
|
||||
mod analyze;
|
||||
mod archive;
|
||||
mod base;
|
||||
mod cast;
|
||||
mod codegen_i128;
|
||||
mod common;
|
||||
mod constant;
|
||||
@ -94,6 +95,7 @@ mod prelude {
|
||||
|
||||
pub use crate::abi::*;
|
||||
pub use crate::base::{trans_operand, trans_place};
|
||||
pub use crate::cast::*;
|
||||
pub use crate::common::*;
|
||||
pub use crate::debuginfo::{DebugContext, FunctionDebugContext};
|
||||
pub use crate::trap::*;
|
||||
|
Loading…
x
Reference in New Issue
Block a user