@@ -2,72 +2,103 @@ use std::hint::black_box;
2
2
use std:: time:: Duration ;
3
3
4
4
use criterion:: { Criterion , criterion_main} ;
5
- use libm_test:: gen:: random;
6
- use libm_test:: { CheckBasis , CheckCtx , TupleCall } ;
5
+ use libm_test:: gen:: { CachedInput , random} ;
6
+ use libm_test:: { CheckBasis , CheckCtx , GenerateInput , MathOp , TupleCall } ;
7
7
8
8
/// Benchmark with this many items to get a variety
9
9
const BENCH_ITER_ITEMS : usize = if cfg ! ( feature = "short-benchmarks" ) { 50 } else { 500 } ;
10
10
11
+ /// Extra parameters we only care about if we are benchmarking against musl.
12
+ #[ allow( dead_code) ]
13
+ struct MuslExtra < F > {
14
+ musl_fn : Option < F > ,
15
+ skip_on_i586 : bool ,
16
+ }
17
+
11
18
macro_rules! musl_rand_benches {
12
19
(
13
20
fn_name: $fn_name: ident,
14
- CFn : $CFn: ty,
15
- CArgs : $CArgs: ty,
16
- CRet : $CRet: ty,
17
- RustFn : $RustFn: ty,
18
- RustArgs : $RustArgs: ty,
19
- RustRet : $RustRet: ty,
20
21
fn_extra: $skip_on_i586: expr,
21
22
) => {
22
23
paste:: paste! {
23
24
fn [ < musl_bench_ $fn_name >] ( c: & mut Criterion ) {
24
- let fn_name = stringify!( $fn_name) ;
25
-
26
- let ulp = libm_test:: musl_allowed_ulp( fn_name) ;
27
- let ctx = CheckCtx :: new( ulp, fn_name, CheckBasis :: Musl ) ;
28
- let benchvec: Vec <_> = random:: get_test_cases:: <$RustArgs>( & ctx)
29
- . take( BENCH_ITER_ITEMS )
30
- . collect( ) ;
25
+ type Op = libm_test:: op:: $fn_name:: Routine ;
31
26
32
- // Perform a sanity check that we are benchmarking the same thing
33
- // Don't test against musl if it is not available
34
27
#[ cfg( feature = "build-musl" ) ]
35
- for input in benchvec. iter( ) . copied( ) {
36
- use anyhow:: Context ;
37
- use libm_test:: { CheckBasis , CheckCtx , CheckOutput } ;
28
+ let musl_extra = MuslExtra {
29
+ musl_fn: Some ( musl_math_sys:: $fn_name as <Op as MathOp >:: CFn ) ,
30
+ skip_on_i586: $skip_on_i586
31
+ } ;
32
+
33
+ #[ cfg( not( feature = "build-musl" ) ) ]
34
+ let musl_extra = MuslExtra {
35
+ musl_fn: None ,
36
+ skip_on_i586: $skip_on_i586
37
+ } ;
38
+
39
+ bench_one:: <Op >( c, musl_extra) ;
40
+ }
41
+ }
42
+ } ;
43
+ }
38
44
39
- if cfg!( x86_no_sse) && $skip_on_i586 {
40
- break ;
41
- }
45
+ fn bench_one < Op > ( c : & mut Criterion , musl_extra : MuslExtra < Op :: CFn > )
46
+ where
47
+ Op : MathOp ,
48
+ CachedInput : GenerateInput < Op :: RustArgs > ,
49
+ {
50
+ let name = Op :: NAME_STR ;
51
+
52
+ let ulp = libm_test:: musl_allowed_ulp ( name) ;
53
+ let ctx = CheckCtx :: new ( ulp, name, CheckBasis :: Musl ) ;
54
+ let benchvec: Vec < _ > =
55
+ random:: get_test_cases :: < Op :: RustArgs > ( & ctx) . take ( BENCH_ITER_ITEMS ) . collect ( ) ;
56
+
57
+ // Perform a sanity check that we are benchmarking the same thing
58
+ // Don't test against musl if it is not available
59
+ #[ cfg( feature = "build-musl" ) ]
60
+ for input in benchvec. iter ( ) . copied ( ) {
61
+ use anyhow:: Context ;
62
+ use libm_test:: CheckOutput ;
63
+
64
+ if cfg ! ( x86_no_sse) && musl_extra. skip_on_i586 {
65
+ break ;
66
+ }
42
67
43
- let musl_res = input. call( musl_math_sys :: $fn_name as $CFn ) ;
44
- let crate_res = input. call( libm :: $fn_name as $RustFn ) ;
68
+ let musl_res = input. call ( musl_extra . musl_fn . unwrap ( ) ) ;
69
+ let crate_res = input. call ( Op :: ROUTINE ) ;
45
70
46
- let ctx = CheckCtx :: new( ulp, fn_name, CheckBasis :: Musl ) ;
47
- crate_res. validate( musl_res, input, & ctx) . context( fn_name) . unwrap( ) ;
48
- }
71
+ crate_res. validate ( musl_res, input, & ctx) . context ( name) . unwrap ( ) ;
72
+ }
49
73
50
- /* Function pointers are black boxed to avoid inlining in the benchmark loop */
74
+ #[ cfg( not( feature = "build-musl" ) ) ]
75
+ let _ = musl_extra; // silence unused warnings
51
76
52
- let mut group = c. benchmark_group( fn_name) ;
53
- group. bench_function( "crate" , |b| b. iter( || {
54
- let f = black_box( libm:: $fn_name as $RustFn) ;
55
- for input in benchvec. iter( ) . copied( ) {
56
- input. call( f) ;
57
- }
58
- } ) ) ;
77
+ /* Option pointers are black boxed to avoid inlining in the benchmark loop */
59
78
60
- // Don't test against musl if it is not available
61
- #[ cfg( feature = "build-musl" ) ]
62
- group. bench_function( "musl" , |b| b. iter( || {
63
- let f = black_box( musl_math_sys:: $fn_name as $CFn) ;
64
- for input in benchvec. iter( ) . copied( ) {
65
- input. call( f) ;
66
- }
67
- } ) ) ;
79
+ let mut group = c. benchmark_group ( name) ;
80
+ group. bench_function ( "crate" , |b| {
81
+ b. iter ( || {
82
+ let f = black_box ( Op :: ROUTINE ) ;
83
+ for input in benchvec. iter ( ) . copied ( ) {
84
+ input. call ( f) ;
68
85
}
69
- }
70
- } ;
86
+ } )
87
+ } ) ;
88
+
89
+ // Don't test against musl if it is not available
90
+ #[ cfg( feature = "build-musl" ) ]
91
+ {
92
+ let musl_fn = musl_extra. musl_fn . unwrap ( ) ;
93
+ group. bench_function ( "musl" , |b| {
94
+ b. iter ( || {
95
+ let f = black_box ( musl_fn) ;
96
+ for input in benchvec. iter ( ) . copied ( ) {
97
+ input. call ( f) ;
98
+ }
99
+ } )
100
+ } ) ;
101
+ }
71
102
}
72
103
73
104
libm_macros:: for_each_function! {
@@ -83,12 +114,6 @@ libm_macros::for_each_function! {
83
114
macro_rules! run_callback {
84
115
(
85
116
fn_name: $fn_name: ident,
86
- CFn : $_CFn: ty,
87
- CArgs : $_CArgs: ty,
88
- CRet : $_CRet: ty,
89
- RustFn : $_RustFn: ty,
90
- RustArgs : $_RustArgs: ty,
91
- RustRet : $_RustRet: ty,
92
117
extra: [ $criterion: ident] ,
93
118
) => {
94
119
paste:: paste! {
0 commit comments