Skip to content

Commit a1f5cd2

Browse files
authored
Make mask types opaque (linebender#218)
This is necessary for eventual AVX-512 support. Part of linebender#179. This does not add any AVX-512 stuff yet, just lays the groundwork by abstracting away the internal representation. Contrary to what the description of linebender#196 said, we don't actually need i64 vectors in the public API so long as we're not providing direct conversions between mask types and integer vector types, which aren't available even on main. Summary of changes: - Add `SimdMask<S>` trait independent from `SimdBase<S>`. - Remove integer-vector-style APIs from masks: - `Deref` - Indexing - `Bytes` - public `SimdSplit` / `SimdCombine` - public `slide` / `slide_within_blocks` - public byte conversions - Remove scalar bit-op overloads for masks, so masks support mask-to-mask `& | ^ !` but not `mask & -1`. This was extricated from a larger changeset I had locally that also added some std::simd API compatibility functions, but that was getting too complicated to review. I'm happy to add more APIs if there's desire and review capacity for them. A port of vello to this API can be found [here]( https://github.com/linebender/vello/compare/main...Shnatsel:opaque-masks?expand=1).
1 parent 12523a6 commit a1f5cd2

22 files changed

Lines changed: 1847 additions & 8039 deletions

File tree

fearless_simd/src/generated/avx2.rs

Lines changed: 58 additions & 970 deletions
Large diffs are not rendered by default.

fearless_simd/src/generated/fallback.rs

Lines changed: 679 additions & 1091 deletions
Large diffs are not rendered by default.

fearless_simd/src/generated/neon.rs

Lines changed: 32 additions & 1156 deletions
Large diffs are not rendered by default.

fearless_simd/src/generated/ops.rs

Lines changed: 0 additions & 720 deletions
Large diffs are not rendered by default.

fearless_simd/src/generated/simd_trait.rs

Lines changed: 316 additions & 588 deletions
Large diffs are not rendered by default.

fearless_simd/src/generated/simd_types.rs

Lines changed: 183 additions & 1163 deletions
Large diffs are not rendered by default.

fearless_simd/src/generated/sse4_2.rs

Lines changed: 39 additions & 931 deletions
Large diffs are not rendered by default.

fearless_simd/src/generated/wasm.rs

Lines changed: 23 additions & 923 deletions
Large diffs are not rendered by default.

fearless_simd/src/traits.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ use crate::{Level, Simd, SimdBase, seal::Seal};
99

1010
/// Element-wise selection between two SIMD vectors using `self`.
1111
pub trait Select<T: Seal>: Seal {
12-
/// For each element of this mask, select the first operand if the element is all ones, and select the second
13-
/// operand if the element is all zeroes.
12+
/// For each logical lane of this mask, select the first operand if the lane is true, and select the second
13+
/// operand if the lane is false.
1414
///
15-
/// If a mask element is *not* all ones or all zeroes, the result is unspecified. It may vary depending on
16-
/// architecture, feature level, the mask elements' width, the mask vector's width, or library version.
15+
/// Masks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those
16+
/// conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).
17+
/// If a mask is constructed from any other integer bit pattern, the result of this operation is unspecified.
1718
fn select(self, if_true: T, if_false: T) -> T;
1819
}
1920

fearless_simd_gen/src/generic.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,19 @@ pub(crate) fn generic_op_name(op: &str, ty: &VecType) -> Ident {
1313
Ident::new(&format!("{op}_{}", ty.rust_name()), Span::call_site())
1414
}
1515

16+
/// For backends that store masks as all-zero/all-one integer lanes, convert the public
17+
/// `bool` mask splat argument into the backend's lane representation.
18+
pub(crate) fn integer_lane_mask_splat_arg(vec_ty: &VecType) -> TokenStream {
19+
if vec_ty.scalar != ScalarType::Mask {
20+
return TokenStream::new();
21+
}
22+
23+
let scalar = vec_ty.scalar.rust(vec_ty.scalar_bits);
24+
quote! {
25+
let val: #scalar = if val { !0 } else { 0 };
26+
}
27+
}
28+
1629
/// Implementation based on split/combine
1730
///
1831
/// Only suitable for lane-wise and block-wise operations

0 commit comments

Comments
 (0)