Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit b806070

Browse files
committed
Fix simd_cast
1 parent aa803f4 commit b806070

File tree

6 files changed

+130
-86
lines changed

6 files changed

+130
-86
lines changed

example/std_example.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ unsafe fn test_simd() {
6868
test_mm256_movemask_epi8();
6969
test_mm_add_epi8();
7070
test_mm_add_pd();
71+
test_mm_cvtepi8_epi16();
7172

7273
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)));
7374
assert_eq!(mask1, 1);
@@ -170,6 +171,18 @@ pub unsafe fn assert_eq_m128d(a: __m128d, b: __m128d) {
170171
}
171172
}
172173

174+
#[target_feature(enable = "sse4.1")]
175+
unsafe fn test_mm_cvtepi8_epi16() {
176+
let a = _mm_set1_epi8(10);
177+
let r = _mm_cvtepi8_epi16(a);
178+
let e = _mm_set1_epi16(10);
179+
assert_eq_m128i(r, e);
180+
let a = _mm_set1_epi8(-10);
181+
let r = _mm_cvtepi8_epi16(a);
182+
let e = _mm_set1_epi16(-10);
183+
assert_eq_m128i(r, e);
184+
}
185+
173186
#[derive(PartialEq)]
174187
enum LoopState {
175188
Continue(()),

src/base.rs

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,6 @@ fn trans_stmt<'a, 'tcx: 'a>(
436436
let discr = trans_get_discriminant(fx, place, fx.layout_of(to_ty));
437437
lval.write_cvalue(fx, discr);
438438
} else {
439-
let from_clif_ty = fx.clif_type(from_ty).unwrap();
440439
let to_clif_ty = fx.clif_type(to_ty).unwrap();
441440
let from = operand.load_scalar(fx);
442441

@@ -447,43 +446,7 @@ fn trans_stmt<'a, 'tcx: 'a>(
447446
_ => panic!("{}", from_ty),
448447
};
449448

450-
let res = if from_clif_ty.is_int() && to_clif_ty.is_int() {
451-
// int-like -> int-like
452-
crate::common::clif_intcast(
453-
fx,
454-
from,
455-
to_clif_ty,
456-
signed,
457-
)
458-
} else if from_clif_ty.is_int() && to_clif_ty.is_float() {
459-
// int-like -> float
460-
if signed {
461-
fx.bcx.ins().fcvt_from_sint(to_clif_ty, from)
462-
} else {
463-
fx.bcx.ins().fcvt_from_uint(to_clif_ty, from)
464-
}
465-
} else if from_clif_ty.is_float() && to_clif_ty.is_int() {
466-
// float -> int-like
467-
let from = operand.load_scalar(fx);
468-
if signed {
469-
fx.bcx.ins().fcvt_to_sint_sat(to_clif_ty, from)
470-
} else {
471-
fx.bcx.ins().fcvt_to_uint_sat(to_clif_ty, from)
472-
}
473-
} else if from_clif_ty.is_float() && to_clif_ty.is_float() {
474-
// float -> float
475-
match (from_clif_ty, to_clif_ty) {
476-
(types::F32, types::F64) => {
477-
fx.bcx.ins().fpromote(types::F64, from)
478-
}
479-
(types::F64, types::F32) => {
480-
fx.bcx.ins().fdemote(types::F32, from)
481-
}
482-
_ => from,
483-
}
484-
} else {
485-
unimpl!("rval misc {:?} {:?}", from_ty, to_ty)
486-
};
449+
let res = clif_int_or_float_cast(fx, from, to_clif_ty, signed);
487450
lval.write_cvalue(fx, CValue::by_val(res, dest_layout));
488451
}
489452
}

src/cast.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
use crate::prelude::*;
2+
3+
pub fn clif_intcast<'a, 'tcx: 'a>(
4+
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
5+
val: Value,
6+
to: Type,
7+
signed: bool,
8+
) -> Value {
9+
let from = fx.bcx.func.dfg.value_type(val);
10+
match (from, to) {
11+
// equal
12+
(_, _) if from == to => val,
13+
14+
// extend
15+
(_, types::I128) => {
16+
let wider = if from == types::I64 {
17+
val
18+
} else if signed {
19+
fx.bcx.ins().sextend(types::I64, val)
20+
} else {
21+
fx.bcx.ins().uextend(types::I64, val)
22+
};
23+
let zero = fx.bcx.ins().iconst(types::I64, 0);
24+
fx.bcx.ins().iconcat(wider, zero)
25+
}
26+
(_, _) if to.wider_or_equal(from) => {
27+
if signed {
28+
fx.bcx.ins().sextend(to, val)
29+
} else {
30+
fx.bcx.ins().uextend(to, val)
31+
}
32+
}
33+
34+
// reduce
35+
(types::I128, _) => {
36+
let (lsb, _msb) = fx.bcx.ins().isplit(val);
37+
if to == types::I64 {
38+
lsb
39+
} else {
40+
fx.bcx.ins().ireduce(to, lsb)
41+
}
42+
}
43+
(_, _) => {
44+
fx.bcx.ins().ireduce(to, val)
45+
}
46+
}
47+
}
48+
49+
pub fn clif_int_or_float_cast(
50+
fx: &mut FunctionCx<'_, '_, impl Backend>,
51+
from: Value,
52+
to_ty: Type,
53+
signed: bool,
54+
) -> Value {
55+
let from_ty = fx.bcx.func.dfg.value_type(from);
56+
57+
if from_ty.is_int() && to_ty.is_int() {
58+
// int-like -> int-like
59+
clif_intcast(
60+
fx,
61+
from,
62+
to_ty,
63+
signed,
64+
)
65+
} else if from_ty.is_int() && to_ty.is_float() {
66+
// int-like -> float
67+
if signed {
68+
fx.bcx.ins().fcvt_from_sint(to_ty, from)
69+
} else {
70+
fx.bcx.ins().fcvt_from_uint(to_ty, from)
71+
}
72+
} else if from_ty.is_float() && to_ty.is_int() {
73+
// float -> int-like
74+
if signed {
75+
fx.bcx.ins().fcvt_to_sint_sat(to_ty, from)
76+
} else {
77+
fx.bcx.ins().fcvt_to_uint_sat(to_ty, from)
78+
}
79+
} else if from_ty.is_float() && to_ty.is_float() {
80+
// float -> float
81+
match (from_ty, to_ty) {
82+
(types::F32, types::F64) => {
83+
fx.bcx.ins().fpromote(types::F64, from)
84+
}
85+
(types::F64, types::F32) => {
86+
fx.bcx.ins().fdemote(types::F32, from)
87+
}
88+
_ => from,
89+
}
90+
} else {
91+
unreachable!("cast value from {:?} to {:?}", from_ty, to_ty);
92+
}
93+
}

