You can use it directly via the _Builtin_intrinsics.intel module (but note that as an underscored module, this is not formally source stable, though in practice it is unlikely to change). Because Intel has funky types (or lack thereof) for their intrinsics, it's helpful to write a little bit of wrapper code to make it more pleasant to work with:
import _Builtin_intrinsics.intel
@inlinable
func movemask(_ v: SIMD32<Int8>) -> UInt32 {
UInt32(truncatingIfNeeded:
_mm256_movemask_epi8(unsafeBitCast(v, to: __m256i.self))
)
}
With that wrapper in place, we can use it easily:
let v = SIMD32<Int8>.random(in: .min ... .max)
print(v)
print(String(movemask(v), radix: 2))
Compile with avx2 enabled (this is ugly, sorry. Better support for enabling target CPU features is something we need to work on):
Sandbox % swiftc jawn.swift -O -Xcc -Xclang -Xcc -target-feature -Xcc -Xclang -Xcc +avx2
Sandbox % ./jawn
SIMD32<Int8>(-18, -95, 57, 112, 70, -39, 55, -33, 16, -57, -118, 42, 106, -101, 93, 28, -68, 72, -102, -18, 36, -46, 96, -6, 87, 123, -26, 117, 68, 46, 76, 122)
100101011010010011010100011
Note that for the most common simple uses of movemask (is any element set / clear, etc) you can also use the any / all functions and avoid all of this:
let v = SIMD32<Int8>.random(in: .min ... .max)
if any(v .< 0) { print("v contains a negative number.") }