Emulate llvm.x86.sse2.pmovmskb.128 llvm intrinsic
This commit is contained in:
parent
9cb787fe70
commit
48a6b581b5
@ -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) {
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user