@@ -2,72 +2,103 @@ use std::hint::black_box;
22use std:: time:: Duration ;
33
44use 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 } ;
77
88/// Benchmark with this many items to get a variety
99const BENCH_ITER_ITEMS : usize = if cfg ! ( feature = "short-benchmarks" ) { 50 } else { 500 } ;
1010
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+
1118macro_rules! musl_rand_benches {
1219 (
1320 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,
2021 fn_extra: $skip_on_i586: expr,
2122 ) => {
2223 paste:: paste! {
2324 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 ;
3126
32- // Perform a sanity check that we are benchmarking the same thing
33- // Don't test against musl if it is not available
3427 #[ 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+ }
3844
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+ }
4267
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 ) ;
4570
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+ }
4973
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
5176
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 */
5978
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) ;
6885 }
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+ }
71102}
72103
73104libm_macros:: for_each_function! {
@@ -83,12 +114,6 @@ libm_macros::for_each_function! {
83114macro_rules! run_callback {
84115 (
85116 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,
92117 extra: [ $criterion: ident] ,
93118 ) => {
94119 paste:: paste! {
0 commit comments