]> git.lizzy.rs Git - rust.git/commitdiff
Emulate llvm.x86.sse2.pmovmskb.128 llvm intrinsic
authorbjorn3 <bjorn3@users.noreply.github.com>
Mon, 29 Jul 2019 10:43:24 +0000 (12:43 +0200)
committerbjorn3 <bjorn3@users.noreply.github.com>
Mon, 29 Jul 2019 10:43:24 +0000 (12:43 +0200)
src/intrinsics.rs
src/llvm_intrinsics.rs

index 251299dcdbe5539869bdcebc559f32954000f89f..042a09347092c7eb8aa4dbdf27e769923d47702f 100644 (file)
@@ -2,42 +2,50 @@
 
 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) {
index 1ffd43bb7808f6814f8cee62d656d95f241c4569..bb99329841150404c4521edca1ce57e599af4ec3 100644 (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