Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add all_lane_counts feature to enable non-power-of-2 lane counts <= 64 #300

Merged
merged 1 commit into from
Aug 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,10 @@ jobs:
- "--features std"
- "--features generic_const_exprs"
- "--features std --features generic_const_exprs"
- "--features all_lane_counts"
- "--features all_lane_counts --features std"
- "--features all_lane_counts --features generic_const_exprs"
- "--features all_lane_counts --features std --features generic_const_exprs"

steps:
- uses: actions/checkout@v2
Expand Down
1 change: 1 addition & 0 deletions crates/core_simd/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ default = ["as_crate"]
as_crate = []
std = []
generic_const_exprs = []
all_lane_counts = []

[target.'cfg(target_arch = "wasm32")'.dev-dependencies.wasm-bindgen]
version = "0.2"
Expand Down
36 changes: 16 additions & 20 deletions crates/core_simd/src/lane_count.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,20 @@ pub trait SupportedLaneCount: Sealed {

impl<const LANES: usize> Sealed for LaneCount<LANES> {}

impl SupportedLaneCount for LaneCount<1> {
type BitMask = [u8; 1];
}
impl SupportedLaneCount for LaneCount<2> {
type BitMask = [u8; 1];
}
impl SupportedLaneCount for LaneCount<4> {
type BitMask = [u8; 1];
}
impl SupportedLaneCount for LaneCount<8> {
type BitMask = [u8; 1];
}
impl SupportedLaneCount for LaneCount<16> {
type BitMask = [u8; 2];
}
impl SupportedLaneCount for LaneCount<32> {
type BitMask = [u8; 4];
}
impl SupportedLaneCount for LaneCount<64> {
type BitMask = [u8; 8];
macro_rules! supported_lane_count {
($($lanes:literal),+) => {
$(
impl SupportedLaneCount for LaneCount<$lanes> {
type BitMask = [u8; ($lanes + 7) / 8];
}
)+
};
}

supported_lane_count!(1, 2, 4, 8, 16, 32, 64);
#[cfg(feature = "all_lane_counts")]
supported_lane_count!(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some sort of const generics would be really nice here, I guess we need bounds first. This is pretty clean though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could just implement them for all usize values using a const generic impl, but iirc @workingjubilee specifically wanted to avoid 0.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'm on the fence about 0. But more than that, LLVM has had issues with larger values in the past, and rustc also has an upper limit on #[repr(simd)], so we need an upper limit anyway.

3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63
);
3 changes: 3 additions & 0 deletions crates/test_helpers/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ publish = false
version = "0.10"
default-features = false
features = ["alloc"]

[features]
all_lane_counts = []
279 changes: 197 additions & 82 deletions crates/test_helpers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,39 @@ pub fn test_ternary_elementwise<
);
}