src/common.rs

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -73,52 +73,6 @@ pub fn codegen_select(bcx: &mut FunctionBuilder, cond: Value, lhs: Value, rhs: V
7373
}
7474
}
7575

76-
pub fn clif_intcast<'a, 'tcx: 'a>(
77-
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
78-
val: Value,
79-
to: Type,
80-
signed: bool,
81-
) -> Value {
82-
let from = fx.bcx.func.dfg.value_type(val);
83-
match (from, to) {
84-
// equal
85-
(_, _) if from == to => val,
86-
87-
// extend
88-
(_, types::I128) => {
89-
let wider = if from == types::I64 {
90-
val
91-
} else if signed {
92-
fx.bcx.ins().sextend(types::I64, val)
93-
} else {
94-
fx.bcx.ins().uextend(types::I64, val)
95-
};
96-
let zero = fx.bcx.ins().iconst(types::I64, 0);
97-
fx.bcx.ins().iconcat(wider, zero)
98-
}
99-
(_, _) if to.wider_or_equal(from) => {
100-
if signed {
101-
fx.bcx.ins().sextend(to, val)
102-
} else {
103-
fx.bcx.ins().uextend(to, val)
104-
}
105-
}
106-
107-
// reduce
108-
(types::I128, _) => {
109-
let (lsb, _msb) = fx.bcx.ins().isplit(val);
110-
if to == types::I64 {
111-
lsb
112-
} else {
113-
fx.bcx.ins().ireduce(to, lsb)
114-
}
115-
}
116-
(_, _) => {
117-
fx.bcx.ins().ireduce(to, val)
118-
}
119-
}
120-
}
121-
12276
fn resolve_normal_value_imm(func: &Function, val: Value) -> Option<i64> {
12377
if let ValueDef::Result(inst, 0 /*param*/) = func.dfg.value_def(val) {
12478
if let InstructionData::UnaryImm {

src/intrinsics.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -853,8 +853,27 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>(
853853
ret.write_cvalue(fx, val);
854854
};
855855

856-
simd_cast, (c x) {
857-
ret.write_cvalue(fx, x.unchecked_cast_to(ret.layout()));
856+
simd_cast, (c a) {
857+
let (lane_layout, lane_count) = lane_type_and_count(fx, a.layout(), intrinsic);
858+
let (ret_lane_layout, ret_lane_count) = lane_type_and_count(fx, ret.layout(), intrinsic);
859+
assert_eq!(lane_count, ret_lane_count);
860+
861+
let ret_lane_ty = fx.clif_type(ret_lane_layout.ty).unwrap();
862+
863+
let signed = match lane_layout.ty.sty {
864+
ty::Uint(..) => false,
865+
ty::Int(..) => true,
866+
ty::Float(..) => false, // `signed` is unused for floats
867+
_ => panic!("{}", lane_layout.ty),
868+
};
869+
870+
for lane in 0..lane_count {
871+
let lane = mir::Field::new(lane.try_into().unwrap());
872+
873+
let a_lane = a.value_field(fx, lane).load_scalar(fx);
874+
let res = clif_int_or_float_cast(fx, a_lane, ret_lane_ty, signed);
875+
ret.place_field(fx, lane).write_cvalue(fx, CValue::by_val(res, ret_lane_layout));
876+
}
858877
};
859878

860879
simd_eq, (c x, c y) {

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ mod allocator;
3333
mod analyze;
3434
mod archive;
3535
mod base;
36+
mod cast;
3637
mod codegen_i128;
3738
mod common;
3839
mod constant;
@@ -94,6 +95,7 @@ mod prelude {
9495

9596
pub use crate::abi::*;
9697
pub use crate::base::{trans_operand, trans_place};
98+
pub use crate::cast::*;
9799
pub use crate::common::*;
98100
pub use crate::debuginfo::{DebugContext, FunctionDebugContext};
99101
pub use crate::trap::*;

0 commit comments

Comments
 (0)