Skip to main content

zenjxl_decoder_simd/x86_64/
mod.rs

1// Copyright (c) the JPEG XL Project Authors. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style
4// license that can be found in the LICENSE file.
5
6#![allow(clippy::identity_op)]
7
8#[cfg(feature = "avx")]
9pub(super) mod avx;
10#[cfg(feature = "avx512")]
11pub(super) mod avx512;
12#[cfg(feature = "sse42")]
13pub(super) mod sse42;
14
15#[macro_export]
16macro_rules! simd_function {
17    (
18        $dname:ident,
19        $descr:ident: $descr_ty:ident,
20        $(#[$($attr:meta)*])*
21        $pub:vis fn $name:ident($($arg:ident: $ty:ty),* $(,)?) $(-> $ret:ty )? $body: block
22    ) => {
23        #[inline(always)]
24        $(#[$($attr)*])*
25        $pub fn $name<$descr_ty: $crate::SimdDescriptor>($descr: $descr_ty, $($arg: $ty),*) $(-> $ret)? $body
26
27        paste::paste! {
28            #[cfg(all(target_arch = "x86_64", feature = "avx512"))]
29            #[$crate::__arcane]
30            $(#[$($attr)*])*
31            fn [<$dname __v4>](_token: $crate::X64V4Token, $($arg: $ty),*) $(-> $ret)? {
32                $name($crate::Avx512Descriptor::from_token(_token), $($arg),*)
33            }
34
35            #[cfg(all(target_arch = "x86_64", feature = "avx"))]
36            #[$crate::__arcane]
37            $(#[$($attr)*])*
38            fn [<$dname __v3>](_token: $crate::X64V3Token, $($arg: $ty),*) $(-> $ret)? {
39                $name($crate::AvxDescriptor::from_token(_token), $($arg),*)
40            }
41
42            #[cfg(all(target_arch = "x86_64", feature = "sse42"))]
43            #[$crate::__arcane]
44            $(#[$($attr)*])*
45            fn [<$dname __v2>](_token: $crate::X64V2Token, $($arg: $ty),*) $(-> $ret)? {
46                $name($crate::Sse42Descriptor::from_token(_token), $($arg),*)
47            }
48
49            $(#[$($attr)*])*
50            fn [<$dname __scalar>](_token: $crate::ScalarToken, $($arg: $ty),*) $(-> $ret)? {
51                $name($crate::ScalarDescriptor::from_token(_token), $($arg),*)
52            }
53
54            $(#[$($attr)*])*
55            $pub fn $dname($($arg: $ty),*) $(-> $ret)? {
56                use $crate::__SimdToken;
57                #[cfg(all(target_arch = "x86_64", feature = "avx512"))]
58                if let Some(t) = $crate::X64V4Token::summon() {
59                    return [<$dname __v4>](t, $($arg),*);
60                }
61                #[cfg(all(target_arch = "x86_64", feature = "avx"))]
62                if let Some(t) = $crate::X64V3Token::summon() {
63                    return [<$dname __v3>](t, $($arg),*);
64                }
65                #[cfg(all(target_arch = "x86_64", feature = "sse42"))]
66                if let Some(t) = $crate::X64V2Token::summon() {
67                    return [<$dname __v2>](t, $($arg),*);
68                }
69                [<$dname __scalar>]($crate::ScalarToken::summon().unwrap(), $($arg),*)
70            }
71        }
72    };
73}
74
75#[macro_export]
76macro_rules! test_all_instruction_sets {
77    (
78        $name:ident
79    ) => {
80        paste::paste! {
81            #[test]
82            fn [<$name _scalar>]() {
83                use $crate::SimdDescriptor;
84                $name($crate::ScalarDescriptor::new().unwrap())
85            }
86        }
87
88        $crate::test_sse42!($name);
89        $crate::test_avx!($name);
90        $crate::test_avx512!($name);
91    };
92}
93
94#[cfg(feature = "sse42")]
95#[doc(hidden)]
96#[macro_export]
97macro_rules! test_sse42 {
98    ($name:ident) => {
99        paste::paste! {
100            #[test]
101            fn [<$name _sse42>]() {
102                use $crate::__SimdToken;
103                let Some(token) = $crate::X64V2Token::summon() else { return; };
104                #[$crate::__arcane]
105                fn inner(token: $crate::X64V2Token) {
106                    $name($crate::Sse42Descriptor::from_token(token))
107                }
108                inner(token);
109            }
110        }
111    };
112}
113
114#[cfg(feature = "avx")]
115#[doc(hidden)]
116#[macro_export]
117macro_rules! test_avx {
118    ($name:ident) => {
119        paste::paste! {
120            #[test]
121            fn [<$name _avx>]() {
122                use $crate::__SimdToken;
123                let Some(token) = $crate::X64V3Token::summon() else { return; };
124                #[$crate::__arcane]
125                fn inner(token: $crate::X64V3Token) {
126                    $name($crate::AvxDescriptor::from_token(token))
127                }
128                inner(token);
129            }
130        }
131    };
132}
133
134#[cfg(feature = "avx512")]
135#[doc(hidden)]
136#[macro_export]
137macro_rules! test_avx512 {
138    ($name:ident) => {
139        paste::paste! {
140            #[test]
141            fn [<$name _avx512>]() {
142                use $crate::__SimdToken;
143                let Some(token) = $crate::X64V4Token::summon() else { return; };
144                #[$crate::__arcane]
145                fn inner(token: $crate::X64V4Token) {
146                    $name($crate::Avx512Descriptor::from_token(token))
147                }
148                inner(token);
149            }
150        }
151    };
152}
153
154#[cfg(not(feature = "sse42"))]
155#[doc(hidden)]
156#[macro_export]
157macro_rules! test_sse42 {
158    ($name:ident) => {};
159}
160
161#[cfg(not(feature = "avx"))]
162#[doc(hidden)]
163#[macro_export]
164macro_rules! test_avx {
165    ($name:ident) => {};
166}
167
168#[cfg(not(feature = "avx512"))]
169#[doc(hidden)]
170#[macro_export]
171macro_rules! test_avx512 {
172    ($name:ident) => {};
173}
174
175#[macro_export]
176macro_rules! bench_all_instruction_sets {
177    (
178        $name:ident,
179        $criterion:ident
180    ) => {
181        #[allow(unused)]
182        use $crate::SimdDescriptor;
183        $crate::bench_avx512!($name, $criterion);
184        $crate::bench_avx!($name, $criterion);
185        $crate::bench_sse42!($name, $criterion);
186        $name(
187            $crate::ScalarDescriptor::new().unwrap(),
188            $criterion,
189            "scalar",
190        );
191    };
192}
193
194#[cfg(feature = "avx512")]
195#[doc(hidden)]
196#[macro_export]
197macro_rules! bench_avx512 {
198    ($name:ident, $criterion:ident) => {
199        if let Some(d) = $crate::Avx512Descriptor::new() {
200            d.call(|d| $name(d, $criterion, "avx512"));
201        }
202    };
203}
204
205#[cfg(feature = "avx")]
206#[doc(hidden)]
207#[macro_export]
208macro_rules! bench_avx {
209    ($name:ident, $criterion:ident) => {
210        if let Some(d) = $crate::AvxDescriptor::new() {
211            d.call(|d| $name(d, $criterion, "avx"));
212        }
213    };
214}
215
216#[cfg(feature = "sse42")]
217#[doc(hidden)]
218#[macro_export]
219macro_rules! bench_sse42 {
220    ($name:ident, $criterion:ident) => {
221        if let Some(d) = $crate::Sse42Descriptor::new() {
222            d.call(|d| $name(d, $criterion, "sse42"));
223        }
224    };
225}
226
227#[cfg(not(feature = "avx512"))]
228#[doc(hidden)]
229#[macro_export]
230macro_rules! bench_avx512 {
231    ($name:ident, $criterion:ident) => {};
232}
233
234#[cfg(not(feature = "avx"))]
235#[doc(hidden)]
236#[macro_export]
237macro_rules! bench_avx {
238    ($name:ident, $criterion:ident) => {};
239}
240
241#[cfg(not(feature = "sse42"))]
242#[doc(hidden)]
243#[macro_export]
244macro_rules! bench_sse42 {
245    ($name:ident, $criterion:ident) => {};
246}