Emulate llvm.x86.sse2.pmovmskb.128 llvm intrinsic

This commit is contained in:
bjorn3 2019-07-29 12:43:24 +02:00
parent 9cb787fe70
commit 48a6b581b5
2 changed files with 71 additions and 19 deletions

View File

@ -2,42 +2,50 @@ use crate::prelude::*;
use rustc::ty::subst::SubstsRef;
macro_rules! intrinsic_pat {
macro intrinsic_pat {
(_) => {
_
};
},
($name:ident) => {
stringify!($name)
},
($name:literal) => {
stringify!($name)
},
($x:ident . $($xs:tt).*) => {
concat!(stringify!($x), ".", intrinsic_pat!($($xs).*))
}
}
macro_rules! intrinsic_arg {
macro intrinsic_arg {
(o $fx:expr, $arg:ident) => {
$arg
};
},
(c $fx:expr, $arg:ident) => {
trans_operand($fx, $arg)
};
},
(v $fx:expr, $arg:ident) => {
trans_operand($fx, $arg).load_scalar($fx)
};
}
}
macro_rules! intrinsic_substs {
($substs:expr, $index:expr,) => {};
macro intrinsic_substs {
($substs:expr, $index:expr,) => {},
($substs:expr, $index:expr, $first:ident $(,$rest:ident)*) => {
let $first = $substs.type_at($index);
intrinsic_substs!($substs, $index+1, $($rest),*);
};
}
}
macro_rules! intrinsic_match {
($fx:expr, $intrinsic:expr, $substs:expr, $args:expr, $(
$($name:tt)|+ $(if $cond:expr)?, $(<$($subst:ident),*>)? ($($a:ident $arg:ident),*) $content:block;
pub macro intrinsic_match {
($fx:expr, $intrinsic:expr, $substs:expr, $args:expr,
_ => $unknown:block;
$(
$($($name:tt).*)|+ $(if $cond:expr)?, $(<$($subst:ident),*>)? ($($a:ident $arg:ident),*) $content:block;
)*) => {
match $intrinsic {
$(
$(intrinsic_pat!($name))|* $(if $cond)? => {
$(intrinsic_pat!($($name).*))|* $(if $cond)? => {
#[allow(unused_parens, non_snake_case)]
{
$(
@ -57,9 +65,9 @@ macro_rules! intrinsic_match {
}
}
)*
_ => unimpl!("unsupported intrinsic {}", $intrinsic),
_ => $unknown,
}
};
}
}
macro_rules! call_intrinsic_match {
@ -122,7 +130,7 @@ macro_rules! atomic_minmax {
};
}
fn lane_type_and_count<'tcx>(
pub fn lane_type_and_count<'tcx>(
fx: &FunctionCx<'_, 'tcx, impl Backend>,
layout: TyLayout<'tcx>,
intrinsic: &str,
@ -282,6 +290,9 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>(
intrinsic_match! {
fx, intrinsic, substs, args,
_ => {
unimpl!("unsupported intrinsic {}", intrinsic)
};
assume, (c _a) {};
likely | unlikely, (c a) {

View File

@ -9,8 +9,50 @@ pub fn codegen_llvm_intrinsic_call<'a, 'tcx: 'a>(
args: &[mir::Operand<'tcx>],
destination: Option<(CPlace<'tcx>, BasicBlock)>,
) {
fx.tcx.sess.warn(&format!("unsupported llvm intrinsic {}; replacing with trap", intrinsic));
crate::trap::trap_unimplemented(fx, intrinsic);
let ret = match destination {
Some((place, _)) => place,
None => {
// Insert non returning intrinsics here
match intrinsic {
"abort" => {
trap_panic(fx, "Called intrinsic::abort.");
}
"unreachable" => {
trap_unreachable(fx, "[corruption] Called intrinsic::unreachable.");
}
_ => unimplemented!("unsupported instrinsic {}", intrinsic),
}
return;
}
};
crate::intrinsics::intrinsic_match! {
fx, intrinsic, substs, args,
_ => {
fx.tcx.sess.warn(&format!("unsupported llvm intrinsic {}; replacing with trap", intrinsic));
crate::trap::trap_unimplemented(fx, intrinsic);
};
// Used by _mm_movemask_epi8
llvm.x86.sse2.pmovmskb.128, (c a) {
let (lane_layout, lane_count) = crate::intrinsics::lane_type_and_count(fx, a.layout(), intrinsic);
assert_eq!(lane_layout.ty.sty, fx.tcx.types.i8.sty);
assert_eq!(lane_count, 16);
let mut res = fx.bcx.ins().iconst(types::I32, 0);
for lane in 0..16 {
let a_lane = a.value_field(fx, mir::Field::new(lane.try_into().unwrap())).load_scalar(fx);
let a_lane_sign = fx.bcx.ins().ushr_imm(a_lane, 7); // extract sign bit of 8bit int
let a_lane_sign = fx.bcx.ins().uextend(types::I32, a_lane_sign);
res = fx.bcx.ins().ishl_imm(res, 1);
res = fx.bcx.ins().bor(res, a_lane_sign);
}
let res = CValue::by_val(res, fx.layout_of(fx.tcx.types.i32));
ret.write_cvalue(fx, res);
};
}
if let Some((_, dest)) = destination {
let ret_ebb = fx.get_ebb(dest);
@ -20,7 +62,6 @@ pub fn codegen_llvm_intrinsic_call<'a, 'tcx: 'a>(
}
}
// llvm.x86.sse2.pmovmskb.128
// llvm.x86.avx2.vperm2i128
// llvm.x86.ssse3.pshuf.b.128
// llvm.x86.avx2.pshuf.b