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

Commit 48a6b58

Browse files
committed
Emulate llvm.x86.sse2.pmovmskb.128 llvm intrinsic
1 parent 9cb787f commit 48a6b58

File tree

2 files changed

+71
-19
lines changed

2 files changed

+71
-19
lines changed

src/intrinsics.rs

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,50 @@ use crate::prelude::*;
22

33
use rustc::ty::subst::SubstsRef;
44

5-
macro_rules! intrinsic_pat {
5+
macro intrinsic_pat {
66
(_) => {
77
_
8-
};
8+
},
99
($name:ident) => {
1010
stringify!($name)
11+
},
12+
($name:literal) => {
13+
stringify!($name)
14+
},
15+
($x:ident . $($xs:tt).*) => {
16+
concat!(stringify!($x), ".", intrinsic_pat!($($xs).*))
1117
}
1218
}
1319

14-
macro_rules! intrinsic_arg {
20+
macro intrinsic_arg {
1521
(o $fx:expr, $arg:ident) => {
1622
$arg
17-
};
23+
},
1824
(c $fx:expr, $arg:ident) => {
1925
trans_operand($fx, $arg)
20-
};
26+
},
2127
(v $fx:expr, $arg:ident) => {
2228
trans_operand($fx, $arg).load_scalar($fx)
23-
};
29+
}
2430
}
2531

26-
macro_rules! intrinsic_substs {
27-
($substs:expr, $index:expr,) => {};
32+
macro intrinsic_substs {
33+
($substs:expr, $index:expr,) => {},
2834
($substs:expr, $index:expr, $first:ident $(,$rest:ident)*) => {
2935
let $first = $substs.type_at($index);
3036
intrinsic_substs!($substs, $index+1, $($rest),*);
31-
};
37+
}
3238
}
3339

34-
macro_rules! intrinsic_match {
35-
($fx:expr, $intrinsic:expr, $substs:expr, $args:expr, $(
36-
$($name:tt)|+ $(if $cond:expr)?, $(<$($subst:ident),*>)? ($($a:ident $arg:ident),*) $content:block;
40+
pub macro intrinsic_match {
41+
($fx:expr, $intrinsic:expr, $substs:expr, $args:expr,
42+
_ => $unknown:block;
43+
$(
44+
$($($name:tt).*)|+ $(if $cond:expr)?, $(<$($subst:ident),*>)? ($($a:ident $arg:ident),*) $content:block;
3745
)*) => {
3846
match $intrinsic {
3947
$(
40-
$(intrinsic_pat!($name))|* $(if $cond)? => {
48+
$(intrinsic_pat!($($name).*))|* $(if $cond)? => {
4149
#[allow(unused_parens, non_snake_case)]
4250
{
4351
$(
@@ -57,9 +65,9 @@ macro_rules! intrinsic_match {
5765
}
5866
}
5967
)*
60-
_ => unimpl!("unsupported intrinsic {}", $intrinsic),
68+
_ => $unknown,
6169
}
62-
};
70+
}
6371
}
6472

6573
macro_rules! call_intrinsic_match {
@@ -122,7 +130,7 @@ macro_rules! atomic_minmax {
122130
};
123131
}
124132

125-
fn lane_type_and_count<'tcx>(
133+
pub fn lane_type_and_count<'tcx>(
126134
fx: &FunctionCx<'_, 'tcx, impl Backend>,
127135
layout: TyLayout<'tcx>,
128136
intrinsic: &str,
@@ -282,6 +290,9 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>(
282290

283291
intrinsic_match! {
284292
fx, intrinsic, substs, args,
293+
_ => {
294+
unimpl!("unsupported intrinsic {}", intrinsic)
295+
};
285296

286297
assume, (c _a) {};
287298
likely | unlikely, (c a) {

src/llvm_intrinsics.rs

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,50 @@ pub fn codegen_llvm_intrinsic_call<'a, 'tcx: 'a>(
99
args: &[mir::Operand<'tcx>],
1010
destination: Option<(CPlace<'tcx>, BasicBlock)>,
1111
) {
12-
fx.tcx.sess.warn(&format!("unsupported llvm intrinsic {}; replacing with trap", intrinsic));
13-
crate::trap::trap_unimplemented(fx, intrinsic);
12+
let ret = match destination {
13+
Some((place, _)) => place,
14+
None => {
15+
// Insert non returning intrinsics here
16+
match intrinsic {
17+
"abort" => {
18+
trap_panic(fx, "Called intrinsic::abort.");
19+
}
20+
"unreachable" => {
21+
trap_unreachable(fx, "[corruption] Called intrinsic::unreachable.");
22+
}
23+
_ => unimplemented!("unsupported instrinsic {}", intrinsic),
24+
}
25+
return;
26+
}
27+
};
28+
29+
crate::intrinsics::intrinsic_match! {
30+
fx, intrinsic, substs, args,
31+
_ => {
32+
fx.tcx.sess.warn(&format!("unsupported llvm intrinsic {}; replacing with trap", intrinsic));
33+
crate::trap::trap_unimplemented(fx, intrinsic);
34+
};
35+
36+
// Used by _mm_movemask_epi8
37+
llvm.x86.sse2.pmovmskb.128, (c a) {
38+
let (lane_layout, lane_count) = crate::intrinsics::lane_type_and_count(fx, a.layout(), intrinsic);
39+
assert_eq!(lane_layout.ty.sty, fx.tcx.types.i8.sty);
40+
assert_eq!(lane_count, 16);
41+
42+
let mut res = fx.bcx.ins().iconst(types::I32, 0);
43+
44+
for lane in 0..16 {
45+
let a_lane = a.value_field(fx, mir::Field::new(lane.try_into().unwrap())).load_scalar(fx);
46+
let a_lane_sign = fx.bcx.ins().ushr_imm(a_lane, 7); // extract sign bit of 8bit int
47+
let a_lane_sign = fx.bcx.ins().uextend(types::I32, a_lane_sign);
48+
res = fx.bcx.ins().ishl_imm(res, 1);
49+
res = fx.bcx.ins().bor(res, a_lane_sign);
50+
}
51+
52+
let res = CValue::by_val(res, fx.layout_of(fx.tcx.types.i32));
53+
ret.write_cvalue(fx, res);
54+
};
55+
}
1456

1557
if let Some((_, dest)) = destination {
1658
let ret_ebb = fx.get_ebb(dest);
@@ -20,7 +62,6 @@ pub fn codegen_llvm_intrinsic_call<'a, 'tcx: 'a>(
2062
}
2163
}
2264

23-
// llvm.x86.sse2.pmovmskb.128
2465
// llvm.x86.avx2.vperm2i128
2566
// llvm.x86.ssse3.pshuf.b.128
2667
// llvm.x86.avx2.pshuf.b

0 commit comments

Comments
 (0)