#[doc(hidden)]
#[macro_export]
macro_rules! test_lanes_helper {
($($(#[$meta:meta])* $fn_name:ident $lanes:literal;)+) => {
$(
#[test]
$(#[$meta])*
fn $fn_name() {
implementation::<$lanes>();
}
)+
};
(
$(#[$meta:meta])+;
$($(#[$meta_before:meta])+ $fn_name_before:ident $lanes_before:literal;)*
$fn_name:ident $lanes:literal;
$($fn_name_rest:ident $lanes_rest:literal;)*
) => {
$crate::test_lanes_helper!(
$(#[$meta])+;
$($(#[$meta_before])+ $fn_name_before $lanes_before;)*
$(#[$meta])+ $fn_name $lanes;
$($fn_name_rest $lanes_rest;)*
);
};
(
$(#[$meta_ignored:meta])+;
$($(#[$meta:meta])+ $fn_name:ident $lanes:literal;)+
) => {
$crate::test_lanes_helper!($($(#[$meta])+ $fn_name $lanes;)+);
};
}

/// Expand a const-generic test into separate tests for each possible lane count.
#[macro_export]
macro_rules! test_lanes {
Expand All @@ -351,51 +384,90 @@ macro_rules! test_lanes {
#[cfg(target_arch = "wasm32")]
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
fn lanes_1() {
implementation::<1>();
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
fn lanes_2() {
implementation::<2>();
}
$crate::test_lanes_helper!(
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)];
lanes_1 1;
lanes_2 2;
lanes_4 4;
);

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
fn lanes_4() {
implementation::<4>();
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[cfg(not(miri))] // Miri intrinsic implementations are uniform and larger tests are sloooow
fn lanes_8() {
implementation::<8>();
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[cfg(not(miri))] // Miri intrinsic implementations are uniform and larger tests are sloooow
fn lanes_16() {
implementation::<16>();
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
$crate::test_lanes_helper!(
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)];
lanes_8 8;
lanes_16 16;
lanes_32 32;
lanes_64 64;
);

#[cfg(feature = "all_lane_counts")]
$crate::test_lanes_helper!(
// test some odd and even non-power-of-2 lengths on miri
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)];
lanes_3 3;
lanes_5 5;
lanes_6 6;
);

#[cfg(feature = "all_lane_counts")]
#[cfg(not(miri))] // Miri intrinsic implementations are uniform and larger tests are sloooow
fn lanes_32() {
implementation::<32>();
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[cfg(not(miri))] // Miri intrinsic implementations are uniform and larger tests are sloooow
fn lanes_64() {
implementation::<64>();
}
$crate::test_lanes_helper!(
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)];
lanes_7 7;
lanes_9 9;
lanes_10 10;
lanes_11 11;
lanes_12 12;
lanes_13 13;
lanes_14 14;
lanes_15 15;
lanes_17 17;
lanes_18 18;
lanes_19 19;
lanes_20 20;
lanes_21 21;
lanes_22 22;
lanes_23 23;
lanes_24 24;
lanes_25 25;
lanes_26 26;
lanes_27 27;
lanes_28 28;
lanes_29 29;
lanes_30 30;
lanes_31 31;
lanes_33 33;
lanes_34 34;
lanes_35 35;
lanes_36 36;
lanes_37 37;
lanes_38 38;
lanes_39 39;
lanes_40 40;
lanes_41 41;
lanes_42 42;
lanes_43 43;
lanes_44 44;
lanes_45 45;
lanes_46 46;
lanes_47 47;
lanes_48 48;
lanes_49 49;
lanes_50 50;
lanes_51 51;
lanes_52 52;
lanes_53 53;
lanes_54 54;
lanes_55 55;
lanes_56 56;
lanes_57 57;
lanes_58 58;
lanes_59 59;
lanes_60 60;
lanes_61 61;
lanes_62 62;
lanes_63 63;
calebzulawski marked this conversation as resolved.
Show resolved Hide resolved
);
}
)*
}
Expand All @@ -416,47 +488,90 @@ macro_rules! test_lanes_panic {
core_simd::LaneCount<$lanes>: core_simd::SupportedLaneCount,
$body

#[test]
#[should_panic]
fn lanes_1() {
implementation::<1>();
}

#[test]
#[should_panic]
fn lanes_2() {
implementation::<2>();
}

#[test]
#[should_panic]
fn lanes_4() {
implementation::<4>();
}

#[test]
#[should_panic]
fn lanes_8() {
implementation::<8>();
}

#[test]
#[should_panic]
fn lanes_16() {
implementation::<16>();
}

#[test]
#[should_panic]
fn lanes_32() {
implementation::<32>();
}
$crate::test_lanes_helper!(
#[should_panic];
lanes_1 1;
lanes_2 2;
lanes_4 4;
);

#[test]
#[should_panic]
fn lanes_64() {
implementation::<64>();
}
#[cfg(not(miri))] // Miri intrinsic implementations are uniform and larger tests are sloooow
$crate::test_lanes_helper!(
#[should_panic];
lanes_8 8;
lanes_16 16;
lanes_32 32;
lanes_64 64;
);

#[cfg(feature = "all_lane_counts")]
$crate::test_lanes_helper!(
// test some odd and even non-power-of-2 lengths on miri
#[should_panic];
lanes_3 3;
lanes_5 5;
lanes_6 6;
);

#[cfg(feature = "all_lane_counts")]
#[cfg(not(miri))] // Miri intrinsic implementations are uniform and larger tests are sloooow
$crate::test_lanes_helper!(
#[should_panic];
lanes_7 7;
lanes_9 9;
lanes_10 10;
lanes_11 11;
lanes_12 12;
lanes_13 13;
lanes_14 14;
lanes_15 15;
lanes_17 17;
lanes_18 18;
lanes_19 19;
lanes_20 20;
lanes_21 21;
lanes_22 22;
lanes_23 23;
lanes_24 24;
lanes_25 25;
lanes_26 26;
lanes_27 27;
lanes_28 28;
lanes_29 29;
lanes_30 30;
lanes_31 31;
lanes_33 33;
lanes_34 34;
lanes_35 35;
lanes_36 36;
lanes_37 37;
lanes_38 38;
lanes_39 39;
lanes_40 40;
lanes_41 41;
lanes_42 42;
lanes_43 43;
lanes_44 44;
lanes_45 45;
lanes_46 46;
lanes_47 47;
lanes_48 48;
lanes_49 49;
lanes_50 50;
lanes_51 51;
lanes_52 52;
lanes_53 53;
lanes_54 54;
lanes_55 55;
lanes_56 56;
lanes_57 57;
lanes_58 58;
lanes_59 59;
lanes_60 60;
lanes_61 61;
lanes_62 62;
lanes_63 63;
);
}
)*
}
Expand Down