@@ -45,7 +45,8 @@ use std::sync::{LazyLock, OnceLock};
4545/// attribute, which requires functions to be marked as unsafe. A safe fallback version will always
4646/// be generated.
4747///
48- /// See [`crate::md5`] as an example.
48+ /// See [`crate::md5`] as an example. [`multiversion_test!`](crate::multiversion_test!) can be used
49+ /// for testing multiversioned libraries.
4950#[ macro_export]
5051macro_rules! multiversion {
5152 // One dynamic dispatch function, optionally with extra helper functions.
@@ -223,11 +224,17 @@ macro_rules! multiversion {
223224 ( @helper $t: meta $( #[ $m: meta] ) * $v: vis fn $n: ident $t0: tt $t1: tt $t2: tt $t3: tt $t4: tt $t5: tt $t6: tt $t7: tt $t8: tt $t9: tt $t10: tt $t11: tt $t12: tt $t13: tt $t14: tt $t15: tt $t16: tt $t17: tt $t18: tt $t19: tt $t20: tt $t21: tt $t22: tt $t23: tt $t24: tt $t25: tt $t26: tt $t27: tt $t28: tt $t29: tt $t30: tt $t31: tt $b: block $( $tail: tt) * ) => { $( #[ $m] ) * #[ $t] $v unsafe fn $n $t0 $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 $t21 $t22 $t23 $t24 $t25 $t26 $t27 $t28 $t29 $t30 $t31 { #[ allow( clippy:: allow_attributes, clippy:: macro_metavars_in_unsafe, unused_unsafe) ] unsafe { $b } } $crate:: multiversion!{ @helper $t $( $tail) * } } ;
224225}
225226
226- /// Helper for testing [`multiversion!`] library functions.
227+ /// Helper for testing and benchmarking [`multiversion!`] library functions.
227228///
228- /// `#[target_feature(...)]` isn't applied to the test functions as the feature-specific code should
229+ /// The first rule is for testing and creates individual
230+ /// [`#[test]`](https://doc.rust-lang.org/reference/attributes/testing.html) functions for each
231+ /// implementation.
232+ ///
233+ /// The second rule is more general, duplicating the same expression for each implementation and
234+ /// is useful for benchmarking.
235+ ///
236+ /// `#[target_feature(...)]` isn't applied to the test code as the feature-specific code should
229237/// be elsewhere, inside a [`multiversion!`] macro.
230- #[ cfg( test) ]
231238#[ macro_export]
232239macro_rules! multiversion_test {
233240 (
@@ -286,7 +293,7 @@ macro_rules! multiversion_test {
286293 #[ allow( clippy:: allow_attributes, unused_imports, clippy:: wildcard_imports) ]
287294 use { $( $( $path:: ) +avx2:: * ) ,* } ;
288295
289- if !std :: arch :: is_x86_feature_detected! ( "avx2" ) {
296+ if !$crate :: multiversion :: Version :: AVX2 . supported ( ) {
290297 use std:: io:: { stdout, Write } ;
291298 let _ = writeln!( & mut stdout( ) , "warning: skipping test in {}::avx2 due to missing avx2 support" , module_path!( ) ) ;
292299 return ;
@@ -295,6 +302,59 @@ macro_rules! multiversion_test {
295302 unsafe { $body }
296303 }
297304 } ;
305+
306+ (
307+ use { $( $( $path: ident:: ) +* ) ,* } ;
308+
309+ { $( $tail: tt) + }
310+ ) => {
311+ #[ allow(
312+ clippy:: reversed_empty_ranges,
313+ clippy:: range_plus_one,
314+ clippy:: modulo_one,
315+ clippy:: trivially_copy_pass_by_ref
316+ ) ]
317+ {
318+ #[ allow( clippy:: allow_attributes, unused_imports, clippy:: wildcard_imports) ]
319+ use { $( $( $path:: ) +scalar:: * ) ,* } ;
320+
321+ $crate:: multiversion_test!( @expr { $( $tail) + } ) ;
322+ }
323+
324+ {
325+ #[ allow( clippy:: allow_attributes, unused_imports, clippy:: wildcard_imports) ]
326+ use { $( $( $path:: ) +array128:: * ) ,* } ;
327+
328+ $crate:: multiversion_test!( @expr { $( $tail) + } ) ;
329+ }
330+
331+ {
332+ #[ allow( clippy:: allow_attributes, unused_imports, clippy:: wildcard_imports) ]
333+ use { $( $( $path:: ) +array256:: * ) ,* } ;
334+
335+ $crate:: multiversion_test!( @expr { $( $tail) + } ) ;
336+ }
337+
338+ #[ cfg( not( target_family = "wasm" ) ) ]
339+ #[ allow( clippy:: large_types_passed_by_value) ]
340+ {
341+ #[ allow( clippy:: allow_attributes, unused_imports, clippy:: wildcard_imports) ]
342+ use { $( $( $path:: ) +array4096:: * ) ,* } ;
343+
344+ $crate:: multiversion_test!( @expr { $( $tail) + } ) ;
345+ }
346+
347+ #[ cfg( all( feature="unsafe" , any( target_arch = "x86" , target_arch = "x86_64" ) ) ) ]
348+ if $crate:: multiversion:: Version :: AVX2 . supported( ) {
349+ unsafe {
350+ #[ allow( clippy:: allow_attributes, unused_imports, clippy:: wildcard_imports) ]
351+ use { $( $( $path:: ) +avx2:: * ) ,* } ;
352+
353+ $crate:: multiversion_test!( @expr { $( $tail) + } ) ;
354+ }
355+ }
356+ } ;
357+ ( @expr $e: expr) => { $e }
298358}
299359
300360macro_rules! versions_impl {
0 commit comments