Skip to content

Commit 5cccb41

Browse files
authored
Implement swizzle_dyn_within_blocks, add tests (#266)
This addresses my criticism of #265 This maps to cheap hardware instructions on x86 and also maps really well to split+combine on blocks on NEON and WASM, so unlike #265 this can be implemented for all widths. The API follows the `std::simd` [`swizzle_dyn`](https://doc.rust-lang.org/stable/std/simd/struct.Simd.html#method.swizzle_dyn), which uses byte-level index vectors. This also makes the implementation really straightforward, since everything is treated as byte vectors internally, so it's implemented for all types too. The scalar fallback is branch-free thanks to `% len` which should be faster than the branchy fallback in #265 and also more amenable to autovectorization on obscure platforms we don't have intrinsics for.
1 parent 57d06a7 commit 5cccb41

17 files changed

Lines changed: 3001 additions & 1 deletion

File tree

fearless_simd/src/generated/avx2.rs

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

fearless_simd/src/generated/avx512.rs

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

fearless_simd/src/generated/fallback.rs

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

fearless_simd/src/generated/neon.rs

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

fearless_simd/src/generated/simd_trait.rs

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

fearless_simd/src/generated/simd_types.rs

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,11 @@ impl<S: Simd> SimdBase<S> for f32x4<S> {
130130
self.simd
131131
.slide_within_blocks_f32x4::<SHIFT>(self, rhs.simd_into(self.simd))
132132
}
133+
#[inline(always)]
134+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
135+
self.simd
136+
.swizzle_dyn_within_blocks_f32x4(self, indices.simd_into(self.simd))
137+
}
133138
}
134139
impl<S: Simd> crate::SimdFloat<S> for f32x4<S> {
135140
#[inline(always)]
@@ -383,6 +388,11 @@ impl<S: Simd> SimdBase<S> for i8x16<S> {
383388
self.simd
384389
.slide_within_blocks_i8x16::<SHIFT>(self, rhs.simd_into(self.simd))
385390
}
391+
#[inline(always)]
392+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
393+
self.simd
394+
.swizzle_dyn_within_blocks_i8x16(self, indices.simd_into(self.simd))
395+
}
386396
}
387397
impl<S: Simd> crate::SimdInt<S> for i8x16<S> {
388398
#[inline(always)]
@@ -568,6 +578,11 @@ impl<S: Simd> SimdBase<S> for u8x16<S> {
568578
self.simd
569579
.slide_within_blocks_u8x16::<SHIFT>(self, rhs.simd_into(self.simd))
570580
}
581+
#[inline(always)]
582+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
583+
self.simd
584+
.swizzle_dyn_within_blocks_u8x16(self, indices.simd_into(self.simd))
585+
}
571586
}
572587
impl<S: Simd> crate::SimdInt<S> for u8x16<S> {
573588
#[inline(always)]
@@ -844,6 +859,11 @@ impl<S: Simd> SimdBase<S> for i16x8<S> {
844859
self.simd
845860
.slide_within_blocks_i16x8::<SHIFT>(self, rhs.simd_into(self.simd))
846861
}
862+
#[inline(always)]
863+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
864+
self.simd
865+
.swizzle_dyn_within_blocks_i16x8(self, indices.simd_into(self.simd))
866+
}
847867
}
848868
impl<S: Simd> crate::SimdInt<S> for i16x8<S> {
849869
#[inline(always)]
@@ -1029,6 +1049,11 @@ impl<S: Simd> SimdBase<S> for u16x8<S> {
10291049
self.simd
10301050
.slide_within_blocks_u16x8::<SHIFT>(self, rhs.simd_into(self.simd))
10311051
}
1052+
#[inline(always)]
1053+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
1054+
self.simd
1055+
.swizzle_dyn_within_blocks_u16x8(self, indices.simd_into(self.simd))
1056+
}
10321057
}
10331058
impl<S: Simd> crate::SimdInt<S> for u16x8<S> {
10341059
#[inline(always)]
@@ -1305,6 +1330,11 @@ impl<S: Simd> SimdBase<S> for i32x4<S> {
13051330
self.simd
13061331
.slide_within_blocks_i32x4::<SHIFT>(self, rhs.simd_into(self.simd))
13071332
}
1333+
#[inline(always)]
1334+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
1335+
self.simd
1336+
.swizzle_dyn_within_blocks_i32x4(self, indices.simd_into(self.simd))
1337+
}
13081338
}
13091339
impl<S: Simd> crate::SimdInt<S> for i32x4<S> {
13101340
#[inline(always)]
@@ -1502,6 +1532,11 @@ impl<S: Simd> SimdBase<S> for u32x4<S> {
15021532
self.simd
15031533
.slide_within_blocks_u32x4::<SHIFT>(self, rhs.simd_into(self.simd))
15041534
}
1535+
#[inline(always)]
1536+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
1537+
self.simd
1538+
.swizzle_dyn_within_blocks_u32x4(self, indices.simd_into(self.simd))
1539+
}
15051540
}
15061541
impl<S: Simd> crate::SimdInt<S> for u32x4<S> {
15071542
#[inline(always)]
@@ -1790,6 +1825,11 @@ impl<S: Simd> SimdBase<S> for f64x2<S> {
17901825
self.simd
17911826
.slide_within_blocks_f64x2::<SHIFT>(self, rhs.simd_into(self.simd))
17921827
}
1828+
#[inline(always)]
1829+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
1830+
self.simd
1831+
.swizzle_dyn_within_blocks_f64x2(self, indices.simd_into(self.simd))
1832+
}
17931833
}
17941834
impl<S: Simd> crate::SimdFloat<S> for f64x2<S> {
17951835
#[inline(always)]
@@ -2120,6 +2160,11 @@ impl<S: Simd> SimdBase<S> for f32x8<S> {
21202160
self.simd
21212161
.slide_within_blocks_f32x8::<SHIFT>(self, rhs.simd_into(self.simd))
21222162
}
2163+
#[inline(always)]
2164+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
2165+
self.simd
2166+
.swizzle_dyn_within_blocks_f32x8(self, indices.simd_into(self.simd))
2167+
}
21232168
}
21242169
impl<S: Simd> crate::SimdFloat<S> for f32x8<S> {
21252170
#[inline(always)]
@@ -2380,6 +2425,11 @@ impl<S: Simd> SimdBase<S> for i8x32<S> {
23802425
self.simd
23812426
.slide_within_blocks_i8x32::<SHIFT>(self, rhs.simd_into(self.simd))
23822427
}
2428+
#[inline(always)]
2429+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
2430+
self.simd
2431+
.swizzle_dyn_within_blocks_i8x32(self, indices.simd_into(self.simd))
2432+
}
23832433
}
23842434
impl<S: Simd> crate::SimdInt<S> for i8x32<S> {
23852435
#[inline(always)]
@@ -2572,6 +2622,11 @@ impl<S: Simd> SimdBase<S> for u8x32<S> {
25722622
self.simd
25732623
.slide_within_blocks_u8x32::<SHIFT>(self, rhs.simd_into(self.simd))
25742624
}
2625+
#[inline(always)]
2626+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
2627+
self.simd
2628+
.swizzle_dyn_within_blocks_u8x32(self, indices.simd_into(self.simd))
2629+
}
25752630
}
25762631
impl<S: Simd> crate::SimdInt<S> for u8x32<S> {
25772632
#[inline(always)]
@@ -2860,6 +2915,11 @@ impl<S: Simd> SimdBase<S> for i16x16<S> {
28602915
self.simd
28612916
.slide_within_blocks_i16x16::<SHIFT>(self, rhs.simd_into(self.simd))
28622917
}
2918+
#[inline(always)]
2919+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
2920+
self.simd
2921+
.swizzle_dyn_within_blocks_i16x16(self, indices.simd_into(self.simd))
2922+
}
28632923
}
28642924
impl<S: Simd> crate::SimdInt<S> for i16x16<S> {
28652925
#[inline(always)]
@@ -3058,6 +3118,11 @@ impl<S: Simd> SimdBase<S> for u16x16<S> {
30583118
self.simd
30593119
.slide_within_blocks_u16x16::<SHIFT>(self, rhs.simd_into(self.simd))
30603120
}
3121+
#[inline(always)]
3122+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
3123+
self.simd
3124+
.swizzle_dyn_within_blocks_u16x16(self, indices.simd_into(self.simd))
3125+
}
30613126
}
30623127
impl<S: Simd> crate::SimdInt<S> for u16x16<S> {
30633128
#[inline(always)]
@@ -3342,6 +3407,11 @@ impl<S: Simd> SimdBase<S> for i32x8<S> {
33423407
self.simd
33433408
.slide_within_blocks_i32x8::<SHIFT>(self, rhs.simd_into(self.simd))
33443409
}
3410+
#[inline(always)]
3411+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
3412+
self.simd
3413+
.swizzle_dyn_within_blocks_i32x8(self, indices.simd_into(self.simd))
3414+
}
33453415
}
33463416
impl<S: Simd> crate::SimdInt<S> for i32x8<S> {
33473417
#[inline(always)]
@@ -3546,6 +3616,11 @@ impl<S: Simd> SimdBase<S> for u32x8<S> {
35463616
self.simd
35473617
.slide_within_blocks_u32x8::<SHIFT>(self, rhs.simd_into(self.simd))
35483618
}
3619+
#[inline(always)]
3620+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
3621+
self.simd
3622+
.swizzle_dyn_within_blocks_u32x8(self, indices.simd_into(self.simd))
3623+
}
35493624
}
35503625
impl<S: Simd> crate::SimdInt<S> for u32x8<S> {
35513626
#[inline(always)]
@@ -3841,6 +3916,11 @@ impl<S: Simd> SimdBase<S> for f64x4<S> {
38413916
self.simd
38423917
.slide_within_blocks_f64x4::<SHIFT>(self, rhs.simd_into(self.simd))
38433918
}
3919+
#[inline(always)]
3920+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
3921+
self.simd
3922+
.swizzle_dyn_within_blocks_f64x4(self, indices.simd_into(self.simd))
3923+
}
38443924
}
38453925
impl<S: Simd> crate::SimdFloat<S> for f64x4<S> {
38463926
#[inline(always)]
@@ -4184,6 +4264,11 @@ impl<S: Simd> SimdBase<S> for f32x16<S> {
41844264
self.simd
41854265
.slide_within_blocks_f32x16::<SHIFT>(self, rhs.simd_into(self.simd))
41864266
}
4267+
#[inline(always)]
4268+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
4269+
self.simd
4270+
.swizzle_dyn_within_blocks_f32x16(self, indices.simd_into(self.simd))
4271+
}
41874272
}
41884273
impl<S: Simd> crate::SimdFloat<S> for f32x16<S> {
41894274
#[inline(always)]
@@ -4439,6 +4524,11 @@ impl<S: Simd> SimdBase<S> for i8x64<S> {
44394524
self.simd
44404525
.slide_within_blocks_i8x64::<SHIFT>(self, rhs.simd_into(self.simd))
44414526
}
4527+
#[inline(always)]
4528+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
4529+
self.simd
4530+
.swizzle_dyn_within_blocks_i8x64(self, indices.simd_into(self.simd))
4531+
}
44424532
}
44434533
impl<S: Simd> crate::SimdInt<S> for i8x64<S> {
44444534
#[inline(always)]
@@ -4625,6 +4715,11 @@ impl<S: Simd> SimdBase<S> for u8x64<S> {
46254715
self.simd
46264716
.slide_within_blocks_u8x64::<SHIFT>(self, rhs.simd_into(self.simd))
46274717
}
4718+
#[inline(always)]
4719+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
4720+
self.simd
4721+
.swizzle_dyn_within_blocks_u8x64(self, indices.simd_into(self.simd))
4722+
}
46284723
}
46294724
impl<S: Simd> crate::SimdInt<S> for u8x64<S> {
46304725
#[inline(always)]
@@ -4907,6 +5002,11 @@ impl<S: Simd> SimdBase<S> for i16x32<S> {
49075002
self.simd
49085003
.slide_within_blocks_i16x32::<SHIFT>(self, rhs.simd_into(self.simd))
49095004
}
5005+
#[inline(always)]
5006+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
5007+
self.simd
5008+
.swizzle_dyn_within_blocks_i16x32(self, indices.simd_into(self.simd))
5009+
}
49105010
}
49115011
impl<S: Simd> crate::SimdInt<S> for i16x32<S> {
49125012
#[inline(always)]
@@ -5099,6 +5199,11 @@ impl<S: Simd> SimdBase<S> for u16x32<S> {
50995199
self.simd
51005200
.slide_within_blocks_u16x32::<SHIFT>(self, rhs.simd_into(self.simd))
51015201
}
5202+
#[inline(always)]
5203+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
5204+
self.simd
5205+
.swizzle_dyn_within_blocks_u16x32(self, indices.simd_into(self.simd))
5206+
}
51025207
}
51035208
impl<S: Simd> crate::SimdInt<S> for u16x32<S> {
51045209
#[inline(always)]
@@ -5382,6 +5487,11 @@ impl<S: Simd> SimdBase<S> for i32x16<S> {
53825487
self.simd
53835488
.slide_within_blocks_i32x16::<SHIFT>(self, rhs.simd_into(self.simd))
53845489
}
5490+
#[inline(always)]
5491+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
5492+
self.simd
5493+
.swizzle_dyn_within_blocks_i32x16(self, indices.simd_into(self.simd))
5494+
}
53855495
}
53865496
impl<S: Simd> crate::SimdInt<S> for i32x16<S> {
53875497
#[inline(always)]
@@ -5586,6 +5696,11 @@ impl<S: Simd> SimdBase<S> for u32x16<S> {
55865696
self.simd
55875697
.slide_within_blocks_u32x16::<SHIFT>(self, rhs.simd_into(self.simd))
55885698
}
5699+
#[inline(always)]
5700+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
5701+
self.simd
5702+
.swizzle_dyn_within_blocks_u32x16(self, indices.simd_into(self.simd))
5703+
}
55895704
}
55905705
impl<S: Simd> crate::SimdInt<S> for u32x16<S> {
55915706
#[inline(always)]
@@ -5876,6 +5991,11 @@ impl<S: Simd> SimdBase<S> for f64x8<S> {
58765991
self.simd
58775992
.slide_within_blocks_f64x8::<SHIFT>(self, rhs.simd_into(self.simd))
58785993
}
5994+
#[inline(always)]
5995+
fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self {
5996+
self.simd
5997+
.swizzle_dyn_within_blocks_f64x8(self, indices.simd_into(self.simd))
5998+
}
58795999
}
58806000
impl<S: Simd> crate::SimdFloat<S> for f64x8<S> {
58816001
#[inline(always)]

0 commit comments

Comments
 (0)