//! This module contains the LLVM intrinsics bindings that provide the functionality for this //! crate. //! //! The LLVM assembly language is documented here: /// These intrinsics aren't linked directly from LLVM and are mostly undocumented, however they are /// simply lowered to the matching LLVM instructions by the compiler. The associated instruction /// is documented alongside each intrinsic. extern "platform-intrinsic" { /// add/fadd pub(crate) fn simd_add(x: T, y: T) -> T; /// sub/fsub pub(crate) fn simd_sub(x: T, y: T) -> T; /// mul/fmul pub(crate) fn simd_mul(x: T, y: T) -> T; /// udiv/sdiv/fdiv /// ints and uints: {s,u}div incur UB if division by zero occurs. /// ints: sdiv is UB for int::MIN / -1. /// floats: fdiv is never UB, but may create NaNs or infinities. pub(crate) fn simd_div(x: T, y: T) -> T; /// urem/srem/frem /// ints and uints: {s,u}rem incur UB if division by zero occurs. /// ints: srem is UB for int::MIN / -1. /// floats: frem is equivalent to libm::fmod in the "default" floating point environment, sans errno. pub(crate) fn simd_rem(x: T, y: T) -> T; /// shl pub(crate) fn simd_shl(x: T, y: T) -> T; /// lshr/ashr pub(crate) fn simd_shr(x: T, y: T) -> T; /// and pub(crate) fn simd_and(x: T, y: T) -> T; /// or pub(crate) fn simd_or(x: T, y: T) -> T; /// xor pub(crate) fn simd_xor(x: T, y: T) -> T; /// fptoui/fptosi/uitofp/sitofp pub(crate) fn simd_cast(x: T) -> U; /// follows Rust's `T as U` semantics, including saturating float casts /// which amounts to the same as `simd_cast` for many cases #[cfg(not(bootstrap))] pub(crate) fn simd_as(x: T) -> U; /// neg/fneg /// ints: ultimately becomes a call to cg_ssa's BuilderMethods::neg. cg_llvm equates this to `simd_sub(Simd::splat(0), x)`. /// floats: LLVM's fneg, which changes the floating point sign bit. Some arches have instructions for it. /// Rust panics for Neg::neg(int::MIN) due to overflow, but it is not UB in LLVM without `nsw`. pub(crate) fn simd_neg(x: T) -> T; /// fabs pub(crate) fn simd_fabs(x: T) -> T; // minnum/maxnum pub(crate) fn simd_fmin(x: T, y: T) -> T; pub(crate) fn simd_fmax(x: T, y: T) -> T; pub(crate) fn simd_eq(x: T, y: T) -> U; pub(crate) fn simd_ne(x: T, y: T) -> U; pub(crate) fn simd_lt(x: T, y: T) -> U; pub(crate) fn simd_le(x: T, y: T) -> U; pub(crate) fn simd_gt(x: T, y: T) -> U; pub(crate) fn simd_ge(x: T, y: T) -> U; // shufflevector pub(crate) fn simd_shuffle(x: T, y: T, idx: U) -> V; pub(crate) fn simd_gather(val: T, ptr: U, mask: V) -> T; pub(crate) fn simd_scatter(val: T, ptr: U, mask: V); // {s,u}add.sat pub(crate) fn simd_saturating_add(x: T, y: T) -> T; // {s,u}sub.sat pub(crate) fn simd_saturating_sub(x: T, y: T) -> T; // reductions pub(crate) fn simd_reduce_add_ordered(x: T, y: U) -> U; pub(crate) fn simd_reduce_mul_ordered(x: T, y: U) -> U; #[allow(unused)] pub(crate) fn simd_reduce_all(x: T) -> bool; #[allow(unused)] pub(crate) fn simd_reduce_any(x: T) -> bool; pub(crate) fn simd_reduce_max(x: T) -> U; pub(crate) fn simd_reduce_min(x: T) -> U; pub(crate) fn simd_reduce_and(x: T) -> U; pub(crate) fn simd_reduce_or(x: T) -> U; pub(crate) fn simd_reduce_xor(x: T) -> U; // truncate integer vector to bitmask #[allow(unused)] pub(crate) fn simd_bitmask(x: T) -> U; // select pub(crate) fn simd_select(m: M, a: T, b: T) -> T; #[allow(unused)] pub(crate) fn simd_select_bitmask(m: M, a: T, b: T) -> T; }